Version 2.11.0-196.0.dev
Merge commit 'e933e91aaa29531ccb32d5adec853270eedbedae' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index 037629d..1a1c1df 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -1278,8 +1278,7 @@
/// the state actually leave `this` unchanged and return a new state object.
@visibleForTesting
class FlowModel<Variable, Type> {
- /// Indicates whether this point in the control flow is reachable.
- final bool reachable;
+ final Reachability reachable;
/// For each variable being tracked by flow analysis, the variable's model.
///
@@ -1303,7 +1302,7 @@
/// Creates a state object with the given [reachable] status. All variables
/// are assumed to be unpromoted and already assigned, so joining another
/// state with this one will have no effect on it.
- FlowModel(bool reachable)
+ FlowModel(Reachability reachable)
: this.withInfo(
reachable,
const {},
@@ -1312,6 +1311,7 @@
@visibleForTesting
FlowModel.withInfo(this.reachable, this.variableInfo)
: _freshVariableInfo = new VariableModel.fresh() {
+ assert(reachable != null);
assert(() {
for (VariableModel<Variable, Type> value in variableInfo.values) {
assert(value != null);
@@ -1484,7 +1484,8 @@
TypeOperations<Variable, Type> typeOperations,
FlowModel<Variable, Type> other,
Set<Variable> unsafe) {
- bool newReachable = reachable && other.reachable;
+ Reachability newReachable =
+ Reachability.restrict(reachable, other.reachable);
Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
<Variable, VariableModel<Variable, Type>>{};
@@ -1528,11 +1529,17 @@
/// Updates the state to indicate that the control flow path is unreachable.
FlowModel<Variable, Type> setUnreachable() {
- if (!reachable) return this;
+ if (!reachable.locallyReachable) return this;
- return new FlowModel<Variable, Type>.withInfo(false, variableInfo);
+ return new FlowModel<Variable, Type>.withInfo(
+ reachable.setUnreachable(), variableInfo);
}
+ /// Returns a [FlowModel] indicating the result of creating a control flow
+ /// split. See [Reachability.split] for more information.
+ FlowModel<Variable, Type> split() =>
+ new FlowModel<Variable, Type>.withInfo(reachable.split(), variableInfo);
+
@override
String toString() => '($reachable, $variableInfo)';
@@ -1646,6 +1653,11 @@
this, modelIfSuccessful, modelIfFailed);
}
+ /// Returns a [FlowModel] indicating the result of removing a control flow
+ /// split. See [Reachability.unsplit] for more information.
+ FlowModel<Variable, Type> unsplit() =>
+ new FlowModel<Variable, Type>.withInfo(reachable.unsplit(), variableInfo);
+
/// Updates the state to indicate that an assignment was made to the given
/// [variable]. The variable is marked as definitely assigned, and any
/// previous type promotion is removed.
@@ -1686,12 +1698,12 @@
}
List<Type> newPromotedTypes = info.promotedTypes;
- bool newReachable = reachable;
+ Reachability newReachable = reachable;
if (promotedType != null) {
newPromotedTypes =
VariableModel._addToPromotedTypes(info.promotedTypes, promotedType);
if (typeOperations.isNever(promotedType)) {
- newReachable = false;
+ newReachable = reachable.setUnreachable();
}
}
@@ -1710,7 +1722,7 @@
/// with [model].
FlowModel<Variable, Type> _updateVariableInfo(
Variable variable, VariableModel<Variable, Type> model,
- {bool reachable}) {
+ {Reachability reachable}) {
reachable ??= this.reachable;
Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
new Map<Variable, VariableModel<Variable, Type>>.from(variableInfo);
@@ -1736,10 +1748,18 @@
if (first == null) return second;
if (second == null) return first;
- if (first.reachable && !second.reachable) return first;
- if (!first.reachable && second.reachable) return second;
+ assert(identical(first.reachable.parent, second.reachable.parent));
+ if (first.reachable.locallyReachable &&
+ !second.reachable.locallyReachable) {
+ return first;
+ }
+ if (!first.reachable.locallyReachable &&
+ second.reachable.locallyReachable) {
+ return second;
+ }
- bool newReachable = first.reachable || second.reachable;
+ Reachability newReachable =
+ Reachability.join(first.reachable, second.reachable);
Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
FlowModel.joinVariableInfo(typeOperations, first.variableInfo,
second.variableInfo, emptyVariableMap);
@@ -1793,7 +1813,7 @@
static FlowModel<Variable, Type> _identicalOrNew<Variable, Type>(
FlowModel<Variable, Type> first,
FlowModel<Variable, Type> second,
- bool newReachable,
+ Reachability newReachable,
Map<Variable, VariableModel<Variable, Type>> newVariableInfo) {
if (first.reachable == newReachable &&
identical(first.variableInfo, newVariableInfo)) {
@@ -1829,6 +1849,101 @@
}
}
+/// Immutable data structure modeling the reachability of the given point in the
+/// source code. Reachability is tracked relative to checkpoints occurring
+/// previously along the control flow path leading up to the current point in
+/// the program. A given point is said to be "locally reachable" if it is
+/// reachable from the most recent checkpoint, and "overall reachable" if it is
+/// reachable from the top of the function.
+@visibleForTesting
+class Reachability {
+ /// Model of the initial reachability state of the function being analyzed.
+ static const Reachability initial = const Reachability._initial();
+
+ /// Reachability of the checkpoint this reachability is relative to, or `null`
+ /// if there is no checkpoint. Reachabilities form a tree structure that
+ /// mimics the control flow of the code being analyzed, so this is called the
+ /// "parent".
+ final Reachability parent;
+
+ /// Whether this point in the source code is considered reachable from the
+ /// most recent checkpoint.
+ final bool locallyReachable;
+
+ /// Whether this point in the source code is considered reachable from the
+ /// beginning of the function being analyzed.
+ final bool overallReachable;
+
+ Reachability._(this.parent, this.locallyReachable, this.overallReachable) {
+ assert(overallReachable ==
+ (locallyReachable && (parent?.overallReachable ?? true)));
+ }
+
+ const Reachability._initial()
+ : parent = null,
+ locallyReachable = true,
+ overallReachable = true;
+
+ /// Returns a reachability with the same checkpoint as `this`, but where the
+ /// current point in the program is considered locally unreachable.
+ Reachability setUnreachable() {
+ if (!locallyReachable) return this;
+ return new Reachability._(parent, false, false);
+ }
+
+ /// Returns a new reachability whose checkpoint is the current point of
+ /// execution. This models flow control within a control flow split, e.g.
+ /// inside an `if` statement.
+ Reachability split() => new Reachability._(this, true, overallReachable);
+
+ @override
+ String toString() {
+ List<bool> values = [];
+ for (Reachability node = this; node != null; node = node.parent) {
+ values.add(node.locallyReachable);
+ }
+ return '[${values.join(', ')}]';
+ }
+
+ /// Returns a reachability that drops the most recent checkpoint but maintains
+ /// the same notion of reachability relative to the previous two checkpoints.
+ Reachability unsplit() {
+ if (locallyReachable) {
+ return parent;
+ } else {
+ return parent.setUnreachable();
+ }
+ }
+
+ /// Combines two reachabilities (both of which must be based on the same
+ /// checkpoint), where the code is considered reachable from the checkpoint
+ /// iff either argument is reachable from the checkpoint.
+ ///
+ /// This is used as part of the "join" operation.
+ static Reachability join(Reachability r1, Reachability r2) {
+ assert(identical(r1.parent, r2.parent));
+ if (r2.locallyReachable) {
+ return r2;
+ } else {
+ return r1;
+ }
+ }
+
+ /// Combines two reachabilities (both of which must be based on the same
+ /// checkpoint), where the code is considered reachable from the checkpoint
+ /// iff both arguments are reachable from the checkpoint.
+ ///
+ /// This is used as part of the "restrict" operation.
+ static Reachability restrict(Reachability r1, Reachability r2) {
+ assert(identical(r1.parent, r2.parent));
+ if (r2.locallyReachable) {
+ return r1;
+ } else {
+ return r2;
+ }
+ }
+}
+
/// Enum representing the different classifications of types that can be
/// returned by [TypeOperations.classifyType].
enum TypeClassification {
@@ -2505,11 +2620,11 @@
final AssignedVariables<Node, Variable> _assignedVariables;
_FlowAnalysisImpl(this.typeOperations, this._assignedVariables) {
- _current = new FlowModel<Variable, Type>(true);
+ _current = new FlowModel<Variable, Type>(Reachability.initial);
}
@override
- bool get isReachable => _current.reachable;
+ bool get isReachable => _current.reachable.overallReachable;
@override
void asExpression_end(Expression subExpression, Type type) {
@@ -2671,6 +2786,7 @@
@override
void finish() {
assert(_stack.isEmpty);
+ assert(_current.reachable.parent == null);
}
@override
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
index f90a68a..16ae7ff 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
@@ -1015,8 +1015,8 @@
});
test(
- 'functionExpression_end does not propagate "definitely unassigned" data',
- () {
+ 'functionExpression_end does not propagate "definitely unassigned" '
+ 'data', () {
var h = _Harness();
var x = h.addVar('x', 'int');
var functionNode = _Node();
@@ -2210,14 +2210,96 @@
});
});
+ group('Reachability', () {
+ test('initial state', () {
+ expect(Reachability.initial.parent, isNull);
+ expect(Reachability.initial.locallyReachable, true);
+ expect(Reachability.initial.overallReachable, true);
+ });
+
+ test('split', () {
+ var reachableSplit = Reachability.initial.split();
+ expect(reachableSplit.parent, same(Reachability.initial));
+ expect(reachableSplit.overallReachable, true);
+ expect(reachableSplit.locallyReachable, true);
+ var unreachable = reachableSplit.setUnreachable();
+ var unreachableSplit = unreachable.split();
+ expect(unreachableSplit.parent, same(unreachable));
+ expect(unreachableSplit.overallReachable, false);
+ expect(unreachableSplit.locallyReachable, true);
+ });
+
+ test('unsplit', () {
+ var base = Reachability.initial.split();
+ var reachableSplit = base.split();
+ var reachableSplitUnsplit = reachableSplit.unsplit();
+ expect(reachableSplitUnsplit.parent, same(base.parent));
+ expect(reachableSplitUnsplit.overallReachable, true);
+ expect(reachableSplitUnsplit.locallyReachable, true);
+ var reachableSplitUnreachable = reachableSplit.setUnreachable();
+ var reachableSplitUnreachableUnsplit =
+ reachableSplitUnreachable.unsplit();
+ expect(reachableSplitUnreachableUnsplit.parent, same(base.parent));
+ expect(reachableSplitUnreachableUnsplit.overallReachable, false);
+ expect(reachableSplitUnreachableUnsplit.locallyReachable, false);
+ var unreachable = base.setUnreachable();
+ var unreachableSplit = unreachable.split();
+ var unreachableSplitUnsplit = unreachableSplit.unsplit();
+ expect(unreachableSplitUnsplit, same(unreachable));
+ var unreachableSplitUnreachable = unreachableSplit.setUnreachable();
+ var unreachableSplitUnreachableUnsplit =
+ unreachableSplitUnreachable.unsplit();
+ expect(unreachableSplitUnreachableUnsplit, same(unreachable));
+ });
+
+ test('setUnreachable', () {
+ var reachable = Reachability.initial.split();
+ var unreachable = reachable.setUnreachable();
+ expect(unreachable.parent, same(reachable.parent));
+ expect(unreachable.locallyReachable, false);
+ expect(unreachable.overallReachable, false);
+ expect(unreachable.setUnreachable(), same(unreachable));
+ var provisionallyReachable = unreachable.split();
+ var provisionallyUnreachable = provisionallyReachable.setUnreachable();
+ expect(
+ provisionallyUnreachable.parent, same(provisionallyReachable.parent));
+ expect(provisionallyUnreachable.locallyReachable, false);
+ expect(provisionallyUnreachable.overallReachable, false);
+ expect(provisionallyUnreachable.setUnreachable(),
+ same(provisionallyUnreachable));
+ });
+
+ test('restrict', () {
+ var previous = Reachability.initial.split();
+ var reachable = previous.split();
+ var unreachable = reachable.setUnreachable();
+ expect(Reachability.restrict(reachable, reachable), same(reachable));
+ expect(Reachability.restrict(reachable, unreachable), same(unreachable));
+ expect(Reachability.restrict(unreachable, reachable), same(unreachable));
+ expect(
+ Reachability.restrict(unreachable, unreachable), same(unreachable));
+ });
+
+ test('join', () {
+ var previous = Reachability.initial.split();
+ var reachable = previous.split();
+ var unreachable = reachable.setUnreachable();
+ expect(Reachability.join(reachable, reachable), same(reachable));
+ expect(Reachability.join(reachable, unreachable), same(reachable));
+ expect(Reachability.join(unreachable, reachable), same(reachable));
+ expect(Reachability.join(unreachable, unreachable), same(unreachable));
+ });
+ });
+
group('State', () {
var intVar = _Var('x', _Type('int'));
var intQVar = _Var('x', _Type('int?'));
var objectQVar = _Var('x', _Type('Object?'));
var nullVar = _Var('x', _Type('Null'));
group('setUnreachable', () {
- var unreachable = FlowModel<_Var, _Type>(false);
- var reachable = FlowModel<_Var, _Type>(true);
+ var unreachable =
+ FlowModel<_Var, _Type>(Reachability.initial.setUnreachable());
+ var reachable = FlowModel<_Var, _Type>(Reachability.initial);
test('unchanged', () {
expect(unreachable.setUnreachable(), same(unreachable));
});
@@ -2226,7 +2308,7 @@
void _check(FlowModel<_Var, _Type> initial) {
var s = initial.setUnreachable();
expect(s, isNot(same(initial)));
- expect(s.reachable, false);
+ expect(s.reachable.overallReachable, false);
expect(s.variableInfo, same(initial.variableInfo));
}
@@ -2234,33 +2316,45 @@
});
});
+ test('split', () {
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial);
+ var s2 = s1.split();
+ expect(s2.reachable.parent, same(s1.reachable));
+ });
+
+ test('unsplit', () {
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial.split());
+ var s2 = s1.unsplit();
+ expect(s2.reachable, same(Reachability.initial));
+ });
+
group('tryPromoteForTypeCheck', () {
test('unpromoted -> unchanged (same)', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true);
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial);
var s2 = s1.tryPromoteForTypeCheck(h, intVar, _Type('int')).ifTrue;
expect(s2, same(s1));
});
test('unpromoted -> unchanged (supertype)', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true);
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial);
var s2 = s1.tryPromoteForTypeCheck(h, intVar, _Type('Object')).ifTrue;
expect(s2, same(s1));
});
test('unpromoted -> unchanged (unrelated)', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true);
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial);
var s2 = s1.tryPromoteForTypeCheck(h, intVar, _Type('String')).ifTrue;
expect(s2, same(s1));
});
test('unpromoted -> subtype', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true);
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial);
var s2 = s1.tryPromoteForTypeCheck(h, intQVar, _Type('int')).ifTrue;
- expect(s2.reachable, true);
+ expect(s2.reachable.overallReachable, true);
expect(s2.variableInfo, {
intQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int'])
});
@@ -2268,7 +2362,7 @@
test('promoted -> unchanged (same)', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
.ifTrue;
var s2 = s1.tryPromoteForTypeCheck(h, objectQVar, _Type('int')).ifTrue;
@@ -2277,7 +2371,7 @@
test('promoted -> unchanged (supertype)', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
.ifTrue;
var s2 =
@@ -2287,7 +2381,7 @@
test('promoted -> unchanged (unrelated)', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
.ifTrue;
var s2 =
@@ -2297,11 +2391,11 @@
test('promoted -> subtype', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
.ifTrue;
var s2 = s1.tryPromoteForTypeCheck(h, objectQVar, _Type('int')).ifTrue;
- expect(s2.reachable, true);
+ expect(s2.reachable.overallReachable, true);
expect(s2.variableInfo, {
objectQVar: _matchVariableModel(
chain: ['int?', 'int'], ofInterest: ['int?', 'int'])
@@ -2315,23 +2409,25 @@
test('without declaration', () {
// This should not happen in valid code, but test that we don't crash.
var h = _Harness();
- var s =
- FlowModel<_Var, _Type>(true).write(objectQVar, _Type('Object?'), h);
+ var s = FlowModel<_Var, _Type>(Reachability.initial)
+ .write(objectQVar, _Type('Object?'), h);
expect(s.variableInfo[objectQVar], isNull);
});
test('unchanged', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true).declare(objectQVar, true);
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
+ .declare(objectQVar, true);
var s2 = s1.write(objectQVar, _Type('Object?'), h);
expect(s2, same(s1));
});
test('marks as assigned', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true).declare(objectQVar, false);
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
+ .declare(objectQVar, false);
var s2 = s1.write(objectQVar, _Type('int?'), h);
- expect(s2.reachable, true);
+ expect(s2.reachable.overallReachable, true);
expect(
s2.infoFor(objectQVar),
_matchVariableModel(
@@ -2343,13 +2439,13 @@
test('un-promotes fully', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(objectQVar, true)
.tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
.ifTrue;
expect(s1.variableInfo, contains(objectQVar));
var s2 = s1.write(objectQVar, _Type('int?'), h);
- expect(s2.reachable, true);
+ expect(s2.reachable.overallReachable, true);
expect(s2.variableInfo, {
objectQVar: _matchVariableModel(
chain: null,
@@ -2361,7 +2457,7 @@
test('un-promotes partially, when no exact match', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(objectQVar, true)
.tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
.ifTrue
@@ -2375,7 +2471,7 @@
unassigned: false)
});
var s2 = s1.write(objectQVar, _Type('num'), h);
- expect(s2.reachable, true);
+ expect(s2.reachable.overallReachable, true);
expect(s2.variableInfo, {
objectQVar: _matchVariableModel(
chain: ['num?', 'num'],
@@ -2387,7 +2483,7 @@
test('un-promotes partially, when exact match', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(objectQVar, true)
.tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
.ifTrue
@@ -2403,7 +2499,7 @@
unassigned: false)
});
var s2 = s1.write(objectQVar, _Type('num'), h);
- expect(s2.reachable, true);
+ expect(s2.reachable.overallReachable, true);
expect(s2.variableInfo, {
objectQVar: _matchVariableModel(
chain: ['num?', 'num'],
@@ -2415,7 +2511,7 @@
test('leaves promoted, when exact match', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(objectQVar, true)
.tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
.ifTrue
@@ -2429,13 +2525,13 @@
unassigned: false)
});
var s2 = s1.write(objectQVar, _Type('num'), h);
- expect(s2.reachable, true);
+ expect(s2.reachable.overallReachable, true);
expect(s2.variableInfo, same(s1.variableInfo));
});
test('leaves promoted, when writing a subtype', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(objectQVar, true)
.tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
.ifTrue
@@ -2449,7 +2545,7 @@
unassigned: false)
});
var s2 = s1.write(objectQVar, _Type('int'), h);
- expect(s2.reachable, true);
+ expect(s2.reachable.overallReachable, true);
expect(s2.variableInfo, same(s1.variableInfo));
});
@@ -2458,7 +2554,8 @@
var h = _Harness();
var x = _Var('x', _Type('int?'));
- var s1 = FlowModel<_Var, _Type>(true).declare(x, true);
+ var s1 =
+ FlowModel<_Var, _Type>(Reachability.initial).declare(x, true);
expect(s1.variableInfo, {
x: _matchVariableModel(chain: null),
});
@@ -2473,7 +2570,8 @@
var h = _Harness();
var x = h.addVar('x', 'int?');
- var s1 = FlowModel<_Var, _Type>(true).declare(x, true);
+ var s1 =
+ FlowModel<_Var, _Type>(Reachability.initial).declare(x, true);
expect(s1.variableInfo, {
x: _matchVariableModel(chain: null),
});
@@ -2492,7 +2590,7 @@
test('when promoted', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(objectQVar, true)
.tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
.ifTrue;
@@ -2513,7 +2611,7 @@
test('when not promoted', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(objectQVar, true)
.tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
.ifFalse;
@@ -2535,7 +2633,7 @@
test('Promotes to type of interest when not previously promoted', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(objectQVar, true)
.tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
.ifFalse;
@@ -2556,7 +2654,7 @@
test('Promotes to type of interest when previously promoted', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(objectQVar, true)
.tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
.ifTrue
@@ -2624,7 +2722,7 @@
test('; first', () {
var x = _Var('x', _Type('Object?'));
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(x, true)
.tryPromoteForTypeCheck(h, x, _Type('B?'))
.ifFalse
@@ -2649,7 +2747,7 @@
test('; second', () {
var x = _Var('x', _Type('Object?'));
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(x, true)
.tryPromoteForTypeCheck(h, x, _Type('A?'))
.ifFalse
@@ -2674,7 +2772,7 @@
test('; nullable and non-nullable', () {
var x = _Var('x', _Type('Object?'));
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(x, true)
.tryPromoteForTypeCheck(h, x, _Type('A'))
.ifFalse
@@ -2700,7 +2798,7 @@
group('; ambiguous', () {
test('; no promotion', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(objectQVar, true)
.tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
.ifFalse
@@ -2721,7 +2819,7 @@
test('exact match', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(objectQVar, true)
.tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
.ifFalse
@@ -2752,7 +2850,7 @@
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(x, true)
.tryPromoteForTypeCheck(h, x, _Type('num?'))
.ifTrue
@@ -2779,14 +2877,16 @@
var objectQVar = _Var('x', _Type('Object?'));
test('initialized', () {
- var s = FlowModel<_Var, _Type>(true).declare(objectQVar, true);
+ var s = FlowModel<_Var, _Type>(Reachability.initial)
+ .declare(objectQVar, true);
expect(s.variableInfo, {
objectQVar: _matchVariableModel(assigned: true, unassigned: false),
});
});
test('not initialized', () {
- var s = FlowModel<_Var, _Type>(true).declare(objectQVar, false);
+ var s = FlowModel<_Var, _Type>(Reachability.initial)
+ .declare(objectQVar, false);
expect(s.variableInfo, {
objectQVar: _matchVariableModel(assigned: false, unassigned: true),
});
@@ -2796,23 +2896,23 @@
group('markNonNullable', () {
test('unpromoted -> unchanged', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true);
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial);
var s2 = s1.tryMarkNonNullable(h, intVar).ifTrue;
expect(s2, same(s1));
});
test('unpromoted -> promoted', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true);
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial);
var s2 = s1.tryMarkNonNullable(h, intQVar).ifTrue;
- expect(s2.reachable, true);
+ expect(s2.reachable.overallReachable, true);
expect(s2.infoFor(intQVar),
_matchVariableModel(chain: ['int'], ofInterest: []));
});
test('promoted -> unchanged', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
.ifTrue;
var s2 = s1.tryMarkNonNullable(h, objectQVar).ifTrue;
@@ -2821,11 +2921,11 @@
test('promoted -> re-promoted', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
.ifTrue;
var s2 = s1.tryMarkNonNullable(h, objectQVar).ifTrue;
- expect(s2.reachable, true);
+ expect(s2.reachable.overallReachable, true);
expect(s2.variableInfo, {
objectQVar:
_matchVariableModel(chain: ['int?', 'int'], ofInterest: ['int?'])
@@ -2834,9 +2934,9 @@
test('promote to Never', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true);
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial);
var s2 = s1.tryMarkNonNullable(h, nullVar).ifTrue;
- expect(s2.reachable, false);
+ expect(s2.reachable.overallReachable, false);
expect(s2.infoFor(nullVar),
_matchVariableModel(chain: ['Never'], ofInterest: []));
});
@@ -2850,7 +2950,7 @@
var a = _Var('a', _Type('int'));
var b = _Var('b', _Type('int'));
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(a, false)
.declare(b, false)
.write(a, _Type('int'), h);
@@ -2876,7 +2976,7 @@
var b = _Var('b', _Type('int'));
var c = _Var('c', _Type('int'));
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(a, false)
.declare(b, false)
.declare(c, false)
@@ -2907,7 +3007,7 @@
group('conservativeJoin', () {
test('unchanged', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(intQVar, true)
.tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
.ifTrue;
@@ -2917,13 +3017,13 @@
test('written', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
.ifTrue
.tryPromoteForTypeCheck(h, intQVar, _Type('int'))
.ifTrue;
var s2 = s1.conservativeJoin([intQVar], []);
- expect(s2.reachable, true);
+ expect(s2.reachable.overallReachable, true);
expect(s2.variableInfo, {
objectQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int']),
intQVar: _matchVariableModel(chain: null, ofInterest: ['int'])
@@ -2932,13 +3032,13 @@
test('write captured', () {
var h = _Harness();
- var s1 = FlowModel<_Var, _Type>(true)
+ var s1 = FlowModel<_Var, _Type>(Reachability.initial)
.tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
.ifTrue
.tryPromoteForTypeCheck(h, intQVar, _Type('int'))
.ifTrue;
var s2 = s1.conservativeJoin([], [intQVar]);
- expect(s2.reachable, true);
+ expect(s2.reachable.overallReachable, true);
expect(s2.variableInfo, {
objectQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int']),
intQVar: _matchVariableModel(
@@ -2950,7 +3050,7 @@
group('restrict', () {
test('reachability', () {
var h = _Harness();
- var reachable = FlowModel<_Var, _Type>(true);
+ var reachable = FlowModel<_Var, _Type>(Reachability.initial);
var unreachable = reachable.setUnreachable();
expect(reachable.restrict(h, reachable, Set()), same(reachable));
expect(reachable.restrict(h, unreachable, Set()), same(unreachable));
@@ -2964,7 +3064,7 @@
var b = _Var('b', _Type('int'));
var c = _Var('c', _Type('int'));
var d = _Var('d', _Type('int'));
- var s0 = FlowModel<_Var, _Type>(true)
+ var s0 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(a, false)
.declare(b, false)
.declare(c, false)
@@ -2984,7 +3084,7 @@
var b = _Var('b', _Type('int'));
var c = _Var('c', _Type('int'));
var d = _Var('d', _Type('int'));
- var s0 = FlowModel<_Var, _Type>(true)
+ var s0 = FlowModel<_Var, _Type>(Reachability.initial)
.declare(a, false)
.declare(b, false)
.declare(c, false)
@@ -3016,7 +3116,8 @@
List<String> expectedChain) {
var h = _Harness();
var x = _Var('x', _Type('Object?'));
- var s0 = FlowModel<_Var, _Type>(true).declare(x, true);
+ var s0 =
+ FlowModel<_Var, _Type>(Reachability.initial).declare(x, true);
var s1 = thisType == null
? s0
: s0.tryPromoteForTypeCheck(h, x, _Type(thisType)).ifTrue;
@@ -3068,7 +3169,8 @@
List<String> inFinally, List<String> expectedResult) {
var h = _Harness();
var x = _Var('x', _Type('Object?'));
- var initialModel = FlowModel<_Var, _Type>(true).declare(x, true);
+ var initialModel =
+ FlowModel<_Var, _Type>(Reachability.initial).declare(x, true);
for (var t in before) {
initialModel =
initialModel.tryPromoteForTypeCheck(h, x, _Type(t)).ifTrue;
@@ -3121,7 +3223,7 @@
test('variable present in one state but not the other', () {
var h = _Harness();
var x = _Var('x', _Type('Object?'));
- var s0 = FlowModel<_Var, _Type>(true);
+ var s0 = FlowModel<_Var, _Type>(Reachability.initial);
var s1 = s0.declare(x, true);
expect(s0.restrict(h, s1, {}), same(s0));
expect(s0.restrict(h, s1, {x}), same(s0));
@@ -3490,10 +3592,10 @@
test('inherits types of interest from other', () {
var h = _Harness();
- var m1 = FlowModel.withInfo(true, {
+ var m1 = FlowModel.withInfo(Reachability.initial, {
x: model([intType])
});
- var m2 = FlowModel.withInfo(true, {
+ var m2 = FlowModel.withInfo(Reachability.initial, {
x: model([stringType])
});
expect(m1.inheritTested(h, m2).variableInfo[x].tested,
@@ -3502,19 +3604,19 @@
test('handles variable missing from other', () {
var h = _Harness();
- var m1 = FlowModel.withInfo(true, {
+ var m1 = FlowModel.withInfo(Reachability.initial, {
x: model([intType])
});
- var m2 = FlowModel.withInfo(true, emptyMap);
+ var m2 = FlowModel.withInfo(Reachability.initial, emptyMap);
expect(m1.inheritTested(h, m2), same(m1));
});
test('returns identical model when no changes', () {
var h = _Harness();
- var m1 = FlowModel.withInfo(true, {
+ var m1 = FlowModel.withInfo(Reachability.initial, {
x: model([intType])
});
- var m2 = FlowModel.withInfo(true, {
+ var m2 = FlowModel.withInfo(Reachability.initial, {
x: model([intType])
});
expect(m1.inheritTested(h, m2), same(m1));
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart
index 3d890e8..35f2d63 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart
@@ -55,6 +55,18 @@
x;
}
+localVariable_initialized_nonNull() {
+ num? x = 0;
+ /*num*/ x;
+ x = null;
+ x;
+}
+
+localVariable_initialized_nonNull_final() {
+ final num? x = 0;
+ x;
+}
+
localVariable_initialized_promoted_type_var<T>(T t) {
if (t is num) {
var x = /*T & num*/ t;
@@ -94,13 +106,13 @@
localVariable_initialized_promoted_type_var_typed<T>(T t) {
if (t is num) {
- // TODO(paulberry): This should promote to `T & Object`, because that's the
- // non-nullable version of T, but it shouldn't promote to `T & num`.
+ // This should promote to `T & Object`, because that's the non-nullable
+ // version of T, but it shouldn't promote to `T & num`.
T x = /*T & num*/ t;
- x;
+ /*T & Object*/ x;
// Check that `T & Object` is a type of interest by promoting and then
// writing to it
- if (x is int) {
+ if (/*T & Object*/ x is int) {
/*T & int*/ x;
x = /*T & num*/ t;
/*T & Object*/ x;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 931cf38..bc2bbad 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2004,12 +2004,17 @@
}
var initializer = node.initializer;
- var parent = node.parent;
- TypeAnnotation declaredType = (parent as VariableDeclarationList).type;
- if (declaredType == null && initializer != null) {
+ var parent = node.parent as VariableDeclarationList;
+ TypeAnnotation declaredType = parent.type;
+ if (initializer != null) {
var initializerStaticType = initializer.staticType;
- if (initializerStaticType is TypeParameterType) {
- _flowAnalysis?.flow?.promote(declaredElement, initializerStaticType);
+ if (declaredType == null) {
+ if (initializerStaticType is TypeParameterType) {
+ _flowAnalysis?.flow?.promote(declaredElement, initializerStaticType);
+ }
+ } else if (!parent.isFinal) {
+ _flowAnalysis?.flow?.write(declaredElement, initializerStaticType,
+ viaInitializer: true);
}
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 9e96eec..3f0e79b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -5722,8 +5722,17 @@
}
if (initializerResult != null) {
DartType initializerType = initializerResult.inferredType;
- if (node.isImplicitlyTyped && initializerType is TypeParameterType) {
- inferrer.flowAnalysis.promote(node, initializerType);
+ if (node.isImplicitlyTyped) {
+ if (initializerType is TypeParameterType) {
+ inferrer.flowAnalysis.promote(node, initializerType);
+ }
+ } else if (!node.isFinal) {
+ // TODO(paulberry): `initializerType` is sometimes `null` during top
+ // level inference. Figure out how to prevent this.
+ if (initializerType != null) {
+ inferrer.flowAnalysis
+ .write(node, initializerType, viaInitializer: true);
+ }
}
Expression initializer = inferrer.ensureAssignableResult(
node.type, initializerResult,
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index cd83c1b..1f0ca3c 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -555,6 +555,7 @@
iterating
iterations
iterators
+ith
j
jacobr
jakemac
@@ -867,6 +868,7 @@
rc
re
reach
+reachabilities
reachability
react
realign
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 267dd7a..b370368 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -431,6 +431,7 @@
checked
checker
checking
+checkpoints
checks
child
children
@@ -579,6 +580,7 @@
conformed
confuse
confused
+conjunction
connect
connected
connection
@@ -912,6 +914,7 @@
drop
dropped
dropping
+drops
due
dump
dumped
@@ -1773,6 +1776,7 @@
main
mainly
maintain
+maintains
major
make
makes
@@ -1844,6 +1848,7 @@
might
millisecond
milliseconds
+mimics
minimal
minimum
minor
@@ -1865,6 +1870,7 @@
mock
mode
model
+modeling
models
modes
modifiable
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml
index 9af8d7f..7b083ef 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml
@@ -14,8 +14,8 @@
main() {
dynamic x;
print(x >>> 2);
- Class? c = new Class();
+ Class? c = new Class() as Class?;
print(c!);
}
class Class {}
- expectedLibraryCount: 1
\ No newline at end of file
+ expectedLibraryCount: 1
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart b/pkg/front_end/testcases/nnbd/issue41114.dart
index 7db889f..3929126 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
main() async {
- List<String>? a = <String>[];
+ List<String>? a = <String>[] as List<String>?;
Iterable<String>? b = a?.map((e) => e);
Iterable<String>? i = b ?? a;
print(i);
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect
index 4b2167b..6fb76f5 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
static method main() → dynamic async {
- core::List<core::String>? a = <core::String>[];
+ core::List<core::String>? a = <core::String>[] as{ForNonNullableByDefault} core::List<core::String>?;
core::Iterable<core::String>? b = let final core::List<core::String>? #t1 = a in #t1.{core::List::==}(null) ?{core::Iterable<core::String>?} null : #t1{core::List<core::String>}.{core::Iterable::map}<core::String>((core::String e) → core::String => e);
core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2.{core::Object::==}(null) ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
core::print(i);
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect
index 4b2167b..6fb76f5 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
static method main() → dynamic async {
- core::List<core::String>? a = <core::String>[];
+ core::List<core::String>? a = <core::String>[] as{ForNonNullableByDefault} core::List<core::String>?;
core::Iterable<core::String>? b = let final core::List<core::String>? #t1 = a in #t1.{core::List::==}(null) ?{core::Iterable<core::String>?} null : #t1{core::List<core::String>}.{core::Iterable::map}<core::String>((core::String e) → core::String => e);
core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2.{core::Object::==}(null) ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
core::print(i);
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart b/pkg/front_end/testcases/nnbd/issue41495.dart
index ceaf89a..cca6995 100644
--- a/pkg/front_end/testcases/nnbd/issue41495.dart
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart
@@ -10,7 +10,7 @@
main() {}
errors() {
- A? a1 = new A();
+ A? a1 = new A() as A?;
a1.c1;
a1.test;
}
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect
index ecc36781..4df1b52 100644
--- a/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect
@@ -27,7 +27,7 @@
}
static method main() → dynamic {}
static method errors() → dynamic {
- self::A? a1 = new self::A::•();
+ self::A? a1 = new self::A::•() as{ForNonNullableByDefault} self::A?;
let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
- 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
Try accessing using ?. instead.
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect
index ecc36781..4df1b52 100644
--- a/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect
@@ -27,7 +27,7 @@
}
static method main() → dynamic {}
static method errors() → dynamic {
- self::A? a1 = new self::A::•();
+ self::A? a1 = new self::A::•() as{ForNonNullableByDefault} self::A?;
let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
- 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
Try accessing using ?. instead.
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart b/pkg/front_end/testcases/nnbd/null_aware_chain.dart
index a53cacf..ff589af 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart
@@ -11,6 +11,6 @@
}
main() {
- Class? c = new Class();
+ Class? c = new Class() as Class?;
c?.getter1.getter2?.getter1.getter2?.field = c;
}
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect
index 267161a..4c16033 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect
@@ -13,7 +13,7 @@
return this.{self::Class::field};
}
static method main() → dynamic {
- self::Class? c = new self::Class::•();
+ self::Class? c = new self::Class::•() as{ForNonNullableByDefault} self::Class?;
let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t2 = #t1{self::Class}.{self::Class::getter1}.{self::Class::getter2} in #t2.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t3 = #t2{self::Class}.{self::Class::getter1}.{self::Class::getter2} in #t3.{core::Object::==}(null) ?{self::Class?} null : #t3{self::Class}.{self::Class::field} = c{self::Class};
}
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect
index 267161a..4c16033 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect
@@ -13,7 +13,7 @@
return this.{self::Class::field};
}
static method main() → dynamic {
- self::Class? c = new self::Class::•();
+ self::Class? c = new self::Class::•() as{ForNonNullableByDefault} self::Class?;
let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t2 = #t1{self::Class}.{self::Class::getter1}.{self::Class::getter2} in #t2.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t3 = #t2{self::Class}.{self::Class::getter1}.{self::Class::getter2} in #t3.{core::Object::==}(null) ?{self::Class?} null : #t3{self::Class}.{self::Class::field} = c{self::Class};
}
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart b/pkg/front_end/testcases/nnbd/null_check.dart
index 110d74f..4cef88b 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart
+++ b/pkg/front_end/testcases/nnbd/null_check.dart
@@ -9,7 +9,7 @@
}
main() {
- Class? c = new Class();
+ Class? c = new Class() as Class?;
c!;
c!.field;
c!.field = 42;
@@ -22,7 +22,7 @@
c + c!;
(c + c)!;
- bool? o = true;
+ bool? o = true as bool?;
!o! ? !o! : !!o!!;
!(o!) ? (!o)! : (!(!o)!)!;
-}
\ No newline at end of file
+}
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
index 26ca627..a1827fa 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
@@ -99,7 +99,7 @@
return new self::Class::•();
}
static method main() → dynamic {
- self::Class? c = new self::Class::•();
+ self::Class? c = new self::Class::•() as{ForNonNullableByDefault} self::Class?;
c!;
c{self::Class}!.{self::Class::field};
c{self::Class}!.{self::Class::field} = 42;
@@ -111,7 +111,7 @@
c{self::Class}!.{self::Class::+}(c{self::Class}!);
c{self::Class}.{self::Class::+}(c{self::Class}!);
c{self::Class}.{self::Class::+}(c{self::Class})!;
- core::bool? o = true;
+ core::bool? o = true as{ForNonNullableByDefault} core::bool?;
!o! ?{core::bool} !o{core::bool}! : !!o{core::bool}!!;
!o{core::bool}! ?{core::bool} (!o{core::bool})! : (!(!o{core::bool})!)!;
}
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect
index 26ca627..a1827fa 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect
@@ -99,7 +99,7 @@
return new self::Class::•();
}
static method main() → dynamic {
- self::Class? c = new self::Class::•();
+ self::Class? c = new self::Class::•() as{ForNonNullableByDefault} self::Class?;
c!;
c{self::Class}!.{self::Class::field};
c{self::Class}!.{self::Class::field} = 42;
@@ -111,7 +111,7 @@
c{self::Class}!.{self::Class::+}(c{self::Class}!);
c{self::Class}.{self::Class::+}(c{self::Class}!);
c{self::Class}.{self::Class::+}(c{self::Class})!;
- core::bool? o = true;
+ core::bool? o = true as{ForNonNullableByDefault} core::bool?;
!o! ?{core::bool} !o{core::bool}! : !!o{core::bool}!!;
!o{core::bool}! ?{core::bool} (!o{core::bool})! : (!(!o{core::bool})!)!;
}
diff --git a/pkg/front_end/testcases/nnbd/nullable_setter.dart b/pkg/front_end/testcases/nnbd/nullable_setter.dart
index 8e9d230..f644300 100644
--- a/pkg/front_end/testcases/nnbd/nullable_setter.dart
+++ b/pkg/front_end/testcases/nnbd/nullable_setter.dart
@@ -19,7 +19,7 @@
}
main() {
- C? c = new C();
+ C? c = new C() as C?;
expect("", c?.m);
c.setter = "42";
expect("42", c?.m);
diff --git a/pkg/front_end/testcases/nnbd/nullable_setter.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_setter.dart.strong.expect
index d367854..ac016f2 100644
--- a/pkg/front_end/testcases/nnbd/nullable_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_setter.dart.strong.expect
@@ -21,7 +21,7 @@
let final self::C? #t2 = #this in #t2.{core::Object::==}(null) ?{core::String?} null : #t2{self::C}.{self::C::m} = "${index}${value}";
}
static method main() → dynamic {
- self::C? c = new self::C::•();
+ self::C? c = new self::C::•() as{ForNonNullableByDefault} self::C?;
self::expect("", let final self::C? #t3 = c in #t3.{core::Object::==}(null) ?{core::String?} null : #t3{self::C}.{self::C::m});
self::_extension#0|set#setter(c, "42");
self::expect("42", let final self::C? #t4 = c in #t4.{core::Object::==}(null) ?{core::String?} null : #t4{self::C}.{self::C::m});
diff --git a/pkg/front_end/testcases/nnbd/nullable_setter.dart.weak.expect b/pkg/front_end/testcases/nnbd/nullable_setter.dart.weak.expect
index d367854..ac016f2 100644
--- a/pkg/front_end/testcases/nnbd/nullable_setter.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_setter.dart.weak.expect
@@ -21,7 +21,7 @@
let final self::C? #t2 = #this in #t2.{core::Object::==}(null) ?{core::String?} null : #t2{self::C}.{self::C::m} = "${index}${value}";
}
static method main() → dynamic {
- self::C? c = new self::C::•();
+ self::C? c = new self::C::•() as{ForNonNullableByDefault} self::C?;
self::expect("", let final self::C? #t3 = c in #t3.{core::Object::==}(null) ?{core::String?} null : #t3{self::C}.{self::C::m});
self::_extension#0|set#setter(c, "42");
self::expect("42", let final self::C? #t4 = c in #t4.{core::Object::==}(null) ?{core::String?} null : #t4{self::C}.{self::C::m});
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
index 919f10f..06a5216 100644
--- a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
@@ -488,11 +488,11 @@
new uns::OptInClass4::•().{uns::OptInClass4::methodForEffect}(i);
}
static method nullAwareIfNullSetOptIn(core::int i) → dynamic {
- uns::OptInClass5? o = new uns::OptInClass5::•(i);
+ uns::OptInClass5? o = new uns::OptInClass5::•(i) as{ForNonNullableByDefault} uns::OptInClass5?;
return let final uns::OptInClass5? #t66 = o in #t66.{core::Object::==}(null) ?{core::int?} null : let final core::int #t67 = #t66.{uns::OptInClass5::field} in #t67.{core::num::==}(null) ?{core::int} #t66.{uns::OptInClass5::field} = 42 : #t67;
}
static method nullAwareIfNullSetOptInForEffect(core::int i) → dynamic {
- uns::OptInClass5? o = new uns::OptInClass5::•(i);
+ uns::OptInClass5? o = new uns::OptInClass5::•(i) as{ForNonNullableByDefault} uns::OptInClass5?;
let final uns::OptInClass5? #t68 = o in #t68.{core::Object::==}(null) ?{core::int?} null : #t68.{uns::OptInClass5::field}.{core::num::==}(null) ?{core::int} #t68.{uns::OptInClass5::field} = 42 : null;
}
static method isTestOptIn(core::int i) → dynamic
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart b/pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart
index 6dd9b47..738e03a 100644
--- a/pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart
@@ -85,12 +85,12 @@
}
nullAwareIfNullSetOptIn(int i) {
- OptInClass5? o = new OptInClass5(i);
+ OptInClass5? o = new OptInClass5(i) as OptInClass5?;
return o?.field ??= 42;
}
nullAwareIfNullSetOptInForEffect(int i) {
- OptInClass5? o = new OptInClass5(i);
+ OptInClass5? o = new OptInClass5(i) as OptInClass5?;
o?.field ??= 42;
}
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 5a8f2bb..2140235 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -4626,7 +4626,7 @@
// here non-null is OK.
int i1 = 0, i2 = i1.gcd(2);
// here non-null is not OK.
- int? i3 = 0, i4 = i3!.gcd(2), i5 = null;
+ int? i3 = 0, i4 = i3.gcd(2), i5 = null;
}
''';
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 7044628..e9f8516a 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -192,7 +192,7 @@
V(::, reachabilityFence, ReachabilityFence, 0xad39d0a6) \
V(_Utf8Decoder, _scan, Utf8DecoderScan, 0x78f44c3c) \
V(_Future, timeout, FutureTimeout, 0x010f8ad4) \
- V(Future, wait, FutureWait, 0x9a812df7) \
+ V(Future, wait, FutureWait, 0x6c0c3295) \
// List of intrinsics:
// (class-name, function-name, intrinsification method, fingerprint).
diff --git a/tests/language/await/null_aware_test.dart b/tests/language/await/null_aware_test.dart
index 819de12..88f16f0 100644
--- a/tests/language/await/null_aware_test.dart
+++ b/tests/language/await/null_aware_test.dart
@@ -13,11 +13,11 @@
}
main() async {
- int? x = 1;
+ var x = 1 as int?;
x ??= await f();
Expect.equals(1, x);
- int? y = 1;
+ var y = 1 as int?;
y = y ?? await f();
Expect.equals(1, y);
}
diff --git a/tests/language/if_null/assignment_static_test.dart b/tests/language/if_null/assignment_static_test.dart
index 14edd3c..7eee56b 100644
--- a/tests/language/if_null/assignment_static_test.dart
+++ b/tests/language/if_null/assignment_static_test.dart
@@ -141,7 +141,7 @@
// The static type of e1?.v op= e2 is the static type of e1.v op e2,
// therefore the static type of e1?.v ??= e2 is the static type of
// e1.v ?? e2, which is the LUB of NonNull(typeof(e1?.v)) and typeof(e2).
- ClassWithInstanceGetters? c = new ClassWithInstanceGetters();
+ var c = new ClassWithInstanceGetters() as ClassWithInstanceGetters?;
(c?.a ??= theA)!.a; //# 36: ok
(c?.a ??= theA)!.b; //# 37: compile-time error
(c?.a ??= theB)!.a; //# 38: ok
diff --git a/tests/language/if_null/behavior_test.dart b/tests/language/if_null/behavior_test.dart
index a679108..a55d7f5 100644
--- a/tests/language/if_null/behavior_test.dart
+++ b/tests/language/if_null/behavior_test.dart
@@ -32,8 +32,8 @@
C? nullC() => null;
main() {
- int? one = 1;
- B? b = B('B');
+ var one = 1 as int?;
+ var b = B('B') as B?;
Expect.equals(1, one ?? 2);
Expect.equals(1, one ?? null);
Expect.equals(2, null ?? 2);
diff --git a/tests/language/if_null/evaluation_order_test.dart b/tests/language/if_null/evaluation_order_test.dart
index ca78ab4..c4da142 100644
--- a/tests/language/if_null/evaluation_order_test.dart
+++ b/tests/language/if_null/evaluation_order_test.dart
@@ -27,7 +27,7 @@
}
main() {
- int? one = 1;
+ var one = 1 as int?;
Expect.equals(1, one ?? bad());
Expect.equals(2, first() ?? second());
}
diff --git a/tests/language/implicit_downcast_during/if_null_assignment_test.dart b/tests/language/implicit_downcast_during/if_null_assignment_test.dart
index 7c91b32..c29d634 100644
--- a/tests/language/implicit_downcast_during/if_null_assignment_test.dart
+++ b/tests/language/implicit_downcast_during/if_null_assignment_test.dart
@@ -8,7 +8,7 @@
void main() {
B? b;
- A? a = new B();
+ var a = new B() as A?;
b ??= a;
// ^
// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
diff --git a/tests/language/implicit_downcast_during/null_aware_method_invocation_test.dart b/tests/language/implicit_downcast_during/null_aware_method_invocation_test.dart
index 535c7db..59c115e 100644
--- a/tests/language/implicit_downcast_during/null_aware_method_invocation_test.dart
+++ b/tests/language/implicit_downcast_during/null_aware_method_invocation_test.dart
@@ -11,7 +11,7 @@
}
main() {
- C? c = new C();
+ var c = new C() as C?;
A a = new B();
c?.f(a);
// ^
diff --git a/tests/language/nnbd/static_errors/super_equals_disallows_non_matching_type_error_test.dart b/tests/language/nnbd/static_errors/super_equals_disallows_non_matching_type_error_test.dart
index 4366065..a2a8182 100644
--- a/tests/language/nnbd/static_errors/super_equals_disallows_non_matching_type_error_test.dart
+++ b/tests/language/nnbd/static_errors/super_equals_disallows_non_matching_type_error_test.dart
@@ -24,7 +24,7 @@
class Derived extends Base {
void test() {
String string = 'foo';
- String? stringQuestion = 'foo';
+ var stringQuestion = 'foo' as String?;
super == string;
// ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
diff --git a/tests/language/nnbd/syntax/class_member_declarations_test.dart b/tests/language/nnbd/syntax/class_member_declarations_test.dart
index 3aa7d26..a6c8efd 100644
--- a/tests/language/nnbd/syntax/class_member_declarations_test.dart
+++ b/tests/language/nnbd/syntax/class_member_declarations_test.dart
@@ -46,7 +46,7 @@
main() {
A? a;
- String? s = '';
+ var s = '' as String?;
a
?..foo().length
..x27 = s!.toString().length;
diff --git a/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart b/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart
index b4b357e..131631e 100644
--- a/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart
+++ b/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart
@@ -43,7 +43,7 @@
Expect.throws(() {
x3 = a!;
});
- Object? x4 = 0;
+ var x4 = 0 as Object?;
Expect.throws(() {
x4 = a!;
});
@@ -62,7 +62,7 @@
// ignores its argument, and verify that the appropriate exception is still
// thrown.
var x6 = 2;
- int? i = 2;
+ var i = 2 as int?;
x6 * i!;
var x7 = new C();
i = null;
@@ -73,9 +73,9 @@
// `-x!` means `-(x!)`, not `(-x)!`. We check the compile-time behavior by
// checking that the negation is accepted even though x is nullable. We check
// the runtime behavior by using an object whose operator- returns null.
- int? x8 = 2;
+ var x8 = 2 as int?;
-x8!;
- C? x9 = new C();
+ var x9 = new C() as C?;
var x10 = -x9!;
Expect.isNull(x10);
diff --git a/tests/language/null_aware/access_runtime_2_test.dart b/tests/language/null_aware/access_runtime_2_test.dart
index b67de99..a1ade72 100644
--- a/tests/language/null_aware/access_runtime_2_test.dart
+++ b/tests/language/null_aware/access_runtime_2_test.dart
@@ -28,7 +28,7 @@
// e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
- C? c = new C(1);
+ var c = new C(1) as C?;
Expect.equals(1, c?.v);
// C?.id is equivalent to C.id.
diff --git a/tests/language/null_aware/access_runtime_5_test.dart b/tests/language/null_aware/access_runtime_5_test.dart
index 5984802..6db60ce3 100644
--- a/tests/language/null_aware/access_runtime_5_test.dart
+++ b/tests/language/null_aware/access_runtime_5_test.dart
@@ -35,7 +35,7 @@
// The static type of e1?.d is the static type of e1.id.
- C? c = new C(1);
+ var c = new C(1) as C?;
{ int? i = c?.v; Expect.equals(1, i); }
diff --git a/tests/language/null_aware/access_test.dart b/tests/language/null_aware/access_test.dart
index 224a794..b2d1bc0 100644
--- a/tests/language/null_aware/access_test.dart
+++ b/tests/language/null_aware/access_test.dart
@@ -70,8 +70,8 @@
// ^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_GETTER
// [cfe] The getter 'bad' isn't defined for the class 'C'.
- { B? b = new C(1); Expect.equals(1, b?.v); }
- // ^
+ { var b = new C(1) as B?; Expect.equals(1, b?.v); }
+ // ^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_GETTER
// [cfe] The getter 'v' isn't defined for the class 'B'.
diff --git a/tests/language/null_aware/assignment_runtime_11_test.dart b/tests/language/null_aware/assignment_runtime_11_test.dart
index 05b84a6..ca60103 100644
--- a/tests/language/null_aware/assignment_runtime_11_test.dart
+++ b/tests/language/null_aware/assignment_runtime_11_test.dart
@@ -77,7 +77,7 @@
// The static type of e1?.v op= e2 is the static type of e1.v op e2.
- { D? d = new D(new E()); F? f = (d?.v += 1); Expect.identical(d!.v, f); }
+ { var d = new D(new E()) as D?; F? f = (d?.v += 1); Expect.identical(d!.v, f); }
diff --git a/tests/language/null_aware/assignment_runtime_2_test.dart b/tests/language/null_aware/assignment_runtime_2_test.dart
index 825bfc6..bc0cdb6 100644
--- a/tests/language/null_aware/assignment_runtime_2_test.dart
+++ b/tests/language/null_aware/assignment_runtime_2_test.dart
@@ -50,7 +50,7 @@
// e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
- { C? c = new C(1); Expect.equals(2, c?.v = 2); Expect.equals(2, c!.v); }
+ { var c = new C(1) as C?; Expect.equals(2, c?.v = 2); Expect.equals(2, c!.v); }
// C?.v = e2 is equivalent to C.v = e2.
diff --git a/tests/language/null_aware/assignment_runtime_5_test.dart b/tests/language/null_aware/assignment_runtime_5_test.dart
index abcf60a..9507557 100644
--- a/tests/language/null_aware/assignment_runtime_5_test.dart
+++ b/tests/language/null_aware/assignment_runtime_5_test.dart
@@ -57,7 +57,7 @@
// The static type of e1?.v = e2 is the static type of e2.
- { D? d = new D(new E()); G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
+ { var d = new D(new E()) as D?; G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
diff --git a/tests/language/null_aware/assignment_runtime_9_test.dart b/tests/language/null_aware/assignment_runtime_9_test.dart
index 3c2d6c0..0a16c52 100644
--- a/tests/language/null_aware/assignment_runtime_9_test.dart
+++ b/tests/language/null_aware/assignment_runtime_9_test.dart
@@ -71,7 +71,7 @@
// e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
- { C? c = new C(1); Expect.equals(3, c?.v += 2); Expect.equals(3, c!.v); }
+ { var c = new C(1) as C?; Expect.equals(3, c?.v += 2); Expect.equals(3, c!.v); }
// C?.v op= e2 is equivalent to C.v op= e2.
diff --git a/tests/language/null_aware/assignment_test.dart b/tests/language/null_aware/assignment_test.dart
index 112b0a6..d7bf2f4 100644
--- a/tests/language/null_aware/assignment_test.dart
+++ b/tests/language/null_aware/assignment_test.dart
@@ -59,9 +59,9 @@
{ h.C.staticInt = 1; Expect.equals(2, h.C?.staticInt = 2); Expect.equals(2, h.C.staticInt); }
// The static type of e1?.v = e2 is the static type of e2.
- { D? d = new D(new E()); G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
- { D? d = new D(new E()); E e = new G(); F? f = (d?.v = e); }
- // ^^^^^^^^
+ { var d = new D(new E()) as D?; G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
+ { var d = new D(new E()) as D?; E e = new G(); F? f = (d?.v = e); }
+ // ^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
// [cfe] A value of type 'E?' can't be assigned to a variable of type 'F?'.
{ D.staticE = new E(); G g = new G(); F? f = (D?.staticE = g); Expect.identical(f, g); }
diff --git a/tests/language/null_aware/increment_decrement_runtime_12_test.dart b/tests/language/null_aware/increment_decrement_runtime_12_test.dart
index 03986fb..4e9c166 100644
--- a/tests/language/null_aware/increment_decrement_runtime_12_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_12_test.dart
@@ -68,7 +68,7 @@
// The static type of e1?.v-- is the same as the static type of e1.v.
- { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v--; Expect.identical(e1, e2); }
+ { E e1 = new E(); var d = new D(e1) as D?; E? e2 = d?.v--; Expect.identical(e1, e2); }
diff --git a/tests/language/null_aware/increment_decrement_runtime_16_test.dart b/tests/language/null_aware/increment_decrement_runtime_16_test.dart
index 1016d22..cfd1b8b 100644
--- a/tests/language/null_aware/increment_decrement_runtime_16_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_16_test.dart
@@ -77,7 +77,7 @@
// ++e1?.v is equivalent to e1?.v += 1.
- { C? c = new C(1); Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
+ { var c = new C(1) as C?; Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
// ++C?.v is equivalent to C?.v += 1.
diff --git a/tests/language/null_aware/increment_decrement_runtime_19_test.dart b/tests/language/null_aware/increment_decrement_runtime_19_test.dart
index bb8c565..0677ac7 100644
--- a/tests/language/null_aware/increment_decrement_runtime_19_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_19_test.dart
@@ -84,7 +84,7 @@
// The static type of ++e1?.v is the same as the static type of e1.v + 1.
- { D? d = new D(new E()); F? f = ++d?.v; Expect.identical(d!.v, f); }
+ { var d = new D(new E()) as D?; F? f = ++d?.v; Expect.identical(d!.v, f); }
diff --git a/tests/language/null_aware/increment_decrement_runtime_23_test.dart b/tests/language/null_aware/increment_decrement_runtime_23_test.dart
index b2dc6b5..2927351 100644
--- a/tests/language/null_aware/increment_decrement_runtime_23_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_23_test.dart
@@ -93,7 +93,7 @@
// --e1?.v is equivalent to e1?.v -= 1.
- { C? c = new C(1); Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
+ { var c = new C(1) as C?; Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
// --C?.v is equivalent to C?.v -= 1.
diff --git a/tests/language/null_aware/increment_decrement_runtime_26_test.dart b/tests/language/null_aware/increment_decrement_runtime_26_test.dart
index 4201d15..903c33a 100644
--- a/tests/language/null_aware/increment_decrement_runtime_26_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_26_test.dart
@@ -100,7 +100,7 @@
// The static type of --e1?.v is the same as the static type of e1.v - 1.
- { D? d = new D(new E()); F? f = --d?.v; Expect.identical(d!.v, f); }
+ { var d = new D(new E()) as D?; F? f = --d?.v; Expect.identical(d!.v, f); }
diff --git a/tests/language/null_aware/increment_decrement_runtime_2_test.dart b/tests/language/null_aware/increment_decrement_runtime_2_test.dart
index 67bca4a..3a29ccc 100644
--- a/tests/language/null_aware/increment_decrement_runtime_2_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_2_test.dart
@@ -45,7 +45,7 @@
// e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
- { C? c = new C(1); Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
+ { var c = new C(1) as C?; Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
// C?.v++ is equivalent to C.v++.
diff --git a/tests/language/null_aware/increment_decrement_runtime_5_test.dart b/tests/language/null_aware/increment_decrement_runtime_5_test.dart
index 8ca6c72..0cc85fb 100644
--- a/tests/language/null_aware/increment_decrement_runtime_5_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_5_test.dart
@@ -52,7 +52,7 @@
// The static type of e1?.v++ is the same as the static type of e1.v.
- { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v++; Expect.identical(e1, e2); }
+ { E e1 = new E(); var d = new D(e1) as D?; E? e2 = d?.v++; Expect.identical(e1, e2); }
diff --git a/tests/language/null_aware/increment_decrement_runtime_9_test.dart b/tests/language/null_aware/increment_decrement_runtime_9_test.dart
index cd3bd72..7b42679 100644
--- a/tests/language/null_aware/increment_decrement_runtime_9_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_9_test.dart
@@ -61,7 +61,7 @@
// e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
- { C? c = new C(1); Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
+ { var c = new C(1) as C?; Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
// C?.v-- is equivalent to C.v--.
diff --git a/tests/language/null_aware/increment_decrement_test.dart b/tests/language/null_aware/increment_decrement_test.dart
index 0b620fc..7e80690 100644
--- a/tests/language/null_aware/increment_decrement_test.dart
+++ b/tests/language/null_aware/increment_decrement_test.dart
@@ -42,16 +42,16 @@
// e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
Expect.equals(null, nullC()?.v++);
- { C? c = new C(1); Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
+ { var c = new C(1) as C?; Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
// C?.v++ is equivalent to C.v++.
{ C.staticInt = 1; Expect.equals(1, C?.staticInt++); Expect.equals(2, C.staticInt); }
{ h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt++); Expect.equals(2, h.C.staticInt); }
// The static type of e1?.v++ is the same as the static type of e1.v.
- { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v++; Expect.identical(e1, e2); }
- { G g = new G(); D? d = new D(g); F? f = d?.v++; Expect.identical(f, g); }
- // ^^^^^^
+ { E e1 = new E(); var d = new D(e1) as D?; E? e2 = d?.v++; Expect.identical(e1, e2); }
+ { G g = new G(); var d = new D(g) as D?; F? f = d?.v++; Expect.identical(f, g); }
+ // ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
// [cfe] A value of type 'E?' can't be assigned to a variable of type 'F?'.
{ E e1 = new E(); D.staticE = e1; E? e2 = D?.staticE++; Expect.identical(e1, e2); }
@@ -69,16 +69,16 @@
// e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
Expect.equals(null, nullC()?.v--);
- { C? c = new C(1); Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
+ { var c = new C(1) as C?; Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
// C?.v-- is equivalent to C.v--.
{ C.staticInt = 1; Expect.equals(1, C?.staticInt--); Expect.equals(0, C.staticInt); }
{ h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt--); Expect.equals(0, h.C.staticInt); }
// The static type of e1?.v-- is the same as the static type of e1.v.
- { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v--; Expect.identical(e1, e2); }
- { G g = new G(); D? d = new D(g); F? f = d?.v--; Expect.identical(f, g); }
- // ^^^^^^
+ { E e1 = new E(); var d = new D(e1) as D?; E? e2 = d?.v--; Expect.identical(e1, e2); }
+ { G g = new G(); var d = new D(g) as D?; F? f = d?.v--; Expect.identical(f, g); }
+ // ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
// [cfe] A value of type 'E?' can't be assigned to a variable of type 'F?'.
{ E e1 = new E(); D.staticE = e1; E? e2 = D?.staticE--; Expect.identical(e1, e2); }
@@ -96,18 +96,18 @@
// ++e1?.v is equivalent to e1?.v += 1.
Expect.equals(null, ++nullC()?.v);
- { C? c = new C(1); Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
+ { var c = new C(1) as C?; Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
// ++C?.v is equivalent to C?.v += 1.
{ C.staticInt = 1; Expect.equals(2, ++C?.staticInt); Expect.equals(2, C.staticInt); }
{ h.C.staticInt = 1; Expect.equals(2, ++h.C?.staticInt); Expect.equals(2, h.C.staticInt); }
// The static type of ++e1?.v is the same as the static type of e1.v + 1.
- { D? d = new D(new E()); F? f = ++d?.v; Expect.identical(d!.v, f); }
- { D? d = new D(new E()); H? h = ++d?.v; Expect.identical(d!.v, h); }
- // ^^^^^^
+ { var d = new D(new E()) as D?; F? f = ++d?.v; Expect.identical(d!.v, f); }
+ { var d = new D(new E()) as D?; H? h = ++d?.v; Expect.identical(d!.v, h); }
+ // ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
- // ^
+ // ^
// [cfe] A value of type 'G?' can't be assigned to a variable of type 'H?'.
{ D.staticE = new E(); F? f = ++D?.staticE; Expect.identical(D.staticE, f); }
{ h.D.staticE = new h.E(); h.F? f = ++h.D?.staticE; Expect.identical(h.D.staticE, f); }
@@ -124,18 +124,18 @@
// --e1?.v is equivalent to e1?.v -= 1.
Expect.equals(null, --nullC()?.v);
- { C? c = new C(1); Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
+ { var c = new C(1) as C?; Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
// --C?.v is equivalent to C?.v -= 1.
{ C.staticInt = 1; Expect.equals(0, --C?.staticInt); Expect.equals(0, C.staticInt); }
{ h.C.staticInt = 1; Expect.equals(0, --h.C?.staticInt); Expect.equals(0, h.C.staticInt); }
// The static type of --e1?.v is the same as the static type of e1.v - 1.
- { D? d = new D(new E()); F? f = --d?.v; Expect.identical(d!.v, f); }
- { D? d = new D(new E()); H? h = --d?.v; Expect.identical(d!.v, h); }
- // ^^^^^^
+ { var d = new D(new E()) as D?; F? f = --d?.v; Expect.identical(d!.v, f); }
+ { var d = new D(new E()) as D?; H? h = --d?.v; Expect.identical(d!.v, h); }
+ // ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
- // ^
+ // ^
// [cfe] A value of type 'G?' can't be assigned to a variable of type 'H?'.
{ D.staticE = new E(); F? f = --D?.staticE; Expect.identical(D.staticE, f); }
{ h.D.staticE = new h.E(); h.F? f = --h.D?.staticE; Expect.identical(h.D.staticE, f); }
diff --git a/tests/language/null_aware/invocation_runtime_2_test.dart b/tests/language/null_aware/invocation_runtime_2_test.dart
index 70a36d1..8c11b27 100644
--- a/tests/language/null_aware/invocation_runtime_2_test.dart
+++ b/tests/language/null_aware/invocation_runtime_2_test.dart
@@ -32,7 +32,7 @@
// o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
- C? c = C();
+ var c = C() as C?;
Expect.equals(1, c?.f(() => 1));
// C?.m(...) is equivalent to C.m(...).
diff --git a/tests/language/null_aware/invocation_runtime_6_test.dart b/tests/language/null_aware/invocation_runtime_6_test.dart
index 23559d8..bbabd59 100644
--- a/tests/language/null_aware/invocation_runtime_6_test.dart
+++ b/tests/language/null_aware/invocation_runtime_6_test.dart
@@ -41,7 +41,7 @@
// The static type of o?.m(...) is the same as the static type of
// o.m(...).
- C? c = new C();
+ var c = new C() as C?;
{ int? i = c?.g(() => 1); Expect.equals(1, i); }
diff --git a/tests/language/null_aware/invocation_test.dart b/tests/language/null_aware/invocation_test.dart
index a1515fa..b1f38e6 100644
--- a/tests/language/null_aware/invocation_test.dart
+++ b/tests/language/null_aware/invocation_test.dart
@@ -23,7 +23,7 @@
C? nullC() => null;
main() {
- C? c = C();
+ var c = C() as C?;
// Make sure the "none" test fails if method invocation using "?." is not
// implemented. This makes status files easier to maintain.
@@ -66,12 +66,12 @@
// Let T be the static type of o and let y be a fresh variable of type T.
// Exactly the same static warnings that would be caused by y.m(...) are also
// generated in the case of o?.m(...).
- { B? b = new C(); Expect.equals(1, b?.f(() => 1)); }
- // ^
+ { var b = new C() as B?; Expect.equals(1, b?.f(() => 1)); }
+ // ^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD
// [cfe] The method 'f' isn't defined for the class 'B'.
- { int? i = 1; Expect.equals(null, nullC()?.f(i)); }
- // ^
+ { var i = 1 as int?; Expect.equals(null, nullC()?.f(i)); }
+ // ^
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'int?' can't be assigned to the parameter type 'dynamic Function()?'.
diff --git a/tests/language/null_aware/null_shortening_test.dart b/tests/language/null_aware/null_shortening_test.dart
index b3510a5..625bc08 100644
--- a/tests/language/null_aware/null_shortening_test.dart
+++ b/tests/language/null_aware/null_shortening_test.dart
@@ -50,11 +50,11 @@
main() {
C1 c1 = C1();
- C1? c1q = c1;
+ var c1q = c1 as C1?;
C1? c1n = null;
C2 c2 = C2();
- C2? c2q = c2;
+ var c2q = c2 as C2?;
// All selector operations short on null.
// .foo
diff --git a/tests/language/null_aware/opt_test.dart b/tests/language/null_aware/opt_test.dart
index c5bb8a7..57f3848 100644
--- a/tests/language/null_aware/opt_test.dart
+++ b/tests/language/null_aware/opt_test.dart
@@ -23,17 +23,17 @@
test() {
var c;
- C? d = new C(5);
+ var d = new C(5) as C?;
Expect.equals(null, c?.m(bomb()));
Expect.equals(null, getNull()?.anything(bomb()));
Expect.equals(1, d?.m(1));
- C? c2 = new C(1);
+ var c2 = new C(1) as C?;
Expect.equals(1, c2?.f);
Expect.equals(null, c?.v);
Expect.equals(10, c ?? 10);
Expect.equals(d, d ?? bomb());
- List<List<int>>? list = [[3]];
+ var list = [[3]] as List<List<int>>?;
Expect.equals(
3,
list?.expand((i) => i).toList()[0]);
@@ -58,7 +58,7 @@
e?.f++;
Expect.equals(201, e.f);
- int? five = 5;
+ var five = 5 as int?;
var x = five ?? bomb();
}
diff --git a/tests/language/spread_collections/const_test.dart b/tests/language/spread_collections/const_test.dart
index 1eb4d76..cab125f 100644
--- a/tests/language/spread_collections/const_test.dart
+++ b/tests/language/spread_collections/const_test.dart
@@ -43,8 +43,8 @@
const <int>[...<int>[...<int>[1, 2], ...<int>[3, 4]]]);
// Null-aware.
- const List<int>? list23 = <int>[2, 3];
- const List<int>? list4 = <int>[4];
+ const list23 = <int>[2, 3] as List<int>?;
+ const list4 = <int>[4] as List<int>?;
Expect.identical(list,
const <int>[1, ...?list23, ...?(null), ...?list4]);
@@ -98,8 +98,8 @@
});
// Null-aware.
- const Map<int, int>? map23 = <int, int>{2: 2, 3: 3};
- const Map<int, int>? map4 = <int, int>{4: 4};
+ const map23 = <int, int>{2: 2, 3: 3} as Map<int, int>?;
+ const map4 = <int, int>{4: 4} as Map<int, int>?;
Expect.identical(map, const <int, int>{
1: 1,
...?map23,
@@ -155,8 +155,8 @@
Expect.identical(set, const <int>{...<int>{...<int>[1, 2], ...<int>[3, 4]}});
// Null-aware.
- const List<int>? list23 = <int>[2, 3];
- const List<int>? list4 = <int>[4];
+ const list23 = <int>[2, 3] as List<int>?;
+ const list4 = <int>[4] as List<int>?;
Expect.identical(set,
const <int>{1, ...?list23, ...?(null), ...?list4});
diff --git a/tests/language/spread_collections/spread_test.dart b/tests/language/spread_collections/spread_test.dart
index 2a19168..baee04c 100644
--- a/tests/language/spread_collections/spread_test.dart
+++ b/tests/language/spread_collections/spread_test.dart
@@ -43,8 +43,8 @@
Expect.listEquals(list, <int>[...<int>[...<int>[1, 2], ...<int>[3, 4]]]);
// Null-aware.
- List<int>? list23 = [2, 3];
- List<int>? list4 = [4];
+ var list23 = [2, 3] as List<int>?;
+ var list4 = [4] as List<int>?;
Expect.listEquals(list, <int>[1, ...?list23, ...?(null), ...?list4]);
// Does not deep flatten.
@@ -94,8 +94,8 @@
});
// Null-aware.
- Map<int, int>? map23 = {2: 2, 3: 3};
- Map<int, int>? map4 = {4: 4};
+ var map23 = {2: 2, 3: 3} as Map<int, int>?;
+ var map4 = {4: 4} as Map<int, int>?;
Expect.mapEquals(map, <int, int>{
1: 1,
...?map23,
@@ -147,8 +147,8 @@
Expect.setEquals(set, <int>{...<int>{...<int>[1, 2], ...<int>[3, 4]}});
// Null-aware.
- List<int>? list23 = [2, 3];
- List<int>? list4 = [4];
+ var list23 = [2, 3] as List<int>?;
+ var list4 = [4] as List<int>?;
Expect.setEquals(set, <int>{1, ...?list23, ...?(null), ...?list4});
// Does not deep flatten.
diff --git a/tests/language/spread_collections/syntax_test.dart b/tests/language/spread_collections/syntax_test.dart
index aa6a51f..ed6676f 100644
--- a/tests/language/spread_collections/syntax_test.dart
+++ b/tests/language/spread_collections/syntax_test.dart
@@ -17,11 +17,11 @@
var a = [0];
Expect.listEquals([1, 2, 3], [1, ...a = [2], 3]);
- List<int>? nullableA = [0];
+ var nullableA = [0] as List<int>?;
Expect.listEquals([1, 3], [1, ...?nullableA = null, 3]);
var b = [2];
Expect.listEquals([1, 2, 3, 4], [1, ...b..add(3), 4]);
- List<int>? nullableB = [2];
+ var nullableB = [2] as List<int>?;
Expect.listEquals([1, 2, 3, 4], [1, ...?nullableB?..add(3), 4]);
}
diff --git a/tools/VERSION b/tools/VERSION
index 15ebdcb..e82a042 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 11
PATCH 0
-PRERELEASE 195
+PRERELEASE 196
PRERELEASE_PATCH 0
\ No newline at end of file