-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Add `call()` method tests for extension types
- Loading branch information
Showing
6 changed files
with
458 additions
and
0 deletions.
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 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 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 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 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 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 _) {} | ||
} | ||
|
||
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.