Skip to content

Commit 9ec6a48

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Flow analysis: document the State class
Change-Id: I36f71953912d23cc77473e56caca14c4d9df19d3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/109894 Commit-Queue: Paul Berry <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]>
1 parent 06b7329 commit 9ec6a48

File tree

1 file changed

+62
-1
lines changed

1 file changed

+62
-1
lines changed

pkg/analyzer/lib/src/dart/resolver/flow_analysis.dart

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -701,12 +701,31 @@ abstract class NodeOperations<Expression> {
701701
Expression unwrapParenthesized(Expression node);
702702
}
703703

704+
/// An instance of the [State] class represents the information gathered by flow
705+
/// analysis at a single point in the control flow of the function or method
706+
/// being analyzed.
707+
///
708+
/// Instances of this class are immuatable, so the methods below that "update"
709+
/// the state actually leave `this` unchanged and return a new state object.
704710
@visibleForTesting
705711
class State<Variable, Type> {
712+
/// Indicates whether this point in the control flow is reachable.
706713
final bool reachable;
714+
715+
/// The set of variables that are not yet definitely assigned at this point in
716+
/// the control flow.
707717
final _VariableSet<Variable> notAssigned;
718+
719+
/// For each variable whose type is promoted at this point in the control
720+
/// flow, the promoted type. Variables whose type is not promoted are not
721+
/// present in the map. Variables that have gone out of scope are not
722+
/// guaranteed to be present in the map even if they were promoted at the time
723+
/// they went out of scope.
708724
final Map<Variable, Type> promoted;
709725

726+
/// Creates a state object with the given [reachable] status. All variables
727+
/// are assumed to be unpromoted and already assigned, so joining another
728+
/// state with this one will have no effect on it.
710729
State(bool reachable)
711730
: this._(
712731
reachable,
@@ -720,7 +739,9 @@ class State<Variable, Type> {
720739
this.promoted,
721740
);
722741

723-
/// Add a new [variable] to track definite assignment.
742+
/// Updates the state to track a newly declared local [variable]. The
743+
/// optional [assigned] boolean indicates whether the variable is assigned at
744+
/// the point of declaration.
724745
State<Variable, Type> add(Variable variable, {bool assigned: false}) {
725746
var newNotAssigned = assigned ? notAssigned : notAssigned.add(variable);
726747

@@ -735,6 +756,7 @@ class State<Variable, Type> {
735756
);
736757
}
737758

759+
/// Updates the state to indicate that the control flow path is unreachable.
738760
State<Variable, Type> exit() {
739761
return State<Variable, Type>._(
740762
false,
@@ -743,6 +765,11 @@ class State<Variable, Type> {
743765
);
744766
}
745767

768+
/// Updates the state to indicate that the given [variable] has been
769+
/// determined to contain a non-null value.
770+
///
771+
/// TODO(paulberry): should this method mark the variable as definitely
772+
/// assigned? Does it matter?
746773
State<Variable, Type> markNonNullable(
747774
TypeOperations<Variable, Type> typeOperations, Variable variable) {
748775
var previousType = promoted[variable];
@@ -762,6 +789,14 @@ class State<Variable, Type> {
762789
return this;
763790
}
764791

792+
/// Updates the state to indicate that the given [variable] has been
793+
/// determined to satisfy the given [type].
794+
///
795+
/// Note that the state is only changed if [type] is a subtype of the
796+
/// variable's previous (possibly promoted) type.
797+
///
798+
/// TODO(paulberry): if the type is non-nullable, should this method mark the
799+
/// variable as definitely assigned? Does it matter?
765800
State<Variable, Type> promote(
766801
TypeOperations<Variable, Type> typeOperations,
767802
Variable variable,
@@ -784,6 +819,8 @@ class State<Variable, Type> {
784819
return this;
785820
}
786821

822+
/// Updates the state to indicate that the given [variables] are no longer
823+
/// promoted; they are presumed to have their declared types.
787824
State<Variable, Type> removePromotedAll(Set<Variable> variables) {
788825
var newPromoted = _removePromotedAll(promoted, variables);
789826

@@ -796,6 +833,16 @@ class State<Variable, Type> {
796833
);
797834
}
798835

836+
/// Updates the state to reflect a control path that is known to have
837+
/// previously passed through some [other] state.
838+
///
839+
/// The control flow path is considered reachable if both this state and the
840+
/// other state are reachable. Variables are considered definitely assigned
841+
/// if they were definitely assigned in either this state or the other state.
842+
/// Variable type promotions are taken from this state, unless the promotion
843+
/// in the other state is more specific, and the variable is "safe". A
844+
/// variable is considered safe if there is no chance that it was assigned
845+
/// more recently than the "other" state.
799846
State<Variable, Type> restrict(
800847
TypeOperations<Variable, Type> typeOperations,
801848
_VariableSet<Variable> emptySet,
@@ -866,6 +913,8 @@ class State<Variable, Type> {
866913
);
867914
}
868915

916+
/// Updates the state to indicate whether the control flow path is
917+
/// [reachable].
869918
State<Variable, Type> setReachable(bool reachable) {
870919
if (this.reachable == reachable) return this;
871920

@@ -879,6 +928,11 @@ class State<Variable, Type> {
879928
@override
880929
String toString() => '($reachable, $notAssigned, $promoted)';
881930

931+
/// Updates the state to indicate that an assignment was made to the given
932+
/// [variable]. The variable is marked as definitely assigned, and any
933+
/// previous type promotion is removed.
934+
///
935+
/// TODO(paulberry): allow for writes that preserve type promotions.
882936
State<Variable, Type> write(TypeOperations<Variable, Type> typeOperations,
883937
_VariableSet<Variable> emptySet, Variable variable) {
884938
var newNotAssigned = typeOperations.isLocalVariable(variable)
@@ -899,6 +953,8 @@ class State<Variable, Type> {
899953
);
900954
}
901955

956+
/// Removes a [variable] from a "promoted" [map], treating the map as
957+
/// immutable.
902958
Map<Variable, Type> _removePromoted(
903959
Map<Variable, Type> map, Variable variable) {
904960
if (map.isEmpty) return const {};
@@ -914,6 +970,8 @@ class State<Variable, Type> {
914970
return result;
915971
}
916972

973+
/// Removes a set of [variable]s from a "promoted" [map], treating the map as
974+
/// immutable.
917975
Map<Variable, Type> _removePromotedAll(
918976
Map<Variable, Type> map,
919977
Set<Variable> variables,
@@ -936,6 +994,8 @@ class State<Variable, Type> {
936994
return result;
937995
}
938996

997+
/// Creates a new [State] object, unless it is equivalent to either [first] or
998+
/// [second], in which case one of those objects is re-used.
939999
static State<Variable, Type> _identicalOrNew<Variable, Type>(
9401000
State<Variable, Type> first,
9411001
State<Variable, Type> second,
@@ -961,6 +1021,7 @@ class State<Variable, Type> {
9611021
);
9621022
}
9631023

1024+
/// Determines whether the given "promoted" maps are equivalent.
9641025
static bool _promotionsEqual<Variable, Type>(
9651026
TypeOperations<Variable, Type> typeOperations,
9661027
Map<Variable, Type> p1,

0 commit comments

Comments
 (0)