Skip to content

Commit c3e9133

Browse files
stereotype441Commit Queue
authored andcommitted
Test interactions between null-aware accesses and field promotion.
As discussed in dart-lang/language#4344, the current implementation has some inconsistencies in how null-aware accesses interact with field promotion. I intend to fix these inconsistencies as part of the `sound-flow-analysis` language feature. In this CL, I'm adding a regression test of the behavior that's currently implemented (as of Dart 3.8), to help me make sure that when I implement the new behavior, the changes will only take effect when `sound-flow-analysis` is enabled. Bug: dart-lang/language#4344 Change-Id: If52a0ad044399904e3389af2130ca802efdd7058 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425922 Reviewed-by: Lasse Nielsen <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent 29e33b0 commit c3e9133

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// Tests the interactions between field promotion and various forms of
6+
// null-aware accesses, when `sound-flow-analysis` is disabled.
7+
8+
// Note that there is (as of this writing) no specification for field promotion;
9+
// this test reflects the current behavior as of Dart 3.8.
10+
11+
// See https://github.com/dart-lang/language/issues/4344, where I've proposed
12+
// improving these behaviors as part of the `sound-flow-analysis` feature.
13+
14+
// @dart = 3.8
15+
16+
// ignore_for_file: invalid_null_aware_operator
17+
18+
import 'package:expect/static_type_helper.dart';
19+
20+
class A {
21+
final int? _i;
22+
A(this._i);
23+
}
24+
25+
// Inside a non-cascaded null-aware field access, prior promotions do not take
26+
// effect.
27+
void nonCascadedPriorPromotion(A a) {
28+
if (a._i != null) {
29+
// `a._i` is promoted now.
30+
a._i.expectStaticType<Exactly<int>>();
31+
// But `a?._i` is not promoted.
32+
a?._i.expectStaticType<Exactly<int?>>();
33+
}
34+
}
35+
36+
// A promotion that occurs inside a non-cascaded null-aware field access does
37+
// not produce a continued effect after the field access.
38+
void nonCascadedPromotionAfter(A a) {
39+
a?._i!;
40+
// `a._i` is not promoted.
41+
a._i.expectStaticType<Exactly<int?>>();
42+
// If the access is not null-aware, it promotes.
43+
a._i!;
44+
a._i.expectStaticType<Exactly<int>>();
45+
}
46+
47+
// Inside a cascaded null-aware field access, prior promotions do take effect.
48+
void cascadedPriorPromotion(A a) {
49+
if (a._i != null) {
50+
// `a._i` is promoted now.
51+
a._i.expectStaticType<Exactly<int>>();
52+
// And `a?.._i` is promoted.
53+
a?.._i.expectStaticType<Exactly<int>>();
54+
}
55+
}
56+
57+
// A promotion that occurs inside a cascaded null-aware field access does not
58+
// produce a continued effect after the cascade.
59+
void cascadedPromotionAfter(A a) {
60+
// `a._i` is promoted inside the cascade
61+
a
62+
?.._i!
63+
.._i.expectStaticType<Exactly<int>>();
64+
// But the promotion is not retained afterwards.
65+
a._i.expectStaticType<Exactly<int?>>();
66+
// If the cascade expression is not null aware, the promotion is retained.
67+
a
68+
.._i!
69+
.._i.expectStaticType<Exactly<int>>();
70+
a._i.expectStaticType<Exactly<int>>();
71+
}
72+
73+
// A promotion that occurs inside a cascaded null-aware field access does not
74+
// produce an effect on the value of the cascade expression.
75+
void cascadedPromotionValue(A a) {
76+
// `a._i` is promoted inside the cascade
77+
(a
78+
?.._i!
79+
.._i.expectStaticType<Exactly<int>>())
80+
// But the promotion is not retained in the value of the cascade expression
81+
._i
82+
.expectStaticType<Exactly<int?>>();
83+
// If the cascade expression is not null aware, the promotion is retained.
84+
(a
85+
.._i!
86+
.._i.expectStaticType<Exactly<int>>())
87+
._i
88+
.expectStaticType<Exactly<int>>();
89+
}
90+
91+
main() {
92+
nonCascadedPriorPromotion(A(0));
93+
nonCascadedPromotionAfter(A(0));
94+
cascadedPriorPromotion(A(0));
95+
cascadedPromotionAfter(A(0));
96+
cascadedPromotionValue(A(0));
97+
}

0 commit comments

Comments
 (0)