Skip to content

Commit c3b8fe1

Browse files
authored
#1400. Dynamic Semantics of an Inline Member Invocation tests (#2053)
Add tests on the dynamic semantics of an Inline member invocation
1 parent 0dd784e commit c3b8fe1

12 files changed

+546
-6
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion Consider an invocation of the inline member m on the receiver e
6+
/// according to the inline type V and with actual type arguments T1, ..., Ts.
7+
/// If the invocation includes an actual argument part (possibly including some
8+
/// actual type arguments) then call it args. Assume that V declares the type
9+
/// variables X1, ..., Xs.
10+
///
11+
/// Let Dm be the declaration named m thath V has.
12+
///
13+
/// Evaluation of this invocation proceeds by evaluating e to an object o.
14+
///
15+
/// Then, if args is omitted and Dm is a getter, execute the body of said
16+
/// getter in an environment where this and the name of the representation are
17+
/// bound to o, and the type variables of V are bound to the actual values of
18+
/// T1, .. Ts. If the body completes returning an object o2 then the invocation
19+
/// evaluates to o2. If the body throws an object and a stack trace then the
20+
/// invocation completes throwing the same object and stack trace.
21+
///
22+
/// @description Check invocation of an inline class getter. Test that if the
23+
/// body completes returning an object `o2` then the invocation evaluates to
24+
/// `o2`.
25+
/// @author [email protected]
26+
27+
// SharedOptions=--enable-experiment=inline-class
28+
29+
import "../../Utils/expect.dart";
30+
import "../../Utils/static_type_helper.dart";
31+
32+
inline class IC<T> {
33+
final T id;
34+
IC(this.id);
35+
}
36+
37+
inline class IC2<T extends num> {
38+
final T id;
39+
IC2(this.id);
40+
41+
List<T> get emptyList => <T>[];
42+
}
43+
44+
main() {
45+
IC<Object?> ic1_1 = IC(42);
46+
Expect.equals(42, ic1_1.id);
47+
48+
IC<Object?> ic1_2 = IC("42");
49+
Expect.equals("42", ic1_2.id);
50+
51+
IC2<int> ic2_1 = IC2(42);
52+
ic2_1.emptyList.expectStaticType<Exactly<List<int>>>();
53+
Expect.throws(() {ic2_1.emptyList.add(3.14 as dynamic);});
54+
55+
IC2<num> ic2_2 = IC2(3.14);
56+
ic2_2.emptyList.expectStaticType<Exactly<List<num>>>();
57+
ic2_2.emptyList.add(42);
58+
ic2_2.emptyList.add(3.14);
59+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion Consider an invocation of the inline member m on the receiver e
6+
/// according to the inline type V and with actual type arguments T1, ..., Ts.
7+
/// If the invocation includes an actual argument part (possibly including some
8+
/// actual type arguments) then call it args. Assume that V declares the type
9+
/// variables X1, ..., Xs.
10+
///
11+
/// Let Dm be the declaration named m thath V has.
12+
///
13+
/// Evaluation of this invocation proceeds by evaluating e to an object o.
14+
///
15+
/// Then, if args is omitted and Dm is a getter, execute the body of said
16+
/// getter in an environment where this and the name of the representation are
17+
/// bound to o, and the type variables of V are bound to the actual values of
18+
/// T1, .. Ts. If the body completes returning an object o2 then the invocation
19+
/// evaluates to o2. If the body throws an object and a stack trace then the
20+
/// invocation completes throwing the same object and stack trace.
21+
///
22+
/// @description Check invocation of an inline class getter in the case when
23+
/// type arguments are omitted. Test that if the body throws an object and a
24+
/// stack trace then the invocation completes throwing the same object and stack
25+
/// trace
26+
/// @author [email protected]
27+
28+
// SharedOptions=--enable-experiment=inline-class
29+
30+
import "../../Utils/expect.dart";
31+
32+
StackTrace st = StackTrace.fromString("42");
33+
34+
inline class IC<T extends num> {
35+
final T id;
36+
IC(this.id);
37+
38+
T get testMe {
39+
if (2 > 1) {
40+
Error.throwWithStackTrace("T is $T", st);
41+
}
42+
return id;
43+
}
44+
}
45+
46+
main() {
47+
IC<num> ic1 = IC(42);
48+
try {
49+
ic1.testMe;
50+
} catch (e, _st) {
51+
Expect.equals("T is num", e);
52+
Expect.equals(st, _st);
53+
}
54+
55+
IC<int> ic2 = IC(42);
56+
try {
57+
ic2.testMe;
58+
} catch (e, _st) {
59+
Expect.equals("T is int", e);
60+
Expect.equals(st, _st);
61+
}
62+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion Consider an invocation of the inline member m on the receiver e
6+
/// according to the inline type V and with actual type arguments T1, ..., Ts.
7+
/// If the invocation includes an actual argument part (possibly including some
8+
/// actual type arguments) then call it args. Assume that V declares the type
9+
/// variables X1, ..., Xs.
10+
///
11+
/// Let Dm be the declaration named m thath V has.
12+
///
13+
/// Evaluation of this invocation proceeds by evaluating e to an object o.
14+
/// ...
15+
/// Otherwise, if args is omitted and Dm is a method, the invocation evaluates
16+
/// to a closurization of Dm where this and the name of the representation are
17+
/// bound to o, and the type variables of V are bound to the actual values of
18+
/// T1, .. Ts. The operator == of the closurization returns true if and only if
19+
/// the operand is the same object.
20+
///
21+
/// @description Check that in case of invocation of an inline class method with
22+
/// the omitted type argument the actual type variables of V are bound to the
23+
/// actual values of T1, .. Ts.
24+
/// @author [email protected]
25+
26+
// SharedOptions=--enable-experiment=inline-class
27+
28+
import "../../Utils/expect.dart";
29+
30+
inline class IC<T> {
31+
final T id;
32+
IC(this.id);
33+
34+
Map<K, Type> asMap<K, V extends T>(K key1, K key2) => {key1: V, key2: T};
35+
}
36+
37+
main() {
38+
IC<num> ic1_1 = IC(42);
39+
Expect.mapEquals({"key1": num, "key2": num}, ic1_1.asMap("key1", "key2"));
40+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion Consider an invocation of the inline member m on the receiver e
6+
/// according to the inline type V and with actual type arguments T1, ..., Ts.
7+
/// If the invocation includes an actual argument part (possibly including some
8+
/// actual type arguments) then call it args. Assume that V declares the type
9+
/// variables X1, ..., Xs.
10+
///
11+
/// Let Dm be the declaration named m thath V has.
12+
///
13+
/// Evaluation of this invocation proceeds by evaluating e to an object o.
14+
/// ...
15+
/// Otherwise, if args is omitted and Dm is a method, the invocation evaluates
16+
/// to a closurization of Dm where this and the name of the representation are
17+
/// bound to o, and the type variables of V are bound to the actual values of
18+
/// T1, .. Ts. The operator == of the closurization returns true if and only if
19+
/// the operand is the same object.
20+
///
21+
/// @description Check that `this` is bound to `o`
22+
/// @author [email protected]
23+
24+
// SharedOptions=--enable-experiment=inline-class
25+
26+
import "../../Utils/expect.dart";
27+
28+
inline class IC<T> {
29+
final T id;
30+
IC(this.id);
31+
32+
Object test1() => this;
33+
void test2() {
34+
Expect.identical(this, id);
35+
}
36+
}
37+
38+
main() {
39+
IC ic = IC(42);
40+
Expect.identical(ic, ic.test1());
41+
ic.test2();
42+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion Consider an invocation of the inline member m on the receiver e
6+
/// according to the inline type V and with actual type arguments T1, ..., Ts.
7+
/// If the invocation includes an actual argument part (possibly including some
8+
/// actual type arguments) then call it args. Assume that V declares the type
9+
/// variables X1, ..., Xs.
10+
///
11+
/// Let Dm be the declaration named m thath V has.
12+
///
13+
/// Evaluation of this invocation proceeds by evaluating e to an object o.
14+
/// ...
15+
/// Otherwise, if args is omitted and Dm is a method, the invocation evaluates
16+
/// to a closurization of Dm where this and the name of the representation are
17+
/// bound to o, and the type variables of V are bound to the actual values of
18+
/// T1, .. Ts. The operator == of the closurization returns true if and only if
19+
/// the operand is the same object.
20+
///
21+
/// @description Check that the operator `==` of the closurization returns true
22+
/// if and only if the operand is the same object
23+
/// @author [email protected]
24+
25+
// SharedOptions=--enable-experiment=inline-class
26+
27+
import "../../Utils/expect.dart";
28+
29+
inline class IC<T> {
30+
final T id;
31+
IC(this.id);
32+
33+
Map<K, V> asMap<K, V extends T>(K key) => {key: this.id as V};
34+
}
35+
36+
main() {
37+
IC<int> ic1 = IC(42);
38+
var asMapTearOff = ic1.asMap;
39+
Expect.notEquals(asMapTearOff, ic1.asMap);
40+
Expect.equals(asMapTearOff, asMapTearOff);
41+
42+
IC<num> ic2 = IC(42);
43+
var asMapTearOff2 = ic2.asMap;
44+
Expect.notEquals(asMapTearOff2, ic2.asMap);
45+
Expect.notEquals(asMapTearOff2, asMapTearOff);
46+
Expect.equals(asMapTearOff2, asMapTearOff2);
47+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion Consider an invocation of the inline member m on the receiver e
6+
/// according to the inline type V and with actual type arguments T1, ..., Ts.
7+
/// If the invocation includes an actual argument part (possibly including some
8+
/// actual type arguments) then call it args. Assume that V declares the type
9+
/// variables X1, ..., Xs.
10+
///
11+
/// Let Dm be the declaration named m thath V has.
12+
///
13+
/// Evaluation of this invocation proceeds by evaluating e to an object o.
14+
/// ...
15+
/// Otherwise, if args is omitted and Dm is a method, the invocation evaluates
16+
/// to a closurization of Dm where this and the name of the representation are
17+
/// bound to o, and the type variables of V are bound to the actual values of
18+
/// T1, .. Ts. The operator == of the closurization returns true if and only if
19+
/// the operand is the same object.
20+
///
21+
/// @description Check that if the body throws an object and a stack trace then
22+
/// the invocation completes throwing the same object and stack trace.
23+
/// @author [email protected]
24+
25+
// SharedOptions=--enable-experiment=inline-class
26+
27+
import "../../Utils/expect.dart";
28+
29+
StackTrace st = StackTrace.fromString("42");
30+
31+
inline class IC<T extends num> {
32+
final T id;
33+
IC(this.id);
34+
35+
X testMe<X extends T>() {
36+
if (2 > 1) {
37+
Error.throwWithStackTrace("X is $X", st);
38+
}
39+
return id as X;
40+
}
41+
}
42+
43+
main() {
44+
IC<num> ic1 = IC(42);
45+
try {
46+
ic1.testMe();
47+
} catch (e, _st) {
48+
Expect.equals("X is num", e);
49+
Expect.equals(st, _st);
50+
}
51+
52+
IC<int> ic2 = IC(42);
53+
try {
54+
ic2.testMe();
55+
} catch (e, _st) {
56+
Expect.equals("X is int", e);
57+
Expect.equals(st, _st);
58+
}
59+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
/// @assertion Consider an invocation of the inline member m on the receiver e
6+
/// according to the inline type V and with actual type arguments T1, ..., Ts.
7+
/// If the invocation includes an actual argument part (possibly including some
8+
/// actual type arguments) then call it args. Assume that V declares the type
9+
/// variables X1, ..., Xs.
10+
///
11+
/// Let Dm be the declaration named m thath V has.
12+
///
13+
/// Evaluation of this invocation proceeds by evaluating e to an object o.
14+
/// ...
15+
/// Otherwise, the following is known: args is included, and Dm is a method. The
16+
/// invocation proceeds to evaluate args to an actual argument list args1. Then
17+
/// it executes the body of Dm in an environment where this and the name of the
18+
/// representation are bound to o, the type variables of V are bound to the
19+
/// actual values of T1, .. Ts, and the formal parameters of m are bound to
20+
/// args1 in the same way that they would be bound for a normal function call.
21+
/// If the body completes returning an object o2 then the invocation evaluates
22+
/// to o2. If the body throws an object and a stack trace then the invocation
23+
/// completes throwing the same object and stack trace.
24+
///
25+
/// @description Check that in case of an invocation of an inline class method
26+
/// `m` the specified type parameters and formal parameters of `m` are bound to
27+
/// `args1` in the same way that they would be bound for a normal function call
28+
/// @author [email protected]
29+
30+
// SharedOptions=--enable-experiment=inline-class
31+
32+
import "../../Utils/expect.dart";
33+
34+
inline class IC<T> {
35+
final T id;
36+
IC(this.id);
37+
38+
Map<K, Type> asMap<K, V extends T>(K key1, K key2) => {key1: V, key2: T};
39+
}
40+
41+
main() {
42+
IC<num> ic1 = IC(42);
43+
Expect.mapEquals(
44+
{"key1": int, "key2": num}, ic1.asMap<String, int>("key1", "key2"));
45+
Expect.mapEquals(
46+
{"key1": num, "key2": num}, ic1.asMap<String, num>("key1", "key2"));
47+
}

0 commit comments

Comments
 (0)