Skip to content

Commit be4e79e

Browse files
scheglovCommit Queue
authored and
Commit Queue
committed
Issue 52313. Support for FutureOr in canBeSubtypeOf().
Bug: #52313 Change-Id: I95792ce457e7a1f3f9d8d4f61565b28a2eb0c004 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/302442 Commit-Queue: Konstantin Shcheglov <[email protected]> Reviewed-by: Samuel Rawlins <[email protected]>
1 parent c4aa754 commit be4e79e

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

pkg/analyzer/lib/src/dart/element/type_system.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,22 @@ class TypeSystemImpl implements TypeSystem {
182182
return true;
183183
}
184184

185+
// FutureOr<T> = T || Future<T>
186+
// So, we attempt to match both to the right.
187+
if (left.isDartAsyncFutureOr) {
188+
final base = futureOrBase(left);
189+
final future = typeProvider.futureType(base);
190+
return canBeSubtypeOf(base, right) || canBeSubtypeOf(future, right);
191+
}
192+
193+
// FutureOr<T> = T || Future<T>
194+
// So, we attempt to match both to the left.
195+
if (right.isDartAsyncFutureOr) {
196+
final base = futureOrBase(right);
197+
final future = typeProvider.futureType(base);
198+
return canBeSubtypeOf(left, base) || canBeSubtypeOf(left, future);
199+
}
200+
185201
bool canBeSubtypeOfInterfaces(InterfaceType left, InterfaceType right) {
186202
assert(left.element == right.element);
187203
final leftArguments = left.typeArguments;

pkg/analyzer/test/src/diagnostics/pattern_never_matches_value_type_test.dart

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,33 @@ mixin class R {}
217217
''');
218218
}
219219

220+
test_interfaceType2_matchedFinal_requiredFutureOrIt() async {
221+
await assertNoErrorsInCode('''
222+
import 'dart:async';
223+
224+
final class A {}
225+
226+
void f(A x) {
227+
if (x case FutureOr<A> _) {}
228+
}
229+
''');
230+
}
231+
232+
test_interfaceType2_matchedFinal_requiredFutureOrOther() async {
233+
await assertErrorsInCode('''
234+
import 'dart:async';
235+
236+
final class A {}
237+
class B {}
238+
239+
void f(A x) {
240+
if (x case FutureOr<B> _) {}
241+
}
242+
''', [
243+
error(WarningCode.PATTERN_NEVER_MATCHES_VALUE_TYPE, 78, 11),
244+
]);
245+
}
246+
220247
test_interfaceType2_matchedFinal_requiredUnrelated() async {
221248
await assertErrorsInCode('''
222249
void f(A x) {
@@ -230,6 +257,69 @@ class R {}
230257
]);
231258
}
232259

260+
test_interfaceType2_matchedFutureFinal_requiredFutureOrIt() async {
261+
await assertNoErrorsInCode('''
262+
import 'dart:async';
263+
264+
final class A {}
265+
266+
void f(Future<A> x) {
267+
if (x case FutureOr<A> _) {}
268+
}
269+
''');
270+
}
271+
272+
test_interfaceType2_matchedFutureOrFinal_requiredFutureIt() async {
273+
await assertNoErrorsInCode('''
274+
import 'dart:async';
275+
276+
final class A {}
277+
278+
void f(FutureOr<A> x) {
279+
if (x case Future<A> _) {}
280+
}
281+
''');
282+
}
283+
284+
test_interfaceType2_matchedFutureOrFinal_requiredFutureOrIt() async {
285+
await assertNoErrorsInCode('''
286+
import 'dart:async';
287+
288+
final class A {}
289+
290+
void f(FutureOr<A> x) {
291+
if (x case FutureOr<A> _) {}
292+
}
293+
''');
294+
}
295+
296+
test_interfaceType2_matchedFutureOrFinal_requiredIt() async {
297+
await assertNoErrorsInCode('''
298+
import 'dart:async';
299+
300+
final class A {}
301+
302+
void f(FutureOr<A> x) {
303+
if (x case A _) {}
304+
}
305+
''');
306+
}
307+
308+
/// `Future` is an interface, so there can be a class that implements both
309+
/// `B` and `Future<A>`.
310+
test_interfaceType2_matchedFutureOrFinal_requiredOther() async {
311+
await assertNoErrorsInCode('''
312+
import 'dart:async';
313+
314+
final class A {}
315+
class B {}
316+
317+
void f(FutureOr<A> x) {
318+
if (x case B _) {}
319+
}
320+
''');
321+
}
322+
233323
test_interfaceType2_matchedInt_requiredDouble() async {
234324
await assertNoErrorsInCode('''
235325
void f(int x) {

0 commit comments

Comments
 (0)