Skip to content

Commit 5580f89

Browse files
lrhncommit-bot@chromium.org
authored andcommitted
Add test for new numeric operator typing rules.
Change-Id: I8e3c478c129e633421625967ff4ac41c9b565fb2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153200 Commit-Queue: Lasse R.H. Nielsen <[email protected]> Reviewed-by: Paul Berry <[email protected]> Reviewed-by: Erik Ernst <[email protected]>
1 parent 73e9554 commit 5580f89

File tree

4 files changed

+1547
-0
lines changed

4 files changed

+1547
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
// Copyright (c) 2021, 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+
// Test the new context type rules for number operators,
6+
// as modified by Null Safety
7+
import "static_type_helper.dart";
8+
9+
// The context rules for `e` of the form:
10+
// For e1 + e2, e1 - e2, e1 * e2, e1 % e2 or e1.remainder(e2),,
11+
// if the static type of e1 is a non-`Never` subtype of `int`,
12+
// and the context type of the entire expression is `int`,
13+
// then the context type of e2 is `int`.
14+
// If the static type of e1 is a non-`Never` subtype of `num`
15+
// that is not a subtype of `double`,
16+
// and the context type of the entire expression is `double`,
17+
// then the context type of e2 is `double`.
18+
19+
// If the context type of `e1.clamp(e2, e3)`, *C*,
20+
// and the the static type of `e1`, *T*,
21+
// are both is a non-`Never` subtypes of `num`,
22+
// then the context types of `e2` and `e3` are both *C*.
23+
// Otherwise the context types of `e2` and `e3` are `num`.
24+
25+
void main() {
26+
testIntContext<int, Object>(1, 1);
27+
testDoubleContext<int, double, num, Object>(1, 1.1, 1.1, 1.1);
28+
testNumContext<num, Object>(1, 1);
29+
}
30+
31+
void testIntContext<I extends int, O extends Object>(I i, O o) {
32+
context<int>(1 + (contextType(1)..expectStaticType<Exactly<int>>()));
33+
context<int>(1 - (contextType(1)..expectStaticType<Exactly<int>>()));
34+
context<int>(1 * (contextType(1)..expectStaticType<Exactly<int>>()));
35+
context<int>(1 % (contextType(1)..expectStaticType<Exactly<int>>()));
36+
context<int>(1.remainder(contextType(1)..expectStaticType<Exactly<int>>()));
37+
38+
context<int>(i + (contextType(1)..expectStaticType<Exactly<int>>()));
39+
context<int>(i - (contextType(1)..expectStaticType<Exactly<int>>()));
40+
context<int>(i * (contextType(1)..expectStaticType<Exactly<int>>()));
41+
context<int>(i % (contextType(1)..expectStaticType<Exactly<int>>()));
42+
context<int>(i.remainder(contextType(1)..expectStaticType<Exactly<int>>()));
43+
44+
context<I>(i + (contextType(1)..expectStaticType<Exactly<int>>()));
45+
context<I>(i - (contextType(1)..expectStaticType<Exactly<int>>()));
46+
context<I>(i * (contextType(1)..expectStaticType<Exactly<int>>()));
47+
context<I>(i % (contextType(1)..expectStaticType<Exactly<int>>()));
48+
context<I>(i.remainder(contextType(1)..expectStaticType<Exactly<int>>()));
49+
50+
context<num>(1 + (contextType(1)..expectStaticType<Exactly<num>>()));
51+
context<num>(1 - (contextType(1)..expectStaticType<Exactly<num>>()));
52+
context<num>(1 * (contextType(1)..expectStaticType<Exactly<num>>()));
53+
context<num>(1 % (contextType(1)..expectStaticType<Exactly<num>>()));
54+
context<num>(1.remainder(contextType(1)..expectStaticType<Exactly<num>>()));
55+
56+
var oi = o;
57+
if (oi is! int) throw "promote oi to O&int";
58+
59+
context<int>(oi + (contextType(1)..expectStaticType<Exactly<int>>()));
60+
context<int>(oi - (contextType(1)..expectStaticType<Exactly<int>>()));
61+
context<int>(oi * (contextType(1)..expectStaticType<Exactly<int>>()));
62+
context<int>(oi % (contextType(1)..expectStaticType<Exactly<int>>()));
63+
context<int>(oi.remainder(contextType(1)..expectStaticType<Exactly<int>>()));
64+
65+
i += contextType(1)..expectStaticType<Exactly<int>>();
66+
i -= contextType(1)..expectStaticType<Exactly<int>>();
67+
i *= contextType(1)..expectStaticType<Exactly<int>>();
68+
i %= contextType(1)..expectStaticType<Exactly<int>>();
69+
70+
oi += contextType(1)..expectStaticType<Exactly<int>>();
71+
oi -= contextType(1)..expectStaticType<Exactly<int>>();
72+
oi *= contextType(1)..expectStaticType<Exactly<int>>();
73+
oi %= contextType(2)..expectStaticType<Exactly<int>>();
74+
75+
context<int>(1.clamp(contextType(1)..expectStaticType<Exactly<int>>(),
76+
contextType(1)..expectStaticType<Exactly<int>>()));
77+
78+
context<int>(i.clamp(contextType(1)..expectStaticType<Exactly<int>>(),
79+
contextType(1)..expectStaticType<Exactly<int>>()));
80+
81+
context<I>(i.clamp(contextType(1)..expectStaticType<Exactly<I>>(),
82+
contextType(1)..expectStaticType<Exactly<I>>()));
83+
84+
context<int>(oi.clamp(contextType(1)..expectStaticType<Exactly<int>>(),
85+
contextType(1)..expectStaticType<Exactly<int>>()));
86+
87+
context<I>(i.clamp(contextType(1)..expectStaticType<Exactly<I>>(),
88+
contextType(1)..expectStaticType<Exactly<I>>()));
89+
}
90+
91+
void testDoubleContext<I extends int, D extends double, N extends num,
92+
O extends Object>(I i, D d, N n, O o) {
93+
context<double>(1 + (contextType(1.0)..expectStaticType<Exactly<double>>()));
94+
context<double>(1 - (contextType(1.0)..expectStaticType<Exactly<double>>()));
95+
context<double>(1 * (contextType(1.0)..expectStaticType<Exactly<double>>()));
96+
context<double>(1 % (contextType(1.0)..expectStaticType<Exactly<double>>()));
97+
context<double>(
98+
1.remainder(contextType(1.0)..expectStaticType<Exactly<double>>()));
99+
100+
context<double>(n + (contextType(1.0)..expectStaticType<Exactly<double>>()));
101+
context<double>(n - (contextType(1.0)..expectStaticType<Exactly<double>>()));
102+
context<double>(n * (contextType(1.0)..expectStaticType<Exactly<double>>()));
103+
context<double>(n % (contextType(1.0)..expectStaticType<Exactly<double>>()));
104+
context<double>(
105+
n.remainder(contextType(1.0)..expectStaticType<Exactly<double>>()));
106+
107+
context<double>(i + (contextType(1.0)..expectStaticType<Exactly<double>>()));
108+
context<double>(i - (contextType(1.0)..expectStaticType<Exactly<double>>()));
109+
context<double>(i * (contextType(1.0)..expectStaticType<Exactly<double>>()));
110+
context<double>(i % (contextType(1.0)..expectStaticType<Exactly<double>>()));
111+
context<double>(
112+
i.remainder(contextType(1.0)..expectStaticType<Exactly<double>>()));
113+
114+
context<double>(d + (contextType(1.0)..expectStaticType<Exactly<num>>()));
115+
context<double>(d - (contextType(1.0)..expectStaticType<Exactly<num>>()));
116+
context<double>(d * (contextType(1.0)..expectStaticType<Exactly<num>>()));
117+
context<double>(d % (contextType(1.0)..expectStaticType<Exactly<num>>()));
118+
context<double>(
119+
d.remainder(contextType(1.0)..expectStaticType<Exactly<num>>()));
120+
121+
context<D>(1 + (contextType(1)..expectStaticType<Exactly<double>>()));
122+
context<D>(1 - (contextType(1)..expectStaticType<Exactly<double>>()));
123+
context<D>(1 * (contextType(1)..expectStaticType<Exactly<double>>()));
124+
context<D>(1 % (contextType(1)..expectStaticType<Exactly<double>>()));
125+
context<D>(1.remainder(contextType(1)..expectStaticType<Exactly<double>>()));
126+
127+
context<D>(d + (contextType(1.0)..expectStaticType<Exactly<num>>()));
128+
context<D>(d - (contextType(1.0)..expectStaticType<Exactly<num>>()));
129+
context<D>(d * (contextType(1.0)..expectStaticType<Exactly<num>>()));
130+
context<D>(d % (contextType(1.0)..expectStaticType<Exactly<num>>()));
131+
context<D>(d.remainder(contextType(1.0)..expectStaticType<Exactly<num>>()));
132+
133+
// The context type also causes double literals.
134+
context<double>(1 + (1..expectStaticType<double>()));
135+
context<double>(1 - (1..expectStaticType<double>()));
136+
context<double>(1 * (1..expectStaticType<double>()));
137+
context<double>(1 % (1..expectStaticType<double>()));
138+
context<double>(1.remainder(1..expectStaticType<double>()));
139+
140+
var od = o;
141+
if (od is! double) throw "promote od to O&double";
142+
143+
context<double>(od + (contextType(1.0)..expectStaticType<Exactly<num>>()));
144+
context<double>(od - (contextType(1.0)..expectStaticType<Exactly<num>>()));
145+
context<double>(od * (contextType(1.0)..expectStaticType<Exactly<num>>()));
146+
context<double>(od % (contextType(1.0)..expectStaticType<Exactly<num>>()));
147+
context<double>(
148+
od.remainder(contextType(1.0)..expectStaticType<Exactly<num>>()));
149+
150+
d += contextType(1)..expectStaticType<Exactly<num>>();
151+
d -= contextType(1)..expectStaticType<Exactly<num>>();
152+
d *= contextType(1)..expectStaticType<Exactly<num>>();
153+
d %= contextType(2)..expectStaticType<Exactly<num>>();
154+
155+
od += contextType(1)..expectStaticType<Exactly<num>>();
156+
od -= contextType(1)..expectStaticType<Exactly<num>>();
157+
od *= contextType(1)..expectStaticType<Exactly<num>>();
158+
od %= contextType(2)..expectStaticType<Exactly<num>>();
159+
160+
context<double>(1.1.clamp(
161+
contextType(1.0)..expectStaticType<Exactly<double>>(),
162+
contextType(1.0)..expectStaticType<Exactly<double>>()));
163+
164+
context<double>(d.clamp(contextType(1.0)..expectStaticType<Exactly<double>>(),
165+
contextType(1.0)..expectStaticType<Exactly<double>>()));
166+
167+
context<D>(d.clamp(contextType(1.0)..expectStaticType<Exactly<D>>(),
168+
contextType(1.0)..expectStaticType<Exactly<D>>()));
169+
170+
context<double>(od.clamp(
171+
contextType(1.0)..expectStaticType<Exactly<double>>(),
172+
contextType(1.0)..expectStaticType<Exactly<double>>()));
173+
174+
context<D>(od.clamp(contextType(1.0)..expectStaticType<Exactly<D>>(),
175+
contextType(1.0)..expectStaticType<Exactly<D>>()));
176+
}
177+
178+
void testNumContext<N extends num, O extends Object>(N n, O o) {
179+
if (o is! num) throw "promote o to O&num";
180+
181+
context<num>(n + (contextType(1)..expectStaticType<Exactly<num>>()));
182+
context<num>(n - (contextType(1)..expectStaticType<Exactly<num>>()));
183+
context<num>(n * (contextType(1)..expectStaticType<Exactly<num>>()));
184+
context<num>(n % (contextType(1)..expectStaticType<Exactly<num>>()));
185+
context<num>(n.remainder(contextType(1)..expectStaticType<Exactly<num>>()));
186+
187+
context<num>(o + (contextType(1)..expectStaticType<Exactly<num>>()));
188+
context<num>(o - (contextType(1)..expectStaticType<Exactly<num>>()));
189+
context<num>(o * (contextType(1)..expectStaticType<Exactly<num>>()));
190+
context<num>(o % (contextType(1)..expectStaticType<Exactly<num>>()));
191+
context<num>(o.remainder(contextType(1)..expectStaticType<Exactly<num>>()));
192+
193+
context<num>(o.clamp(contextType(1)..expectStaticType<Exactly<num>>(),
194+
contextType(1)..expectStaticType<Exactly<num>>()));
195+
196+
context<N>(n.clamp(contextType(1)..expectStaticType<Exactly<N>>(),
197+
contextType(1)..expectStaticType<Exactly<N>>()));
198+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
// Copyright (c) 2021, 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+
// Test the new context type rules for number operators,
6+
import "static_type_helper.dart";
7+
8+
// as modified by Null Safety
9+
void main() {
10+
testTypes<int, double, num, Object, int, double, num>(
11+
1, 1.0, 1, 1, 1, 1.0, 1);
12+
}
13+
14+
void testTypes<
15+
I extends int,
16+
D extends double,
17+
N extends num,
18+
O extends Object,
19+
II extends I,
20+
DD extends D,
21+
NN extends N>(I ti, D td, N tn, O to, II tii, DD tdd, NN tnn) {
22+
int i = 1;
23+
double d = 1.0;
24+
num n = cast(1);
25+
O oi = cast(1);
26+
if (oi is! int) throw "promote oi to O&int";
27+
checkIntersectionType<O, int>(oi, oi, oi);
28+
O od = cast(1.0);
29+
if (od is! double) throw "promote od to O&double";
30+
checkIntersectionType<O, double>(od, od, od);
31+
O on = cast(1);
32+
if (on is! num) throw "promote on to I&num";
33+
checkIntersectionType<O, num>(on, on, on);
34+
dynamic dyn = cast(1);
35+
late never = throw "unreachable";
36+
37+
/* indent */ i + "string";
38+
// ^^^^^^^^
39+
// [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
40+
// [cfe] A value of type 'String' can't be assigned to a variable of type 'num'.
41+
42+
i += d;
43+
// ^
44+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
45+
//^^
46+
// [cfe] A value of type 'double' can't be assigned to a variable of type 'int'.
47+
48+
i += n;
49+
// ^
50+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
51+
//^^
52+
// [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
53+
54+
i += never;
55+
// ^^^^^
56+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
57+
//^^
58+
// [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
59+
60+
i += dyn; // type of `i + dyn` is `num`, not assignable to `int`.
61+
// ^^^
62+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
63+
//^^
64+
// [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
65+
66+
ti += d; // Type of expression is `num`, not `I`.
67+
// ^
68+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
69+
// ^^
70+
// [cfe] A value of type 'double' can't be assigned to a variable of type 'I'.
71+
72+
ti += n; // Type of expression is `num`, not `I`.
73+
// ^
74+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
75+
// ^^
76+
// [cfe] A value of type 'num' can't be assigned to a variable of type 'I'.
77+
78+
ti += never; // Type of expression is `num`, not `I`.
79+
// ^^^^^
80+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
81+
// ^^
82+
// [cfe] A value of type 'num' can't be assigned to a variable of type 'I'.
83+
84+
ti += dyn; // type of `i + dyn` is `num`, not assignable to `int`.
85+
// ^^^
86+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
87+
// ^^
88+
// [cfe] A value of type 'num' can't be assigned to a variable of type 'I'.
89+
90+
O oi1 = to; // New variable to avoid demoting `oi`.
91+
if (oi1 is int) {
92+
// Promote oi1 to O&int
93+
oi1 + d; // Valid
94+
oi1 += d;
95+
// ^
96+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
97+
// ^^
98+
// [cfe] A value of type 'double' can't be assigned to a variable of type 'O'.
99+
}
100+
101+
O oi2 = to;
102+
if (oi2 is int) {
103+
// Promote oi2 to O&int.
104+
oi2 + n; // Valid
105+
oi2 += n;
106+
// ^
107+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
108+
// ^^
109+
// [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
110+
}
111+
112+
O oi3 = to;
113+
if (oi3 is int) {
114+
// Promote oi3 to O&int.
115+
oi3 + dyn; // Valid
116+
oi3 += dyn;
117+
// ^^^
118+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
119+
// ^^
120+
// [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
121+
}
122+
123+
O oi4 = to;
124+
if (oi4 is int) {
125+
// Promote oi4 to O&int.
126+
oi4 + never; // Valid.
127+
oi4 += never;
128+
// ^^^^^
129+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
130+
// ^^
131+
// [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
132+
}
133+
134+
context<D>(i + td); // Type of expression is `double`, not `D`.
135+
// ^^^^^^
136+
// [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
137+
// ^
138+
// [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
139+
140+
context<D>(n + td); // Type of expression is `double`, not `D`.
141+
// ^^^^^^
142+
// [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
143+
// ^
144+
// [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
145+
146+
context<D>(1.0 + td); // Type of expression is `double`, not `D`.
147+
// ^^^^^^^^
148+
// [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
149+
// ^
150+
// [cfe] The argument type 'double' can't be assigned to the parameter type 'D'.
151+
152+
tn += n; // Type of expression is `num`, not `N`.
153+
// ^
154+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
155+
// ^^
156+
// [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
157+
158+
tn += dyn;
159+
// ^^^
160+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
161+
// ^^
162+
// [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
163+
164+
O on1 = to;
165+
if (on1 is num) {
166+
// Promote on1 to O&num.
167+
on1 += n; // Type of expression is `num`, not `N` or `O`.
168+
// ^
169+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
170+
// ^^
171+
// [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
172+
}
173+
174+
O on2 = to;
175+
if (on2 is num) {
176+
// Promote on2 to O&num.
177+
on2 += dyn; // Type of expression is `num`, not `N` or `O`.
178+
// ^^^
179+
// [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
180+
// ^^
181+
// [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
182+
}
183+
}
184+
185+
T cast<T>(Object value) => value as T;

0 commit comments

Comments
 (0)