mirror of
https://github.com/dart-lang/sdk
synced 2024-07-03 00:08:46 +00:00
[cfe] Make the context for await expressions consistent with analyzer.
Fixes https://github.com/dart-lang/language/issues/3649. Fixes https://github.com/dart-lang/sdk/issues/55418. Bug: https://github.com/dart-lang/language/issues/3649 Change-Id: Ifb2fe47bb343a357e2338843775f140c01bd8a88 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/361302 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Paul Berry <paulberry@google.com> Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
parent
8c1de038e0
commit
497d6105df
|
@ -1,5 +1,14 @@
|
|||
## 3.5.0
|
||||
|
||||
### Language
|
||||
|
||||
- **Breaking Change** [#55418][]: The context used by the compiler to perform
|
||||
type inference on the operand of an `await` expression has been changed to
|
||||
match the behavior of the analyzer. This change is not expected to make any
|
||||
difference in practice.
|
||||
|
||||
[#55418]: https://github.com/dart-lang/sdk/issues/55418
|
||||
|
||||
### Dart Runtime
|
||||
|
||||
- The Dart VM only executes sound null safe code, running of unsound null
|
||||
|
|
|
@ -857,9 +857,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
|||
@override
|
||||
ExpressionInferenceResult visitAwaitExpression(
|
||||
AwaitExpression node, DartType typeContext) {
|
||||
if (!typeSchemaEnvironment.isEmptyContext(typeContext)) {
|
||||
typeContext = wrapFutureOrType(typeContext);
|
||||
if (typeContext is DynamicType) {
|
||||
typeContext = const UnknownType();
|
||||
}
|
||||
typeContext = wrapFutureOrType(typeContext);
|
||||
ExpressionInferenceResult operandResult = inferExpression(
|
||||
node.operand, typeContext,
|
||||
isVoidAllowed: !isNonNullableByDefault);
|
||||
|
|
47
tests/language/await/await_with_dynamic_context_test.dart
Normal file
47
tests/language/await/await_with_dynamic_context_test.dart
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) 2024, 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.
|
||||
|
||||
// Verify that if an `await` expression is analyzed in a `dynamic` context, it
|
||||
// supplies a context of `FutureOr<_>` to its operand, rather than `dynamic`
|
||||
// (which was the front end behavior prior to fixing
|
||||
// https://github.com/dart-lang/language/issues/3649).
|
||||
|
||||
// Contexts of `FutureOr<_>` and `dynamic` are difficult to distinguish. This
|
||||
// test distinguishes them by awaiting the expression `id(((null as Future<B>?)
|
||||
// ?? (Future.value(C())..expectStaticType<Exactly<Future<C>>>())))`, where `C`
|
||||
// is a class that extends `B`, and `id` is a generic identity function having
|
||||
// type `T Function<T>(T)`.
|
||||
//
|
||||
// This works because, if it is analyzed in context `Future<_>`, then:
|
||||
// - The call to `id` is analyzed in context `Future<_>`.
|
||||
// - Therefore the `??` expression is analyzed in context `Future<_>`.
|
||||
// - Therefore the RHS of `??` is analyzed in context `Future<_>`.
|
||||
// - Therefore downwards inference doesn't impose any constraint on the type
|
||||
// parameter of `Future.value(C())`.
|
||||
// - Therefore `Future.value(C())` gets its type parameter from upwards
|
||||
// inference.
|
||||
// - So it receives a type parameter of `C`.
|
||||
// - So the static type of `Future.value(C())` is `Future<C>`.
|
||||
//
|
||||
// Whereas if it is analyzed in context `dynamic`, then:
|
||||
// - The call to `id` is analyzed in context `dynamic`.
|
||||
// - Therefore the `??` expression is analyzed in context `_`.
|
||||
// - Therefore the static type of the LHS of `??` is used as the context for the
|
||||
// RHS. That is, the RHS is analyzed in context `Future<B>?`.
|
||||
// - Therefore downwards inference constraints the type parameter of
|
||||
// `Future.value(C())` to `B`.
|
||||
// - So the static type of `Future.value(C())` is `Future<B>`.
|
||||
|
||||
import '../static_type_helper.dart';
|
||||
|
||||
class B {}
|
||||
|
||||
class C extends B {}
|
||||
|
||||
T id<T>(T t) => t;
|
||||
|
||||
main() async {
|
||||
dynamic x = await id(((null as Future<B>?) ??
|
||||
(Future.value(C())..expectStaticType<Exactly<Future<C>>>())));
|
||||
}
|
Loading…
Reference in New Issue
Block a user