mirror of
https://github.com/dart-lang/sdk
synced 2024-10-03 00:45:16 +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
|
## 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
|
### Dart Runtime
|
||||||
|
|
||||||
- The Dart VM only executes sound null safe code, running of unsound null
|
- The Dart VM only executes sound null safe code, running of unsound null
|
||||||
|
|
|
@ -857,9 +857,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase
|
||||||
@override
|
@override
|
||||||
ExpressionInferenceResult visitAwaitExpression(
|
ExpressionInferenceResult visitAwaitExpression(
|
||||||
AwaitExpression node, DartType typeContext) {
|
AwaitExpression node, DartType typeContext) {
|
||||||
if (!typeSchemaEnvironment.isEmptyContext(typeContext)) {
|
if (typeContext is DynamicType) {
|
||||||
typeContext = wrapFutureOrType(typeContext);
|
typeContext = const UnknownType();
|
||||||
}
|
}
|
||||||
|
typeContext = wrapFutureOrType(typeContext);
|
||||||
ExpressionInferenceResult operandResult = inferExpression(
|
ExpressionInferenceResult operandResult = inferExpression(
|
||||||
node.operand, typeContext,
|
node.operand, typeContext,
|
||||||
isVoidAllowed: !isNonNullableByDefault);
|
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 a new issue