[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 https://github.com/dart-lang/sdk/issues/48768 Change-Id: Ie3ac8fe834210d1249cbd5bd3d68b416f9efc034 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/240722 Auto-Submit: Chloe Stefantsova <cstefantsova@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
committed by
Commit Bot
parent
f2b5ba82ab
commit
3d27f5cb79
@@ -0,0 +1,9 @@
|
||||
// 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.
|
||||
|
||||
foo(dynamic y) async {
|
||||
var a = await (<X>(List<X> Function() x, X x2) => x2)(() => y, throw 0);
|
||||
}
|
||||
|
||||
main() {}
|
||||
@@ -0,0 +1,8 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
static method foo(dynamic y) → dynamic async /* futureValueType= dynamic */ {
|
||||
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>?};
|
||||
}
|
||||
static method main() → dynamic {}
|
||||
@@ -0,0 +1,34 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:async" as asy;
|
||||
import "dart:core" as core;
|
||||
|
||||
static method foo(dynamic y) → dynamic /* futureValueType= dynamic */ /* originally async */ {
|
||||
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
|
||||
core::bool* :is_sync = false;
|
||||
dynamic :return_value;
|
||||
(dynamic) → dynamic :async_op_then;
|
||||
(core::Object, core::StackTrace) → dynamic :async_op_error;
|
||||
core::int :await_jump_var = 0;
|
||||
dynamic :await_ctx_var;
|
||||
dynamic :saved_try_context_var0;
|
||||
function :async_op(dynamic :result_or_exception, dynamic :stack_trace) → dynamic yielding
|
||||
try {
|
||||
#L1:
|
||||
{
|
||||
[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;
|
||||
dynamic a = :result_or_exception;
|
||||
}
|
||||
asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
|
||||
return;
|
||||
}
|
||||
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
|
||||
asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
|
||||
}
|
||||
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
|
||||
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
|
||||
:async_op(null, null){() → dynamic};
|
||||
:is_sync = true;
|
||||
return :async_future;
|
||||
}
|
||||
static method main() → dynamic {}
|
||||
@@ -0,0 +1,2 @@
|
||||
foo(dynamic y) async {}
|
||||
main() {}
|
||||
@@ -0,0 +1,2 @@
|
||||
foo(dynamic y) async {}
|
||||
main() {}
|
||||
@@ -0,0 +1,8 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
static method foo(dynamic y) → dynamic async /* futureValueType= dynamic */ {
|
||||
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>?};
|
||||
}
|
||||
static method main() → dynamic {}
|
||||
@@ -0,0 +1,8 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
static method foo(dynamic y) → dynamic async /* futureValueType= dynamic */ {
|
||||
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>?};
|
||||
}
|
||||
static method main() → dynamic {}
|
||||
@@ -0,0 +1,7 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
|
||||
static method foo(dynamic y) → dynamic async
|
||||
;
|
||||
static method main() → dynamic
|
||||
;
|
||||
@@ -0,0 +1,34 @@
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self;
|
||||
import "dart:async" as asy;
|
||||
import "dart:core" as core;
|
||||
|
||||
static method foo(dynamic y) → dynamic /* futureValueType= dynamic */ /* originally async */ {
|
||||
final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
|
||||
core::bool* :is_sync = false;
|
||||
dynamic :return_value;
|
||||
(dynamic) → dynamic :async_op_then;
|
||||
(core::Object, core::StackTrace) → dynamic :async_op_error;
|
||||
core::int :await_jump_var = 0;
|
||||
dynamic :await_ctx_var;
|
||||
dynamic :saved_try_context_var0;
|
||||
function :async_op(dynamic :result_or_exception, dynamic :stack_trace) → dynamic yielding
|
||||
try {
|
||||
#L1:
|
||||
{
|
||||
[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;
|
||||
dynamic a = :result_or_exception;
|
||||
}
|
||||
asy::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
|
||||
return;
|
||||
}
|
||||
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
|
||||
asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
|
||||
}
|
||||
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
|
||||
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
|
||||
:async_op(null, null){() → dynamic};
|
||||
:is_sync = true;
|
||||
return :async_future;
|
||||
}
|
||||
static method main() → dynamic {}
|
||||
@@ -171,8 +171,26 @@ class ReplacementVisitor implements DartTypeVisitor1<DartType?, int> {
|
||||
// No nullability or type arguments needed to be substituted.
|
||||
return null;
|
||||
} else {
|
||||
return new FutureOrType(newTypeArgument ?? node.typeArgument,
|
||||
newNullability ?? node.declaredNullability);
|
||||
newTypeArgument ??= node.typeArgument;
|
||||
newNullability ??= node.declaredNullability;
|
||||
|
||||
// The top-level nullability of a FutureOr should remain the same, with
|
||||
// the exception of the case of [Nullability.undetermined]. In that case
|
||||
// it remains undetermined if the nullability of [typeArgument] is
|
||||
// undetermined, and otherwise it should become
|
||||
// [Nullability.nonNullable].
|
||||
Nullability adjustedNullability;
|
||||
if (newNullability == Nullability.undetermined) {
|
||||
if (newTypeArgument.nullability == Nullability.undetermined) {
|
||||
adjustedNullability = Nullability.undetermined;
|
||||
} else {
|
||||
adjustedNullability = Nullability.nonNullable;
|
||||
}
|
||||
} else {
|
||||
adjustedNullability = newNullability;
|
||||
}
|
||||
|
||||
return new FutureOrType(newTypeArgument, adjustedNullability);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user