[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
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
[#55436]: https://github.com/dart-lang/sdk/issues/55436
### Dart Runtime

View file

@ -1931,9 +1931,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase
flowAnalysis.ifNullExpression_rightBegin(node.left, t1);
// - 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;
if (typeContext is UnknownType) {
if (typeContext is UnknownType || typeContext is DynamicType) {
j = t1;
} else
// - 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>>>());
}