Skip to content

Commit 2225b6f

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Migration: fix handling of async functions that return FutureOr.
Change-Id: I613d0bfd8340062bb78b20a8fd035d24a4ccdf8d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/155543 Commit-Queue: Paul Berry <paulberry@google.com> Reviewed-by: Samuel Rawlins <srawlins@google.com>
1 parent f907e56 commit 2225b6f

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

pkg/nnbd_migration/lib/src/edge_builder.dart

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2995,11 +2995,26 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
29952995
/// upcast T to that type if possible, skipping the flatten when not
29962996
/// necessary.
29972997
DecoratedType _wrapFuture(DecoratedType type, AstNode node) {
2998-
if (type.type.isDartCoreNull || type.type.isBottom) {
2998+
var dartType = type.type;
2999+
if (dartType.isDartCoreNull || dartType.isBottom) {
29993000
return _futureOf(type, node);
30003001
}
30013002

3002-
if (_typeSystem.isSubtypeOf(type.type, typeProvider.futureDynamicType)) {
3003+
if (dartType is InterfaceType &&
3004+
dartType.element == typeProvider.futureOrElement) {
3005+
var typeArguments = type.typeArguments;
3006+
if (typeArguments.length == 1) {
3007+
// Wrapping FutureOr<T?1>?2 should produce Future<T?3>, where either 1
3008+
// or 2 being nullable causes 3 to become nullable.
3009+
var typeArgument = typeArguments[0];
3010+
return _futureOf(
3011+
typeArgument
3012+
.withNode(NullabilityNode.forLUB(typeArgument.node, type.node)),
3013+
node);
3014+
}
3015+
}
3016+
3017+
if (_typeSystem.isSubtypeOf(dartType, typeProvider.futureDynamicType)) {
30033018
return _decoratedClassHierarchy.asInstanceOf(
30043019
type, typeProvider.futureDynamicType.element);
30053020
}

pkg/nnbd_migration/test/api_test.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5583,6 +5583,20 @@ test() => C.one();
55835583
await _checkSingleFileChanges(content, expected);
55845584
}
55855585

5586+
Future<void> test_return_future_or_null_from_async_method() async {
5587+
var content = '''
5588+
import 'dart:async';
5589+
Future<Null> f() async => g();
5590+
FutureOr<Null> g() => null;
5591+
''';
5592+
var expected = '''
5593+
import 'dart:async';
5594+
Future<Null> f() async => g();
5595+
FutureOr<Null> g() => null;
5596+
''';
5597+
await _checkSingleFileChanges(content, expected);
5598+
}
5599+
55865600
Future<void> test_setter_overrides_implicit_setter() async {
55875601
var content = '''
55885602
class A {

pkg/nnbd_migration/test/edge_builder_test.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6812,6 +6812,29 @@ int g() => 1;
68126812
// No assertions; just checking that it doesn't crash.
68136813
}
68146814

6815+
Future<void> test_return_from_async_futureOr_to_future() async {
6816+
await analyze('''
6817+
import 'dart:async';
6818+
Future<Object> f(FutureOr<int> x) async => x;
6819+
''');
6820+
var lubNodeMatcher = anyNode;
6821+
assertEdge(lubNodeMatcher, decoratedTypeAnnotation('Object').node,
6822+
hard: false, checkable: false);
6823+
var lubNode = lubNodeMatcher.matchingNode as NullabilityNodeForLUB;
6824+
expect(lubNode.left, same(decoratedTypeAnnotation('int> x').node));
6825+
expect(lubNode.right, same(decoratedTypeAnnotation('FutureOr<int>').node));
6826+
}
6827+
6828+
Future<void> test_return_from_async_list_to_future() async {
6829+
await analyze('''
6830+
import 'dart:async';
6831+
Future<Object> f(List<int> x) async => x;
6832+
''');
6833+
assertEdge(decoratedTypeAnnotation('List<int>').node,
6834+
decoratedTypeAnnotation('Object').node,
6835+
hard: false, checkable: false);
6836+
}
6837+
68156838
Future<void> test_return_from_async_null() async {
68166839
await analyze('''
68176840
Future<int> f() async {

0 commit comments

Comments
 (0)