@@ -2566,8 +2566,12 @@ class _EqualityOpContext<Variable, Type> extends _BranchContext {
2566
2566
/// The type of the expression on the LHS of `==` or `!=` .
2567
2567
final Type _leftOperandType;
2568
2568
2569
- _EqualityOpContext (
2570
- ExpressionInfo <Variable , Type > conditionInfo, this ._leftOperandType)
2569
+ /// If the LHS of `==` or `!=` is a variable reference, the variable.
2570
+ /// Otherwise `null` .
2571
+ final Variable _leftOperandVariable;
2572
+
2573
+ _EqualityOpContext (ExpressionInfo <Variable , Type > conditionInfo,
2574
+ this ._leftOperandType, this ._leftOperandVariable)
2571
2575
: super (conditionInfo);
2572
2576
2573
2577
@override
@@ -2602,6 +2606,14 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
2602
2606
/// corresponding to it. Otherwise `null` .
2603
2607
ExpressionInfo <Variable , Type > _expressionInfo;
2604
2608
2609
+ /// The most recently visited expression which was a variable reference, or
2610
+ /// `null` if no expression has been visited that was a variable reference.
2611
+ Expression _expressionWithVariable;
2612
+
2613
+ /// If [_expressionVariable] is not `null` , the variable corresponding to it.
2614
+ /// Otherwise `null` .
2615
+ Variable _expressionVariable;
2616
+
2605
2617
int _functionNestingLevel = 0 ;
2606
2618
2607
2619
final AssignedVariables <Node , Variable > _assignedVariables;
@@ -2615,14 +2627,8 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
2615
2627
2616
2628
@override
2617
2629
void asExpression_end (Expression subExpression, Type type) {
2618
- ExpressionInfo <Variable , Type > subExpressionInfo =
2619
- _getExpressionInfo (subExpression);
2620
- Variable variable;
2621
- if (subExpressionInfo is _VariableReadInfo <Variable , Type >) {
2622
- variable = subExpressionInfo._variable;
2623
- } else {
2624
- return ;
2625
- }
2630
+ Variable variable = _getExpressionVariable (subExpression);
2631
+ if (variable == null ) return ;
2626
2632
_current = _current.tryPromoteForTypeCast (typeOperations, variable, type);
2627
2633
}
2628
2634
@@ -2730,8 +2736,10 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
2730
2736
_EqualityOpContext <Variable , Type > context =
2731
2737
_stack.removeLast () as _EqualityOpContext <Variable , Type >;
2732
2738
ExpressionInfo <Variable , Type > lhsInfo = context._conditionInfo;
2739
+ Variable lhsVariable = context._leftOperandVariable;
2733
2740
Type leftOperandType = context._leftOperandType;
2734
2741
ExpressionInfo <Variable , Type > rhsInfo = _getExpressionInfo (rightOperand);
2742
+ Variable rhsVariable = _getExpressionVariable (rightOperand);
2735
2743
TypeClassification leftOperandTypeClassification =
2736
2744
typeOperations.classifyType (leftOperandType);
2737
2745
TypeClassification rightOperandTypeClassification =
@@ -2749,18 +2757,16 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
2749
2757
// but weak mode it might produce an "equal" result. We don't want flow
2750
2758
// analysis behavior to depend on mode, so we conservatively assume that
2751
2759
// either result is possible.
2752
- } else if (lhsInfo is _NullInfo <Variable , Type > &&
2753
- rhsInfo is _VariableReadInfo <Variable , Type >) {
2760
+ } else if (lhsInfo is _NullInfo <Variable , Type > && rhsVariable != null ) {
2754
2761
assert (
2755
2762
leftOperandTypeClassification == TypeClassification .nullOrEquivalent);
2756
2763
ExpressionInfo <Variable , Type > equalityInfo =
2757
- _current.tryMarkNonNullable (typeOperations, rhsInfo._variable );
2764
+ _current.tryMarkNonNullable (typeOperations, rhsVariable );
2758
2765
_storeExpressionInfo (wholeExpression,
2759
2766
notEqual ? equalityInfo : ExpressionInfo .invert (equalityInfo));
2760
- } else if (rhsInfo is _NullInfo <Variable , Type > &&
2761
- lhsInfo is _VariableReadInfo <Variable , Type >) {
2767
+ } else if (rhsInfo is _NullInfo <Variable , Type > && lhsVariable != null ) {
2762
2768
ExpressionInfo <Variable , Type > equalityInfo =
2763
- _current.tryMarkNonNullable (typeOperations, lhsInfo._variable );
2769
+ _current.tryMarkNonNullable (typeOperations, lhsVariable );
2764
2770
_storeExpressionInfo (wholeExpression,
2765
2771
notEqual ? equalityInfo : ExpressionInfo .invert (equalityInfo));
2766
2772
}
@@ -2769,7 +2775,9 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
2769
2775
@override
2770
2776
void equalityOp_rightBegin (Expression leftOperand, Type leftOperandType) {
2771
2777
_stack.add (new _EqualityOpContext <Variable , Type >(
2772
- _getExpressionInfo (leftOperand), leftOperandType));
2778
+ _getExpressionInfo (leftOperand),
2779
+ leftOperandType,
2780
+ _getExpressionVariable (leftOperand)));
2773
2781
}
2774
2782
2775
2783
@override
@@ -2844,6 +2852,9 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
2844
2852
if (identical (_expressionWithInfo, oldExpression)) {
2845
2853
_expressionWithInfo = newExpression;
2846
2854
}
2855
+ if (identical (_expressionWithVariable, oldExpression)) {
2856
+ _expressionWithVariable = newExpression;
2857
+ }
2847
2858
}
2848
2859
2849
2860
@override
@@ -2901,12 +2912,12 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
2901
2912
@override
2902
2913
void ifNullExpression_rightBegin (
2903
2914
Expression leftHandSide, Type leftHandSideType) {
2904
- ExpressionInfo < Variable , Type > lhsInfo = _getExpressionInfo (leftHandSide);
2915
+ Variable lhsVariable = _getExpressionVariable (leftHandSide);
2905
2916
FlowModel <Variable , Type > promoted;
2906
2917
_current = _current.split ();
2907
- if (lhsInfo is _VariableReadInfo < Variable , Type > ) {
2918
+ if (lhsVariable != null ) {
2908
2919
ExpressionInfo <Variable , Type > promotionInfo =
2909
- _current.tryMarkNonNullable (typeOperations, lhsInfo._variable );
2920
+ _current.tryMarkNonNullable (typeOperations, lhsVariable );
2910
2921
_current = promotionInfo.ifFalse;
2911
2922
promoted = promotionInfo.ifTrue;
2912
2923
} else {
@@ -2959,12 +2970,10 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
2959
2970
@override
2960
2971
void isExpression_end (Expression isExpression, Expression subExpression,
2961
2972
bool isNot, Type type) {
2962
- ExpressionInfo <Variable , Type > subExpressionInfo =
2963
- _getExpressionInfo (subExpression);
2964
- if (subExpressionInfo is _VariableReadInfo <Variable , Type >) {
2965
- ExpressionInfo <Variable , Type > expressionInfo =
2966
- _current.tryPromoteForTypeCheck (
2967
- typeOperations, subExpressionInfo._variable, type);
2973
+ Variable subExpressionVariable = _getExpressionVariable (subExpression);
2974
+ if (subExpressionVariable != null ) {
2975
+ ExpressionInfo <Variable , Type > expressionInfo = _current
2976
+ .tryPromoteForTypeCheck (typeOperations, subExpressionVariable, type);
2968
2977
_storeExpressionInfo (isExpression,
2969
2978
isNot ? ExpressionInfo .invert (expressionInfo) : expressionInfo);
2970
2979
}
@@ -3054,11 +3063,10 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
3054
3063
3055
3064
@override
3056
3065
void nonNullAssert_end (Expression operand) {
3057
- ExpressionInfo <Variable , Type > operandInfo = _getExpressionInfo (operand);
3058
- if (operandInfo is _VariableReadInfo <Variable , Type >) {
3059
- _current = _current
3060
- .tryMarkNonNullable (typeOperations, operandInfo._variable)
3061
- .ifTrue;
3066
+ Variable operandVariable = _getExpressionVariable (operand);
3067
+ if (operandVariable != null ) {
3068
+ _current =
3069
+ _current.tryMarkNonNullable (typeOperations, operandVariable).ifTrue;
3062
3070
}
3063
3071
}
3064
3072
@@ -3075,11 +3083,10 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
3075
3083
_current = _current.split ();
3076
3084
_stack.add (new _NullAwareAccessContext <Variable , Type >(_current));
3077
3085
if (target != null ) {
3078
- ExpressionInfo <Variable , Type > targetInfo = _getExpressionInfo (target);
3079
- if (targetInfo is _VariableReadInfo <Variable , Type >) {
3080
- _current = _current
3081
- .tryMarkNonNullable (typeOperations, targetInfo._variable)
3082
- .ifTrue;
3086
+ Variable targetVariable = _getExpressionVariable (target);
3087
+ if (targetVariable != null ) {
3088
+ _current =
3089
+ _current.tryMarkNonNullable (typeOperations, targetVariable).ifTrue;
3083
3090
}
3084
3091
}
3085
3092
}
@@ -3226,7 +3233,7 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
3226
3233
3227
3234
@override
3228
3235
Type variableRead (Expression expression, Variable variable) {
3229
- _storeExpressionInfo (expression, new _VariableReadInfo (_current, variable) );
3236
+ _storeExpressionVariable (expression, variable);
3230
3237
return _current.infoFor (variable).promotedTypes? .last;
3231
3238
}
3232
3239
@@ -3273,6 +3280,8 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
3273
3280
print (' current: $_current ' );
3274
3281
print (' expressionWithInfo: $_expressionWithInfo ' );
3275
3282
print (' expressionInfo: $_expressionInfo ' );
3283
+ print (' expressionWithVariable: $_expressionWithVariable ' );
3284
+ print (' expressionVariable: $_expressionVariable ' );
3276
3285
print (' stack:' );
3277
3286
for (_FlowContext stackEntry in _stack.reversed) {
3278
3287
print (' $stackEntry ' );
@@ -3301,6 +3310,19 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
3301
3310
}
3302
3311
}
3303
3312
3313
+ /// Gets the [Variable] associated with the [expression] (which should be the
3314
+ /// last expression that was traversed). If there is no [Variable] associated
3315
+ /// with the [expression] , then `null` is returned.
3316
+ Variable _getExpressionVariable (Expression expression) {
3317
+ if (identical (expression, _expressionWithVariable)) {
3318
+ Variable expressionVariable = _expressionVariable;
3319
+ _expressionVariable = null ;
3320
+ return expressionVariable;
3321
+ } else {
3322
+ return null ;
3323
+ }
3324
+ }
3325
+
3304
3326
FlowModel <Variable , Type > _join (
3305
3327
FlowModel <Variable , Type > first, FlowModel <Variable , Type > second) =>
3306
3328
FlowModel .join (typeOperations, first, second, _current._emptyVariableMap);
@@ -3319,6 +3341,14 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
3319
3341
_expressionInfo = expressionInfo;
3320
3342
_current = expressionInfo.after;
3321
3343
}
3344
+
3345
+ /// Associates [expression] , which should be the most recently visited
3346
+ /// expression, with the given [Variable] object.
3347
+ void _storeExpressionVariable (
3348
+ Expression expression, Variable expressionVariable) {
3349
+ _expressionWithVariable = expression;
3350
+ _expressionVariable = expressionVariable;
3351
+ }
3322
3352
}
3323
3353
3324
3354
/// Base class for objects representing constructs in the Dart programming
@@ -3437,28 +3467,6 @@ class _TryContext<Variable, Type> extends _SimpleContext<Variable, Type> {
3437
3467
'afterBodyAndCatches: $_afterBodyAndCatches )' ;
3438
3468
}
3439
3469
3440
- /// [ExpressionInfo] representing an expression that reads the value of a
3441
- /// variable.
3442
- class _VariableReadInfo <Variable , Type >
3443
- implements ExpressionInfo <Variable , Type > {
3444
- @override
3445
- final FlowModel <Variable , Type > after;
3446
-
3447
- /// The variable that is being read.
3448
- final Variable _variable;
3449
-
3450
- _VariableReadInfo (this .after, this ._variable);
3451
-
3452
- @override
3453
- FlowModel <Variable , Type > get ifFalse => after;
3454
-
3455
- @override
3456
- FlowModel <Variable , Type > get ifTrue => after;
3457
-
3458
- @override
3459
- String toString () => '_VariableReadInfo(after: $after , variable: $_variable )' ;
3460
- }
3461
-
3462
3470
/// [_FlowContext] representing a `while` loop (or a C-style `for` loop, which
3463
3471
/// is functionally similar).
3464
3472
class _WhileContext <Variable , Type >
0 commit comments