Skip to content

Commit 6428bab

Browse files
lrhncommit-bot@chromium.org
authored andcommitted
Add tests for override inherited inference.
Change-Id: I636682c38e2ba97826420f6f6bbb8e54aa29e21f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/148761 Reviewed-by: Lasse R.H. Nielsen <[email protected]> Reviewed-by: Erik Ernst <[email protected]> Reviewed-by: Bob Nystrom <[email protected]> Reviewed-by: Leaf Petersen <[email protected]> Commit-Queue: Lasse R.H. Nielsen <[email protected]>
1 parent 67da8cf commit 6428bab

File tree

2 files changed

+692
-0
lines changed

2 files changed

+692
-0
lines changed
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
// Copyright (c) 2020, 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+
// ignore_for_file: unused_local_variable
6+
7+
// Static tests for inheriting types on overriding members.
8+
9+
// If a member `m` omits any parameter type, or the return type, and
10+
// one or more of the immediate superinterfaces have a member named
11+
// `m`: Find the combined member signature `s` for `m` in the immediate
12+
// superinterfaces. A compile-time error occurs if it does not exist.
13+
// Otherwise, each missing type annotation of a parameter is obtained
14+
// from the corresponding parameter in `s`, and the return type, if
15+
// missing, is obtained from `s`. If there is no corresponding
16+
// parameter in `s`, the inferred type annotation is `dynamic`.
17+
//
18+
// Only types are inherited. Other modifiers and annotations are not.
19+
// This includes `final`, `required` and any annotations
20+
// or default values.
21+
// (The `covariant` keyword is not inherited, but its semantics
22+
// are so it's impossible to tell the difference).
23+
//
24+
// For getters and setters, if both are present, subclasses inherit the type of
25+
// the corresponding superclass member.
26+
// If the superclass has only a setter or a getter, subclasses inherit that type
27+
// for both getters and setters.
28+
29+
// Incompatible `foo` signatures.
30+
abstract class IIntInt {
31+
int foo(int x);
32+
}
33+
34+
abstract class IIntDouble {
35+
double foo(int x);
36+
}
37+
38+
abstract class IDoubleInt {
39+
int foo(double x);
40+
}
41+
42+
abstract class IDoubleDouble {
43+
double foo(double x);
44+
}
45+
46+
// If the superinterfaces do not have a most specific member signature,
47+
// then omitting any parameter or return type is an error.
48+
49+
abstract class CInvalid1 implements IIntInt, IIntDouble {
50+
/*indent*/ foo(x);
51+
// ^^^
52+
// [analyzer] unspecified
53+
// [cfe] unspecified
54+
}
55+
56+
abstract class CInvalid2 implements IIntInt, IDoubleInt {
57+
/*indent*/ foo(x);
58+
// ^^^
59+
// [analyzer] unspecified
60+
// [cfe] unspecified
61+
}
62+
63+
abstract class CInvalid3 implements IIntInt, IDoubleDouble {
64+
/*indent*/ foo(x);
65+
// ^^^
66+
// [analyzer] unspecified
67+
// [cfe] unspecified
68+
}
69+
70+
// Even if the conflicting super-parameter/return type is given a type.
71+
abstract class CInvalid4 implements IIntInt, IIntDouble {
72+
Never foo(x);
73+
// ^^^
74+
// [analyzer] unspecified
75+
// [cfe] unspecified
76+
}
77+
78+
abstract class CInvalid5 implements IIntInt, IDoubleInt {
79+
/*indent*/ foo(num x);
80+
// ^^^
81+
// [analyzer] unspecified
82+
// [cfe] unspecified
83+
}
84+
85+
// Even if the omitted parameter doesn't exist in the super-interfaces.
86+
abstract class CInvalid6 implements IIntInt, IDoubleInt {
87+
Never foo(num x, [y]);
88+
// ^^^
89+
// [analyzer] unspecified
90+
// [cfe] unspecified
91+
}
92+
93+
// And even if there is no real conflict.
94+
abstract class IOptx {
95+
int foo({int x});
96+
}
97+
98+
abstract class IOpty {
99+
int foo({int y});
100+
}
101+
102+
abstract class CInvalid7 implements IOptx, IOpty {
103+
/*indent*/ foo({int x, int y});
104+
// ^^^
105+
// [analyzer] unspecified
106+
// [cfe] unspecified
107+
}
108+
109+
// The type of unconstrained omitted types is `dynamic`.
110+
class CInherit1 implements IOptx {
111+
foo({x = 0, y = 0}) {
112+
// Type of `y` is `dynamic`.
113+
Object? tmp;
114+
y = tmp; // Top type.
115+
Null tmp2 = y; // And implicit downcast.
116+
y.arglebargle(); // And unsound member invocations.
117+
118+
// x is exactly int.
119+
// Assignable to int and usable as int.
120+
int intVar = x;
121+
x = x.toRadixString(16).length;
122+
// And not dynamic.
123+
/*indent*/ x.arglebargle();
124+
// ^^^^^^^^^^^
125+
// [analyzer] unspecified
126+
// [cfe] unspecified
127+
128+
// Return type is exactly int.
129+
if (x == 0) {
130+
num tmp3 = x;
131+
return tmp3; // Does not allow returning a supertype of int.
132+
// ^^^^
133+
// [analyzer] unspecified
134+
// [cfe] unspecified
135+
}
136+
// Allows returning int.
137+
return intVar;
138+
}
139+
140+
// No supertype signature, infer `dynamic` for every type.
141+
bar(x) {
142+
// x is Object?.
143+
Object? tmp;
144+
x = tmp; // A top type since Object? is assignable to it.
145+
Null tmp2 = x; // Implicit downcast.
146+
x.arglebargle(); // Unsafe invocations.
147+
148+
// Return type is `dynamic` when calling `bar`.
149+
var ret = bar(x);
150+
ret = tmp;
151+
tmp2 = ret;
152+
ret.arglebargle();
153+
154+
// And definitely a top type when returning.
155+
return tmp;
156+
}
157+
}
158+
159+
/// Do not inherit `required`.
160+
class IReq {
161+
void foo({required int x}) {}
162+
}
163+
164+
class CInvalid8 implements IReq {
165+
// Do not inherit `required` if there is a type.
166+
foo({num x}) {}
167+
// ^
168+
// [analyzer] COMPILE_TIME_ERROR.MISSING_DEFAULT_VALUE_FOR_PARAMETER
169+
// [cfe] unspecified
170+
}
171+
172+
class CInvalid9 implements IReq {
173+
// Do not inherit `required` if there is no type.
174+
void foo({x}) {}
175+
// ^
176+
// [analyzer] COMPILE_TIME_ERROR.MISSING_DEFAULT_VALUE_FOR_PARAMETER
177+
// [cfe] unspecified
178+
}
179+
180+
abstract class INonNullable {
181+
foo({num x});
182+
}
183+
184+
class CInvalid10 implements INonNullable {
185+
// Inherit type even when it would be invalid in the supertype, if it had been
186+
// non-abstract.
187+
foo({x}) {}
188+
// ^
189+
// [analyzer] COMPILE_TIME_ERROR.MISSING_DEFAULT_VALUE_FOR_PARAMETER
190+
// [cfe] unspecified
191+
}
192+
193+
/// Do not inherit default value implicitly.
194+
class IDefault {
195+
int foo({int x = 0}) => x;
196+
}
197+
198+
class CInvalid11 implements IDefault {
199+
foo({x}) => x;
200+
// ^
201+
// [analyzer] COMPILE_TIME_ERROR.MISSING_DEFAULT_VALUE_FOR_PARAMETER
202+
// [cfe] unspecified
203+
// ^
204+
// [analyzer] STATIC_WARNING.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED
205+
}
206+
207+
// Inherits type variables, even with different names.
208+
class CGeneric<T> {
209+
T foo(T x) => x;
210+
211+
R bar<R>(R x) => x;
212+
}
213+
214+
class CInheritGeneric<S> implements CGeneric<S> {
215+
foo(x) {
216+
// x has type exactly S.
217+
// Assignable both ways.
218+
S tmp = x;
219+
x = tmp;
220+
// And not dynamic.
221+
/*indent*/ x.arglebargle();
222+
// ^^^^^^^^^^^
223+
// [analyzer] unspecified
224+
// [cfe] unspecified
225+
226+
// Return type is S.
227+
tmp = foo(x);
228+
return tmp;
229+
}
230+
231+
bar<Q>(x) {
232+
// x has type exactly Q.
233+
// Assignable both ways.
234+
Q tmp = x;
235+
x = tmp;
236+
// And not dynamic.
237+
/*indent*/ x.arglebargle();
238+
// ^^^^^^^^^^^
239+
// [analyzer] unspecified
240+
// [cfe] unspecified
241+
242+
// Return type is Q.
243+
tmp = bar<Q>(x);
244+
return tmp;
245+
}
246+
}
247+
248+
main() {}

0 commit comments

Comments
 (0)