[cfe] Make type inference for if-null expressions consistent with analyzer.

Fixes https://github.com/dart-lang/language/issues/3650.
Fixes https://github.com/dart-lang/sdk/issues/55436.

Bug: https://github.com/dart-lang/language/issues/3650
Change-Id: I30b39221c85713aab10f2edc35625f38e34cae5e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/362100
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
Paul Berry 2024-05-08 20:05:18 +00:00 committed by Commit Queue
parent 62ec713bab
commit 5b020f2ee6
3 changed files with 24 additions and 2 deletions

View file

@ -7,7 +7,15 @@
match the behavior of the analyzer. This change is not expected to make any match the behavior of the analyzer. This change is not expected to make any
difference in practice. difference in practice.
- **Breaking Change** [#55436][]: The context used by the compiler to perform
type inference on the right hand side of an "if-null" expression (`e1 ?? e2`)
has been changed to match the behavior of the analyzer. change is expected to
have low impact on real-world code. But in principle it could cause
compile-time errors or changes in runtime behavior by changing inferred
types. The old behavior can be restored by supplying explicit types.
[#55418]: https://github.com/dart-lang/sdk/issues/55418 [#55418]: https://github.com/dart-lang/sdk/issues/55418
[#55436]: https://github.com/dart-lang/sdk/issues/55436
### Dart Runtime ### Dart Runtime

View file

@ -1931,9 +1931,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase
flowAnalysis.ifNullExpression_rightBegin(node.left, t1); flowAnalysis.ifNullExpression_rightBegin(node.left, t1);
// - Let `T2` be the type of `e2` inferred with context type `J`, where: // - Let `T2` be the type of `e2` inferred with context type `J`, where:
// - If `K` is `_`, `J = T1`. // - If `K` is `_` or `dynamic`, `J = T1`.
DartType j; DartType j;
if (typeContext is UnknownType) { if (typeContext is UnknownType || typeContext is DynamicType) {
j = t1; j = t1;
} else } else
// - Otherwise, `J = K`. // - Otherwise, `J = K`.

View file

@ -0,0 +1,14 @@
// 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 if-null expression is analyzed in a `dynamic` context, the
// context for the RHS is taken from the static type of the LHS (see
// https://github.com/dart-lang/language/issues/3650).
import '../static_type_helper.dart';
main() async {
dynamic x =
(null as List<int>?) ?? ([]..expectStaticType<Exactly<List<int>>>());
}