Skip to content

Commit 3d27f5c

Browse files
chloestefantsovaCommit Bot
authored and
Commit Bot
committed
[cfe] Adjust nullability of FutureOr in ReplacementVisitor
This fix is analogous to that made in _TypeSubstitutor in https://dart-review.googlesource.com/c/sdk/+/240049, but made for ReplacementVisitor. Closes #48768 Change-Id: Ie3ac8fe834210d1249cbd5bd3d68b416f9efc034 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/240722 Auto-Submit: Chloe Stefantsova <[email protected]> Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent f2b5ba8 commit 3d27f5c

10 files changed

+132
-2
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright (c) 2022, 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+
foo(dynamic y) async {
6+
var a = await (<X>(List<X> Function() x, X x2) => x2)(() => y, throw 0);
7+
}
8+
9+
main() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
static method foo(dynamic y) → dynamic async /* futureValueType= dynamic */ {
6+
dynamic a = await(<X extends core::Object? = dynamic>(() → core::List<X%> x, X% x2) → X% => x2)<FutureOr<dynamic>>(() → core::List<FutureOr<dynamic>> => y as{TypeError,ForDynamic,ForNonNullableByDefault} core::List<FutureOr<dynamic>>, throw 0){(() → core::List<FutureOr<dynamic>?>, FutureOr<dynamic>?) → FutureOr<dynamic>?};
7+
}
8+
static method main() → dynamic {}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:async" as asy;
4+
import "dart:core" as core;
5+
6+
static method foo(dynamic y) → dynamic /* futureValueType= dynamic */ /* originally async */ {
7+
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
8+
core::bool* :is_sync = false;
9+
dynamic :return_value;
10+
(dynamic) → dynamic :async_op_then;
11+
(core::Object, core::StackTrace) → dynamic :async_op_error;
12+
core::int :await_jump_var = 0;
13+
dynamic :await_ctx_var;
14+
dynamic :saved_try_context_var0;
15+
function :async_op(dynamic :result_or_exception, dynamic :stack_trace) → dynamic yielding
16+
try {
17+
#L1:
18+
{
19+
[yield] let dynamic #t1 = asy::_awaitHelper((<X extends core::Object? = dynamic>(() → core::List<X%> x, X% x2) → X% => x2)<FutureOr<dynamic>>(() → core::List<FutureOr<dynamic>> => y as{TypeError,ForDynamic,ForNonNullableByDefault} core::List<FutureOr<dynamic>>, throw 0){(() → core::List<FutureOr<dynamic>?>, FutureOr<dynamic>?) → FutureOr<dynamic>?}, :async_op_then, :async_op_error) in null;
20+
dynamic a = :result_or_exception;
21+
}
22+
asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
23+
return;
24+
}
25+
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
26+
asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
27+
}
28+
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
29+
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
30+
:async_op(null, null){() → dynamic};
31+
:is_sync = true;
32+
return :async_future;
33+
}
34+
static method main() → dynamic {}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
foo(dynamic y) async {}
2+
main() {}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
foo(dynamic y) async {}
2+
main() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
static method foo(dynamic y) → dynamic async /* futureValueType= dynamic */ {
6+
dynamic a = await(<X extends core::Object? = dynamic>(() → core::List<X%> x, X% x2) → X% => x2)<FutureOr<dynamic>>(() → core::List<FutureOr<dynamic>> => y as{TypeError,ForDynamic,ForNonNullableByDefault} core::List<FutureOr<dynamic>>, throw 0){(() → core::List<FutureOr<dynamic>?>, FutureOr<dynamic>?) → FutureOr<dynamic>?};
7+
}
8+
static method main() → dynamic {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
static method foo(dynamic y) → dynamic async /* futureValueType= dynamic */ {
6+
dynamic a = await(<X extends core::Object? = dynamic>(() → core::List<X%> x, X% x2) → X% => x2)<FutureOr<dynamic>>(() → core::List<FutureOr<dynamic>> => y as{TypeError,ForDynamic,ForNonNullableByDefault} core::List<FutureOr<dynamic>>, throw 0){(() → core::List<FutureOr<dynamic>?>, FutureOr<dynamic>?) → FutureOr<dynamic>?};
7+
}
8+
static method main() → dynamic {}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
4+
static method foo(dynamic y) → dynamic async
5+
;
6+
static method main() → dynamic
7+
;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:async" as asy;
4+
import "dart:core" as core;
5+
6+
static method foo(dynamic y) → dynamic /* futureValueType= dynamic */ /* originally async */ {
7+
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
8+
core::bool* :is_sync = false;
9+
dynamic :return_value;
10+
(dynamic) → dynamic :async_op_then;
11+
(core::Object, core::StackTrace) → dynamic :async_op_error;
12+
core::int :await_jump_var = 0;
13+
dynamic :await_ctx_var;
14+
dynamic :saved_try_context_var0;
15+
function :async_op(dynamic :result_or_exception, dynamic :stack_trace) → dynamic yielding
16+
try {
17+
#L1:
18+
{
19+
[yield] let dynamic #t1 = asy::_awaitHelper((<X extends core::Object? = dynamic>(() → core::List<X%> x, X% x2) → X% => x2)<FutureOr<dynamic>>(() → core::List<FutureOr<dynamic>> => y as{TypeError,ForDynamic,ForNonNullableByDefault} core::List<FutureOr<dynamic>>, throw 0){(() → core::List<FutureOr<dynamic>?>, FutureOr<dynamic>?) → FutureOr<dynamic>?}, :async_op_then, :async_op_error) in null;
20+
dynamic a = :result_or_exception;
21+
}
22+
asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
23+
return;
24+
}
25+
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
26+
asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
27+
}
28+
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
29+
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
30+
:async_op(null, null){() → dynamic};
31+
:is_sync = true;
32+
return :async_future;
33+
}
34+
static method main() → dynamic {}

pkg/kernel/lib/src/replacement_visitor.dart

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,26 @@ class ReplacementVisitor implements DartTypeVisitor1<DartType?, int> {
171171
// No nullability or type arguments needed to be substituted.
172172
return null;
173173
} else {
174-
return new FutureOrType(newTypeArgument ?? node.typeArgument,
175-
newNullability ?? node.declaredNullability);
174+
newTypeArgument ??= node.typeArgument;
175+
newNullability ??= node.declaredNullability;
176+
177+
// The top-level nullability of a FutureOr should remain the same, with
178+
// the exception of the case of [Nullability.undetermined]. In that case
179+
// it remains undetermined if the nullability of [typeArgument] is
180+
// undetermined, and otherwise it should become
181+
// [Nullability.nonNullable].
182+
Nullability adjustedNullability;
183+
if (newNullability == Nullability.undetermined) {
184+
if (newTypeArgument.nullability == Nullability.undetermined) {
185+
adjustedNullability = Nullability.undetermined;
186+
} else {
187+
adjustedNullability = Nullability.nonNullable;
188+
}
189+
} else {
190+
adjustedNullability = newNullability;
191+
}
192+
193+
return new FutureOrType(newTypeArgument, adjustedNullability);
176194
}
177195
}
178196

0 commit comments

Comments
 (0)