Migration: Properly handle `await`s of custom future classes.
Bug: https://b.corp.google.com/issues/200651131
Change-Id: Ia06066783a9107848f85bc234b7612a55f54c9c9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/214069
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index 62cd9a3..078631a 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -489,9 +489,12 @@
@override
DecoratedType visitAwaitExpression(AwaitExpression node) {
var expressionType = _dispatch(node.expression)!;
- // TODO(paulberry) Handle subclasses of Future.
- if (expressionType.type!.isDartAsyncFuture ||
- expressionType.type!.isDartAsyncFutureOr) {
+ var type = expressionType.type!;
+ if (_typeSystem.isSubtypeOf(type, typeProvider.futureDynamicType)) {
+ expressionType = _decoratedClassHierarchy!
+ .asInstanceOf(expressionType, typeProvider.futureElement)
+ .typeArguments[0]!;
+ } else if (type.isDartAsyncFutureOr) {
expressionType = expressionType.typeArguments[0]!;
}
return expressionType;
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 5307de5..9815198 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -1601,6 +1601,26 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_custom_future() async {
+ var content = '''
+class CustomFuture<T> implements Future<T> {
+ @override
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+f(CustomFuture<List<int>> x) async => (await x).first;
+''';
+ var expected = '''
+class CustomFuture<T> implements Future<T> {
+ @override
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+f(CustomFuture<List<int>> x) async => (await x).first;
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
Future<void> test_data_flow_assignment_field() async {
var content = '''
class C {