@@ -229,16 +229,16 @@ class AssignedVariablesForTesting<Node, Variable>
229229
230230/// Information tracked by [AssignedVariables] for a single node.
231231class AssignedVariablesNodeInfo <Variable > {
232+ /// The set of local variables that are potentially written in the node.
232233 final Set <Variable > _written = new Set <Variable >.identity ();
233234
234- // The set of local variables that are potentially written in the node.
235+ /// The set of local variables for which a potential write is captured by a
236+ /// local function or closure inside the node.
235237 final Set <Variable > _captured = new Set <Variable >.identity ();
236238
237- // The set of local variables for which a potential write is captured by a
238- // local function or closure inside the node.
239+ /// The set of local variables that are declared in the node.
239240 final Set <Variable > _declared = new Set <Variable >.identity ();
240241
241- // The set of local variables that are declared in the node.
242242 String toString () =>
243243 'AssignedVariablesNodeInfo(_written=$_written , _captured=$_captured , '
244244 '_declared=$_declared )' ;
@@ -341,6 +341,13 @@ abstract class FlowAnalysis<Node, Statement extends Node, Expression, Variable,
341341 /// ("?:"). [condition] should be the expression preceding the "?".
342342 void conditional_thenBegin (Expression condition);
343343
344+ /// Register a declaration of the [variable] in the current state.
345+ /// Should also be called for function parameters.
346+ ///
347+ /// A local variable is [initialized] if its declaration has an initializer.
348+ /// A function parameter is always initialized, so [initialized] is `true` .
349+ void declare (Variable variable, bool initialized);
350+
344351 /// Call this method before visiting the body of a "do-while" statement.
345352 /// [doStatement] should be the same node that was passed to
346353 /// [AssignedVariables.endNode] for the do-while statement.
@@ -494,10 +501,6 @@ abstract class FlowAnalysis<Node, Statement extends Node, Expression, Variable,
494501 /// - Call [ifStatement_end] , passing `true` for `hasElse` .
495502 void ifStatement_thenBegin (Expression condition);
496503
497- /// Register an initialized declaration of the given [variable] in the current
498- /// state. Should also be called for function parameters.
499- void initialize (Variable variable);
500-
501504 /// Return whether the [variable] is definitely assigned in the current state.
502505 bool isAssigned (Variable variable);
503506
@@ -774,6 +777,12 @@ class FlowAnalysisDebug<Node, Statement extends Node, Expression, Variable,
774777 () => _wrapped.conditional_thenBegin (condition));
775778 }
776779
780+ @override
781+ void declare (Variable variable, bool initialized) {
782+ _wrap ('declare($variable , $initialized )' ,
783+ () => _wrapped.declare (variable, initialized));
784+ }
785+
777786 @override
778787 void doStatement_bodyBegin (Statement doStatement) {
779788 return _wrap ('doStatement_bodyBegin($doStatement )' ,
@@ -903,11 +912,6 @@ class FlowAnalysisDebug<Node, Statement extends Node, Expression, Variable,
903912 () => _wrapped.ifStatement_thenBegin (condition));
904913 }
905914
906- @override
907- void initialize (Variable variable) {
908- _wrap ('initialize($variable )' , () => _wrapped.initialize (variable));
909- }
910-
911915 @override
912916 bool isAssigned (Variable variable) {
913917 return _wrap ('isAssigned($variable )' , () => _wrapped.isAssigned (variable),
@@ -1152,20 +1156,24 @@ class FlowModel<Variable, Type> {
11521156 }());
11531157 }
11541158
1155- /// Gets the info for the given [variable] , creating it if it doesn't exist.
1156- VariableModel <Type > infoFor (Variable variable) =>
1157- variableInfo[variable] ?? _freshVariableInfo;
1159+ /// Register a declaration of the [variable] .
1160+ /// Should also be called for function parameters.
1161+ ///
1162+ /// A local variable is [initialized] if its declaration has an initializer.
1163+ /// A function parameter is always initialized, so [initialized] is `true` .
1164+ FlowModel <Variable , Type > declare (Variable variable, bool initialized) {
1165+ VariableModel <Type > newInfoForVar = _freshVariableInfo;
1166+ if (initialized) {
1167+ newInfoForVar = newInfoForVar.initialize ();
1168+ }
11581169
1159- /// Updates the state to indicate that the given [variable] was initialized.
1160- /// The variable is marked as definitely assigned, and any previous type
1161- /// promotion is removed.
1162- FlowModel <Variable , Type > initialize (Variable variable) {
1163- VariableModel <Type > infoForVar = infoFor (variable);
1164- VariableModel <Type > newInfoForVar = infoForVar.initialize ();
1165- if (identical (newInfoForVar, infoForVar)) return this ;
11661170 return _updateVariableInfo (variable, newInfoForVar);
11671171 }
11681172
1173+ /// Gets the info for the given [variable] , creating it if it doesn't exist.
1174+ VariableModel <Type > infoFor (Variable variable) =>
1175+ variableInfo[variable] ?? _freshVariableInfo;
1176+
11691177 /// Updates the state to indicate that the given [writtenVariables] are no
11701178 /// longer promoted; they are presumed to have their declared types.
11711179 ///
@@ -1245,28 +1253,24 @@ class FlowModel<Variable, Type> {
12451253 in variableInfo.entries) {
12461254 Variable variable = entry.key;
12471255 VariableModel <Type > thisModel = entry.value;
1248- VariableModel <Type > otherModel = other.infoFor (variable);
1256+ VariableModel <Type > otherModel = other.variableInfo[variable];
1257+ if (otherModel == null ) {
1258+ variableInfoMatchesThis = false ;
1259+ continue ;
1260+ }
12491261 VariableModel <Type > restricted = thisModel.restrict (
12501262 typeOperations, otherModel, unsafe.contains (variable));
1251- if (! identical (restricted, _freshVariableInfo)) {
1252- newVariableInfo[variable] = restricted;
1253- }
1263+ newVariableInfo[variable] = restricted;
12541264 if (! identical (restricted, thisModel)) variableInfoMatchesThis = false ;
12551265 if (! identical (restricted, otherModel)) variableInfoMatchesOther = false ;
12561266 }
1257- for (MapEntry <Variable , VariableModel <Type >> entry
1258- in other.variableInfo.entries) {
1259- Variable variable = entry.key;
1260- if (variableInfo.containsKey (variable)) continue ;
1261- VariableModel <Type > thisModel = _freshVariableInfo;
1262- VariableModel <Type > otherModel = entry.value;
1263- VariableModel <Type > restricted = thisModel.restrict (
1264- typeOperations, otherModel, unsafe.contains (variable));
1265- if (! identical (restricted, _freshVariableInfo)) {
1266- newVariableInfo[variable] = restricted;
1267+ if (variableInfoMatchesOther) {
1268+ for (Variable variable in other.variableInfo.keys) {
1269+ if (! variableInfo.containsKey (variable)) {
1270+ variableInfoMatchesOther = false ;
1271+ break ;
1272+ }
12671273 }
1268- if (! identical (restricted, thisModel)) variableInfoMatchesThis = false ;
1269- if (! identical (restricted, otherModel)) variableInfoMatchesOther = false ;
12701274 }
12711275 assert (variableInfoMatchesThis ==
12721276 _variableInfosEqual (newVariableInfo, variableInfo));
@@ -1347,10 +1351,13 @@ class FlowModel<Variable, Type> {
13471351 /// previous type promotion is removed.
13481352 FlowModel <Variable , Type > write (Variable variable, Type writtenType,
13491353 TypeOperations <Variable , Type > typeOperations) {
1350- VariableModel <Type > infoForVar = infoFor (variable);
1354+ VariableModel <Type > infoForVar = variableInfo[variable];
1355+ if (infoForVar == null ) return this ;
1356+
13511357 VariableModel <Type > newInfoForVar =
13521358 infoForVar.write (writtenType, typeOperations);
13531359 if (identical (newInfoForVar, infoForVar)) return this ;
1360+
13541361 return _updateVariableInfo (variable, newInfoForVar);
13551362 }
13561363
@@ -2053,6 +2060,11 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
20532060 _current = conditionInfo.ifTrue;
20542061 }
20552062
2063+ @override
2064+ void declare (Variable variable, bool initialized) {
2065+ _current = _current.declare (variable, initialized);
2066+ }
2067+
20562068 @override
20572069 void doStatement_bodyBegin (Statement doStatement) {
20582070 AssignedVariablesNodeInfo <Variable > info =
@@ -2267,11 +2279,6 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
22672279 _current = conditionInfo.ifTrue;
22682280 }
22692281
2270- @override
2271- void initialize (Variable variable) {
2272- _current = _current.initialize (variable);
2273- }
2274-
22752282 @override
22762283 bool isAssigned (Variable variable) {
22772284 return _current.infoFor (variable).assigned;
@@ -2441,10 +2448,10 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
24412448 _stack.last as _TryContext <Variable , Type >;
24422449 _current = context._beforeCatch;
24432450 if (exceptionVariable != null ) {
2444- _current = _current.initialize (exceptionVariable);
2451+ _current = _current.declare (exceptionVariable, true );
24452452 }
24462453 if (stackTraceVariable != null ) {
2447- _current = _current.initialize (stackTraceVariable);
2454+ _current = _current.declare (stackTraceVariable, true );
24482455 }
24492456 }
24502457
0 commit comments