@@ -449,6 +449,26 @@ abstract class FlowAnalysis<Node, Statement extends Node, Expression, Variable,
449449 /// collection element. See [forEach_bodyBegin] for details.
450450 void forEach_end ();
451451
452+ /// Call this method to forward information on [oldExpression] to
453+ /// [newExpression] .
454+ ///
455+ /// This can be used to preserve promotions through a replacement from
456+ /// [oldExpression] to [newExpression] . For instance when rewriting
457+ ///
458+ /// method(int i) {
459+ /// if (i is int) { ... } else { ... }
460+ /// }
461+ ///
462+ /// to
463+ ///
464+ /// method(int i) {
465+ /// if (i is int || throw ...) { ... } else { ... }
466+ /// }
467+ ///
468+ /// the promotion `i is int` can be forwarded to `i is int || throw ...` and
469+ /// there preserved in the surrounding if statement.
470+ void forwardExpression (Expression newExpression, Expression oldExpression);
471+
452472 /// Call this method just before visiting the body of a function expression or
453473 /// local function.
454474 ///
@@ -915,6 +935,12 @@ class FlowAnalysisDebug<Node, Statement extends Node, Expression, Variable,
915935 return _wrap ('forEach_end()' , () => _wrapped.forEach_end ());
916936 }
917937
938+ @override
939+ void forwardExpression (Expression newExpression, Expression oldExpression) {
940+ return _wrap ('forwardExpression($newExpression , $oldExpression )' ,
941+ () => _wrapped.forwardExpression (newExpression, oldExpression));
942+ }
943+
918944 @override
919945 void functionExpression_begin (Node node) {
920946 _wrap ('functionExpression_begin($node )' ,
@@ -1561,9 +1587,17 @@ class FlowModel<Variable, Type> {
15611587 }
15621588
15631589 Type factoredType = typeOperations.factor (previousType, type);
1564- Type typeIfFailed = typeOperations.isSameType (factoredType, previousType)
1565- ? null
1566- : factoredType;
1590+ Type typeIfFailed;
1591+ if (typeOperations.isNever (factoredType)) {
1592+ // Promoting to `Never` would mark the code as unreachable. But it might
1593+ // be reachable due to mixed mode unsoundness. So don't promote.
1594+ typeIfFailed = null ;
1595+ } else if (typeOperations.isSameType (factoredType, previousType)) {
1596+ // No change to the type, so don't promote.
1597+ typeIfFailed = null ;
1598+ } else {
1599+ typeIfFailed = factoredType;
1600+ }
15671601 FlowModel <Variable , Type > modelIfFailed =
15681602 _finishTypeTest (typeOperations, variable, info, type, typeIfFailed);
15691603
@@ -2564,8 +2598,11 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
25642598 (rightOperandTypeClassification ==
25652599 TypeClassification .nullOrEquivalent &&
25662600 leftOperandTypeClassification == TypeClassification .nonNullable)) {
2567- booleanLiteral (wholeExpression, notEqual);
2568- return false ;
2601+ // In strong mode the test is guaranteed to produce a "not equal" result,
2602+ // but weak mode it might produce an "equal" result. We don't want flow
2603+ // analysis behavior to depend on mode, so we conservatively assume that
2604+ // either result is possible.
2605+ return true ;
25692606 } else if (lhsInfo is _NullInfo <Variable , Type > &&
25702607 rhsInfo is _VariableReadInfo <Variable , Type >) {
25712608 assert (
@@ -2581,7 +2618,7 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
25812618 }
25822619 _storeExpressionInfo (wholeExpression,
25832620 notEqual ? equalityInfo : ExpressionInfo .invert (equalityInfo));
2584- return equalityInfo.ifFalse.reachable ;
2621+ return true ;
25852622 }
25862623
25872624 @override
@@ -2655,6 +2692,13 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
26552692 _current = _join (_current, context._previous);
26562693 }
26572694
2695+ @override
2696+ void forwardExpression (Expression newExpression, Expression oldExpression) {
2697+ if (identical (_expressionWithInfo, oldExpression)) {
2698+ _expressionWithInfo = newExpression;
2699+ }
2700+ }
2701+
26582702 @override
26592703 void functionExpression_begin (Node node) {
26602704 AssignedVariablesNodeInfo <Variable > info =
@@ -2720,12 +2764,8 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
27202764 } else {
27212765 promoted = _current;
27222766 }
2723- if (typeOperations.classifyType (leftHandSideType) ==
2724- TypeClassification .nonNullable) {
2725- _current = _current.setReachable (false );
2726- }
27272767 _stack.add (new _SimpleContext <Variable , Type >(promoted));
2728- return _current.reachable ;
2768+ return true ;
27292769 }
27302770
27312771 @override
@@ -2779,7 +2819,7 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
27792819 _current.tryPromoteForTypeCheck (typeOperations, variable, type);
27802820 _storeExpressionInfo (isExpression,
27812821 isNot ? ExpressionInfo .invert (expressionInfo) : expressionInfo);
2782- return expressionInfo.ifFalse.reachable ;
2822+ return true ;
27832823 }
27842824
27852825 @override
@@ -2858,14 +2898,7 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
28582898 @override
28592899 bool nullAwareAccess_rightBegin (Expression target, Type targetType) {
28602900 assert (targetType != null );
2861- bool shortingIsReachable = true ;
2862- FlowModel <Variable , Type > shortingModel = _current;
2863- if (typeOperations.classifyType (targetType) ==
2864- TypeClassification .nonNullable) {
2865- shortingModel = shortingModel.setReachable (false );
2866- shortingIsReachable = false ;
2867- }
2868- _stack.add (new _SimpleContext <Variable , Type >(shortingModel));
2901+ _stack.add (new _SimpleContext <Variable , Type >(_current));
28692902 if (target != null ) {
28702903 ExpressionInfo <Variable , Type > targetInfo = _getExpressionInfo (target);
28712904 if (targetInfo is _VariableReadInfo <Variable , Type >) {
@@ -2874,7 +2907,7 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
28742907 .ifTrue;
28752908 }
28762909 }
2877- return shortingIsReachable ;
2910+ return true ;
28782911 }
28792912
28802913 @override
@@ -2885,9 +2918,7 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
28852918 @override
28862919 void parenthesizedExpression (
28872920 Expression outerExpression, Expression innerExpression) {
2888- if (identical (_expressionWithInfo, innerExpression)) {
2889- _expressionWithInfo = outerExpression;
2890- }
2921+ forwardExpression (outerExpression, innerExpression);
28912922 }
28922923
28932924 @override
0 commit comments