@@ -789,7 +789,8 @@ class State<Variable, Type> {
789789 }
790790
791791 /// Updates the state to indicate that the given [variable] has been
792- /// determined to satisfy the given [type] .
792+ /// determined to satisfy the given [type] , e.g. as a consequence of an `is`
793+ /// expression as the condition of an `if` statement.
793794 ///
794795 /// Note that the state is only changed if [type] is a subtype of the
795796 /// variable's previous (possibly promoted) type.
@@ -820,6 +821,23 @@ class State<Variable, Type> {
820821
821822 /// Updates the state to indicate that the given [variables] are no longer
822823 /// promoted; they are presumed to have their declared types.
824+ ///
825+ /// This is used at the top of loops to conservatively cancel the promotion of
826+ /// variables that are modified within the loop, so that we correctly analyze
827+ /// code like the following:
828+ ///
829+ /// if (x is int) {
830+ /// x.isEven; // OK, promoted to int
831+ /// while (true) {
832+ /// x.isEven; // ERROR: promotion lost
833+ /// x = 'foo';
834+ /// }
835+ /// }
836+ ///
837+ /// Note that a more accurate analysis would be to iterate to a fixed point,
838+ /// and only remove promotions if it can be shown that they aren't restored
839+ /// later in the loop body. If we switch to a fixed point analysis, we should
840+ /// be able to remove this method.
823841 State <Variable , Type > removePromotedAll (Set <Variable > variables) {
824842 var newPromoted = _removePromotedAll (promoted, variables);
825843
@@ -835,13 +853,23 @@ class State<Variable, Type> {
835853 /// Updates the state to reflect a control path that is known to have
836854 /// previously passed through some [other] state.
837855 ///
856+ /// Approximately, this method forms the union of the definite assignments and
857+ /// promotions in `this` state and the [other] state. More precisely:
858+ ///
838859 /// The control flow path is considered reachable if both this state and the
839860 /// other state are reachable. Variables are considered definitely assigned
840861 /// if they were definitely assigned in either this state or the other state.
841862 /// Variable type promotions are taken from this state, unless the promotion
842863 /// in the other state is more specific, and the variable is "safe". A
843864 /// variable is considered safe if there is no chance that it was assigned
844865 /// more recently than the "other" state.
866+ ///
867+ /// This is used after a `try/finally` statement to combine the promotions and
868+ /// definite assignments that occurred in the `try` and `finally` blocks
869+ /// (where `this` is the state from the `finally` block and `other` is the
870+ /// state from the `try` block). Variables that are assigned in the `finally`
871+ /// block are considered "unsafe" because the assignment might have cancelled
872+ /// the effect of any promotion that occurred inside the `try` block.
845873 State <Variable , Type > restrict (
846874 TypeOperations <Variable , Type > typeOperations,
847875 _VariableSet <Variable > emptySet,
0 commit comments