blob: 9dc9ec17ffafea91ab2e00f16d19741c98a56d39 [file] [log] [blame]
// Copyright (c) 2022, 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.
// Verifies that 'await' should check if the awaited value has a correct
// Future<T> type before awaiting it. A Future of incompatible type
// should not be awaited.
//
// Regression test for https://github.com/dart-lang/sdk/issues/49396.
// Requirements=nnbd-strong
import 'dart:async';
import 'package:expect/expect.dart';
import '../static_type_helper.dart';
class A {}
abstract class B<X> extends A implements Future<X> {
Future<X> get fut;
asStream() => fut.asStream();
catchError(error, {test}) => fut.catchError(error, test: test);
then<R>(onValue, {onError}) => fut.then(onValue, onError: onError);
timeout(timeLimit, {onTimeout}) =>
fut.timeout(timeLimit, onTimeout: onTimeout);
whenComplete(action) => fut.whenComplete(action);
}
class C extends B<Object?> {
final Future<Object?> fut = Future.value(CompletelyUnrelated());
}
class CompletelyUnrelated {}
class C1 extends A {}
class C2 extends B<C1> {
final Future<C1> fut = Future.value(C1());
}
void main() async {
final Object o = Future<Object?>.value();
var o2 = await o; // Remains a future.
o2.expectStaticType<Exactly<Object>>();
Expect.isTrue(o2 is Future<Object?>);
Expect.identical(o2, o);
final FutureOr<Object> x = Future<Object?>.value();
var x2 = await x; // Remains a future.
x2.expectStaticType<Exactly<Object>>();
Expect.isTrue(x2 is Future<Object?>);
Expect.identical(x2, x);
final FutureOr<Future<int>> y = Future<int>.value(1);
var y2 = await y; // Remains a `Future<int>`.
y2.expectStaticType<Exactly<Future<int>>>();
Expect.isTrue(y2 is Future<int>);
Expect.identical(y2, y);
A a = C();
var a2 = await a; // Remains an `A`.
a2.expectStaticType<Exactly<A>>();
Expect.isTrue(a2 is A);
Expect.identical(a2, a);
Future<void> f<X extends Object>(X x) async {
var x2 = await x; // Remains a `Future<Object?>`.
Expect.isTrue(x2 is Future<Object?>);
Expect.identical(x2, x);
}
await f(Future<Object?>.value(null));
Future<void> g<X extends A>(X x) async {
var x2 = await x; // The future is awaited.
Expect.isTrue(x2 is C1);
Expect.notIdentical(x2, x);
}
await g<A>(C2());
}