-
Notifications
You must be signed in to change notification settings - Fork 28
Fixes #2428. Add call
member tests for extension types
#2438
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
61 changes: 61 additions & 0 deletions
61
LanguageFeatures/Extension-types/dynamic_semantics_member_invocation_A02_t05.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
/// @assertion Consider an invocation of the extension type member m on the | ||
/// receiver expression e according to the extension type declaration V with | ||
/// actual type arguments T1, ..., Ts. If the invocation includes an actual | ||
/// argument part (possibly including some actual type arguments) then call it | ||
/// args. If the invocation omits args, but includes a list of actual type | ||
/// arguments then call them typeArgs. Assume that V declares the type variables | ||
/// X1, ..., Xs | ||
/// ... | ||
/// Let Dm be the unique declaration named m that V has. | ||
/// | ||
/// Evaluation of this invocation proceeds by evaluating e to an object o. | ||
/// ... | ||
/// Otherwise, if args is omitted and Dm is a method, the invocation evaluates | ||
/// to a closurization of Dm where this and the name of the representation are | ||
/// bound as with the getter invocation, and the type variables of V are bound | ||
/// to the actual values of T1, .. Ts. The operator == of the closurization | ||
/// returns true if and only if the operand is the same object. | ||
/// | ||
/// @description Check implicit tear-off of a `call` member | ||
/// @author [email protected] | ||
|
||
// SharedOptions=--enable-experiment=inline-class | ||
|
||
import "../../Utils/expect.dart"; | ||
|
||
class C { | ||
String call() => "call from C"; | ||
} | ||
|
||
extension type ET1(Function it) { | ||
String call() => "call from ET1"; | ||
} | ||
|
||
extension type ET2(Function it) implements Object { | ||
String call() => "call from ET2"; | ||
} | ||
|
||
extension type ET3(Function it) { | ||
String call() => it.call(); | ||
} | ||
|
||
String foo() => "call from foo()"; | ||
|
||
Function get functionGetter1 => ET1(C()); | ||
|
||
Function get functionGetter2 => ET2(C()); | ||
|
||
Function get functionGetter3 => ET3(C()); | ||
|
||
Function get functionGetter4 => ET3(foo); | ||
|
||
void main() { | ||
Expect.equals("call from ET1", functionGetter1()); | ||
Expect.equals("call from ET2", functionGetter2()); | ||
Expect.equals("call from C", functionGetter3()); | ||
Expect.equals("call from foo()", functionGetter4()); | ||
} |
50 changes: 50 additions & 0 deletions
50
LanguageFeatures/Extension-types/dynamic_semantics_member_invocation_A02_t06.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
/// @assertion Consider an invocation of the extension type member m on the | ||
/// receiver expression e according to the extension type declaration V with | ||
/// actual type arguments T1, ..., Ts. If the invocation includes an actual | ||
/// argument part (possibly including some actual type arguments) then call it | ||
/// args. If the invocation omits args, but includes a list of actual type | ||
/// arguments then call them typeArgs. Assume that V declares the type variables | ||
/// X1, ..., Xs | ||
/// ... | ||
/// Let Dm be the unique declaration named m that V has. | ||
/// | ||
/// Evaluation of this invocation proceeds by evaluating e to an object o. | ||
/// ... | ||
/// Otherwise, if args is omitted and Dm is a method, the invocation evaluates | ||
/// to a closurization of Dm where this and the name of the representation are | ||
/// bound as with the getter invocation, and the type variables of V are bound | ||
/// to the actual values of T1, .. Ts. The operator == of the closurization | ||
/// returns true if and only if the operand is the same object. | ||
/// | ||
/// @description Check invocation of an extension type `call` member | ||
/// @author [email protected] | ||
|
||
// SharedOptions=--enable-experiment=inline-class | ||
|
||
import "../../Utils/expect.dart"; | ||
|
||
class C { | ||
String call() => "call from C"; | ||
} | ||
|
||
extension type ET1(C _) implements C {} | ||
|
||
extension type ET2(int _) { | ||
String call() => "call from ET2"; | ||
} | ||
|
||
main() { | ||
ET1 e1 = ET1(C()); | ||
ET2 e2 = ET2(0); | ||
|
||
Expect.equals("call from C", e1()); | ||
Expect.equals("call from ET2", e2()); | ||
Expect.equals("call from C", e1.call()); | ||
Expect.equals("call from ET2", e2.call()); | ||
Expect.equals("call from C", (e1.call)()); | ||
Expect.equals("call from ET2", (e2.call)()); | ||
} |
54 changes: 54 additions & 0 deletions
54
LanguageFeatures/Extension-types/dynamic_semantics_member_invocation_A02_t07.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
/// @assertion Consider an invocation of the extension type member m on the | ||
/// receiver expression e according to the extension type declaration V with | ||
/// actual type arguments T1, ..., Ts. If the invocation includes an actual | ||
/// argument part (possibly including some actual type arguments) then call it | ||
/// args. If the invocation omits args, but includes a list of actual type | ||
/// arguments then call them typeArgs. Assume that V declares the type variables | ||
/// X1, ..., Xs | ||
/// ... | ||
/// Let Dm be the unique declaration named m that V has. | ||
/// | ||
/// Evaluation of this invocation proceeds by evaluating e to an object o. | ||
/// ... | ||
/// Otherwise, if args is omitted and Dm is a method, the invocation evaluates | ||
/// to a closurization of Dm where this and the name of the representation are | ||
/// bound as with the getter invocation, and the type variables of V are bound | ||
/// to the actual values of T1, .. Ts. The operator == of the closurization | ||
/// returns true if and only if the operand is the same object. | ||
/// | ||
/// @description Check that if an extension type has `call()` member then it can | ||
/// be assigned to the type `Function` | ||
/// @author [email protected] | ||
|
||
// SharedOptions=--enable-experiment=inline-class | ||
|
||
import "../../Utils/expect.dart"; | ||
|
||
class C { | ||
String call() => "call from C"; | ||
} | ||
|
||
extension type ET1(C _) implements C {} | ||
|
||
extension type ET2(int _) { | ||
String call() => "call from ET2"; | ||
} | ||
|
||
main() { | ||
ET1 e1 = ET1(C()); | ||
ET2 e2 = ET2(0); | ||
|
||
Function f1 = e1; | ||
Function f2 = e2; | ||
Function f3 = e1.call; | ||
Function f4 = e2.call; | ||
|
||
Expect.equals("call from C", f1()); | ||
Expect.equals("call from ET2", f2()); | ||
Expect.equals("call from C", f3()); | ||
Expect.equals("call from ET2", f4()); | ||
} |
99 changes: 99 additions & 0 deletions
99
LanguageFeatures/Extension-types/superinterfaces_of_extension_type_A05_t09.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
/// @assertion Assume that DV is an extension type declaration named Name, and | ||
/// V1 occurs as one of the <type>s in the <interfaces> of DV. In this case we | ||
/// say that V1 is a superinterface of DV. | ||
/// ... | ||
/// Assume that DV is an extension type declaration named Name, and the type V1, | ||
/// declared by DV1, is a superinterface of DV (V1 could be an extension type or | ||
/// a non-extension type). Let m be the name of a member of V1. If DV also | ||
/// declares a member named m then the latter may be considered similar to a | ||
/// declaration that "overrides" the former. However, it should be noted that | ||
/// extension type method invocation is resolved statically, and hence there is | ||
/// no override relationship among the two in the traditional object-oriented | ||
/// sense (that is, it will never occur that the statically known declaration is | ||
/// the member of V1, and the member invoked at run time is the one in DV). A | ||
/// receiver with static type V1 will invoke the declaration in DV1, and a | ||
/// receiver with a static type which is a reference to DV (like Name or | ||
/// Name<...>) will invoke the one in DV. | ||
/// | ||
/// Hence, we use a different word to describe the relationship between a member | ||
/// named m of a superinterface, and a member named m which is declared by the | ||
/// subinterface: We say that the latter redeclares the former. | ||
/// | ||
/// In particular, if two different declarations of m are inherited from two | ||
/// superinterfaces then the subinterface can resolve the conflict by | ||
/// redeclaring m. | ||
/// | ||
/// There is no notion of having a 'correct override relation' here. With | ||
/// extension types, any member signature can redeclare any other member | ||
/// signature with the same name, including the case where a method is | ||
/// redeclared by a getter, or vice versa. | ||
/// | ||
/// @description Checks that a `call` member can be redeclared as any other | ||
/// member, and also that an extension type member named `call` can coexist with | ||
/// a member named `call` in the interface of the representation type. | ||
/// @author [email protected] | ||
|
||
// SharedOptions=--enable-experiment=inline-class | ||
|
||
import '../../Utils/expect.dart'; | ||
|
||
class C1 { | ||
String call() => "call from C1"; | ||
} | ||
|
||
class C2 { | ||
String get call => "call from C2"; | ||
} | ||
|
||
class C3 { | ||
void set call(String _) {} | ||
} | ||
|
||
extension type ET1(C1 c) { | ||
String call() => "call from ET1"; | ||
} | ||
|
||
extension type ET2(C2 c) { | ||
String call() => "call from ET2"; | ||
} | ||
|
||
extension type ET3(C3 c) { | ||
String call() => "call from ET3"; | ||
} | ||
|
||
extension type ET4(C1 c) implements C1 { | ||
String call() => "call from ET4"; | ||
} | ||
|
||
extension type ET5(C2 c) implements C2 { | ||
String call() => "call from ET5"; | ||
} | ||
|
||
extension type ET6(C3 c) implements C3 { | ||
String call() => "call from ET6"; | ||
} | ||
|
||
main() { | ||
Expect.equals("call from ET1", ET1(C1())()); | ||
Expect.equals("call from ET1", ET1(C1()).call()); | ||
Expect.equals("call from C1", ET1(C1()).c()); | ||
Expect.equals("call from ET2", ET2(C2())()); | ||
Expect.equals("call from ET2", ET2(C2()).call()); | ||
Expect.equals("call from C2", ET2(C2()).c.call); | ||
Expect.equals("call from ET3", ET3(C3())()); | ||
Expect.equals("call from ET3", ET3(C3()).call()); | ||
ET3(C3()).c.call = "x"; | ||
Expect.equals("call from ET4", ET4(C1())()); | ||
Expect.equals("call from ET4", ET4(C1()).call()); | ||
Expect.equals("call from C1", ET4(C1()).c()); | ||
Expect.equals("call from ET5", ET5(C2())()); | ||
Expect.equals("call from ET5", ET5(C2()).call()); | ||
Expect.equals("call from C2", ET5(C2()).c.call); | ||
Expect.equals("call from ET6", ET6(C3())()); | ||
Expect.equals("call from ET6", ET6(C3()).call()); | ||
ET6(C3()).c.call = "x"; | ||
} |
87 changes: 87 additions & 0 deletions
87
LanguageFeatures/Extension-types/superinterfaces_of_extension_type_A05_t10.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
/// @assertion Assume that DV is an extension type declaration named Name, and | ||
/// V1 occurs as one of the <type>s in the <interfaces> of DV. In this case we | ||
/// say that V1 is a superinterface of DV. | ||
/// ... | ||
/// Assume that DV is an extension type declaration named Name, and the type V1, | ||
/// declared by DV1, is a superinterface of DV (V1 could be an extension type or | ||
/// a non-extension type). Let m be the name of a member of V1. If DV also | ||
/// declares a member named m then the latter may be considered similar to a | ||
/// declaration that "overrides" the former. However, it should be noted that | ||
/// extension type method invocation is resolved statically, and hence there is | ||
/// no override relationship among the two in the traditional object-oriented | ||
/// sense (that is, it will never occur that the statically known declaration is | ||
/// the member of V1, and the member invoked at run time is the one in DV). A | ||
/// receiver with static type V1 will invoke the declaration in DV1, and a | ||
/// receiver with a static type which is a reference to DV (like Name or | ||
/// Name<...>) will invoke the one in DV. | ||
/// | ||
/// Hence, we use a different word to describe the relationship between a member | ||
/// named m of a superinterface, and a member named m which is declared by the | ||
/// subinterface: We say that the latter redeclares the former. | ||
/// | ||
/// In particular, if two different declarations of m are inherited from two | ||
/// superinterfaces then the subinterface can resolve the conflict by | ||
/// redeclaring m. | ||
/// | ||
/// There is no notion of having a 'correct override relation' here. With | ||
/// extension types, any member signature can redeclare any other member | ||
/// signature with the same name, including the case where a method is | ||
/// redeclared by a getter, or vice versa. | ||
/// | ||
/// @description Checks that a `call` member can be redeclared as any other | ||
/// member, and it can coexist with a member named `call` in the interface of | ||
/// the representation type. | ||
/// @author [email protected] | ||
|
||
// SharedOptions=--enable-experiment=inline-class | ||
|
||
import '../../Utils/expect.dart'; | ||
|
||
class C1 { | ||
String call() => "call from C1"; | ||
} | ||
|
||
class C2 { | ||
String get call => "call from C2"; | ||
} | ||
|
||
class C3 { | ||
void set call(String _) {} | ||
eernstg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
extension type ET1(C1 c) { | ||
String get call => "call from ET1"; | ||
} | ||
|
||
extension type ET2(C2 c) { | ||
String get call => "call from ET2"; | ||
} | ||
|
||
extension type ET3(C3 c) { | ||
String get call => "call from ET3"; | ||
} | ||
|
||
extension type ET4(C1 c) implements C1 { | ||
String get call => "call from ET4"; | ||
} | ||
|
||
extension type ET5(C2 c) implements C2 { | ||
String get call => "call from ET5"; | ||
} | ||
|
||
extension type ET6(C3 c) implements C3 { | ||
String get call => "call from ET6"; | ||
} | ||
|
||
main() { | ||
Expect.equals("call from ET1", ET1(C1()).call); | ||
Expect.equals("call from ET2", ET2(C2()).call); | ||
Expect.equals("call from ET3", ET3(C3()).call); | ||
Expect.equals("call from ET4", ET4(C1()).call); | ||
Expect.equals("call from ET5", ET5(C2()).call); | ||
Expect.equals("call from ET6", ET6(C3()).call); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.