Skip to content

Commit 085529d

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Flow analysis: hardcode allowLocalBooleanVarsToPromote flag.
This flag was being kept around in case the corresponding feature (dart-lang/language#1274) wound up having bugs and needed to be switched off. It's now had sufficient bake time that we no longer need the flag. Removing the flag allows us to remove a bunch of flow analysis code that's no longer needed. Bug: dart-lang/language#1274 Change-Id: Ib91fa09a560bb0ebc6bff280ffc37d6037816ef9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/187981 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent 265f6fc commit 085529d

File tree

6 files changed

+50
-216
lines changed

6 files changed

+50
-216
lines changed

pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart

Lines changed: 21 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,6 @@
44

55
import 'package:meta/meta.dart';
66

7-
/// Set this boolean to `true` to permanently enable the feature of allowing
8-
/// local boolean variables to influence promotion (see
9-
/// https://github.com/dart-lang/language/issues/1274). While this boolean is
10-
/// `false`, the feature remains experimental and can be activated via an
11-
/// optional boolean parameter to the [FlowAnalysis] constructor.
12-
///
13-
/// Changing this value to `true` will cause some dead code warnings to appear
14-
/// for code that only exists to support the old behavior.
15-
const bool allowLocalBooleanVarsToPromoteByDefault = true;
16-
177
/// [AssignedVariables] is a helper class capable of computing the set of
188
/// variables that are potentially written to, and potentially captured by
199
/// closures, at various locations inside the code being analyzed. This class
@@ -242,6 +232,11 @@ class AssignedVariables<Node extends Object, Variable extends Object> {
242232
'{${_info.keys.map((k) => '$k (${k.hashCode})').join(',')}}'));
243233
}
244234

235+
/// Indicates whether information is stored for the given [node].
236+
bool _hasInfoForNode(Node node) {
237+
return _info[node] != null;
238+
}
239+
245240
void _printOn(StringBuffer sb) {
246241
sb.write('_info=$_info,');
247242
sb.write('_stack=$_stack,');
@@ -402,10 +397,8 @@ class ExpressionInfo<Variable extends Object, Type extends Object> {
402397
abstract class FlowAnalysis<Node extends Object, Statement extends Node,
403398
Expression extends Object, Variable extends Object, Type extends Object> {
404399
factory FlowAnalysis(TypeOperations<Variable, Type> typeOperations,
405-
AssignedVariables<Node, Variable> assignedVariables,
406-
{bool allowLocalBooleanVarsToPromote = false}) {
407-
return new _FlowAnalysisImpl(typeOperations, assignedVariables,
408-
allowLocalBooleanVarsToPromote: allowLocalBooleanVarsToPromote);
400+
AssignedVariables<Node, Variable> assignedVariables) {
401+
return new _FlowAnalysisImpl(typeOperations, assignedVariables);
409402
}
410403

411404
factory FlowAnalysis.legacy(TypeOperations<Variable, Type> typeOperations,
@@ -976,12 +969,10 @@ class FlowAnalysisDebug<Node extends Object, Statement extends Node,
976969
bool _exceptionOccurred = false;
977970

978971
factory FlowAnalysisDebug(TypeOperations<Variable, Type> typeOperations,
979-
AssignedVariables<Node, Variable> assignedVariables,
980-
{bool allowLocalBooleanVarsToPromote = false}) {
972+
AssignedVariables<Node, Variable> assignedVariables) {
981973
print('FlowAnalysisDebug()');
982-
return new FlowAnalysisDebug._(new _FlowAnalysisImpl(
983-
typeOperations, assignedVariables,
984-
allowLocalBooleanVarsToPromote: allowLocalBooleanVarsToPromote));
974+
return new FlowAnalysisDebug._(
975+
new _FlowAnalysisImpl(typeOperations, assignedVariables));
985976
}
986977

987978
factory FlowAnalysisDebug.legacy(
@@ -1881,79 +1872,6 @@ class FlowModel<Variable extends Object, Type extends Object> {
18811872
return _identicalOrNew(this, base, newReachable, newVariableInfo);
18821873
}
18831874

1884-
/// Updates the state to reflect a control path that is known to have
1885-
/// previously passed through some [other] state.
1886-
///
1887-
/// Approximately, this method forms the union of the definite assignments and
1888-
/// promotions in `this` state and the [other] state. More precisely:
1889-
///
1890-
/// The control flow path is considered reachable if both this state and the
1891-
/// other state are reachable. Variables are considered definitely assigned
1892-
/// if they were definitely assigned in either this state or the other state.
1893-
/// Variable type promotions are taken from this state, unless the promotion
1894-
/// in the other state is more specific, and the variable is "safe". A
1895-
/// variable is considered safe if there is no chance that it was assigned
1896-
/// more recently than the "other" state.
1897-
///
1898-
/// This is used after a `try/finally` statement to combine the promotions and
1899-
/// definite assignments that occurred in the `try` and `finally` blocks
1900-
/// (where `this` is the state from the `finally` block and `other` is the
1901-
/// state from the `try` block). Variables that are assigned in the `finally`
1902-
/// block are considered "unsafe" because the assignment might have cancelled
1903-
/// the effect of any promotion that occurred inside the `try` block.
1904-
FlowModel<Variable, Type> restrict(
1905-
TypeOperations<Variable, Type> typeOperations,
1906-
FlowModel<Variable, Type> other,
1907-
Set<Variable> unsafe) {
1908-
if (allowLocalBooleanVarsToPromoteByDefault) {
1909-
// TODO(paulberry): when we hardcode
1910-
// allowLocalBooleanVarsToPromoteByDefault to `true`, we should remove
1911-
// this method entirely.
1912-
throw new StateError('This method should not be called anymore');
1913-
}
1914-
Reachability newReachable =
1915-
Reachability.restrict(reachable, other.reachable);
1916-
1917-
Map<Variable?, VariableModel<Variable, Type>> newVariableInfo =
1918-
<Variable?, VariableModel<Variable, Type>>{};
1919-
bool variableInfoMatchesThis = true;
1920-
bool variableInfoMatchesOther = true;
1921-
for (MapEntry<Variable?, VariableModel<Variable, Type>> entry
1922-
in variableInfo.entries) {
1923-
Variable? variable = entry.key;
1924-
VariableModel<Variable, Type> thisModel = entry.value;
1925-
VariableModel<Variable, Type>? otherModel = other.variableInfo[variable];
1926-
if (otherModel == null) {
1927-
variableInfoMatchesThis = false;
1928-
continue;
1929-
}
1930-
VariableModel<Variable, Type> restricted = thisModel.restrict(
1931-
typeOperations, otherModel, unsafe.contains(variable));
1932-
newVariableInfo[variable] = restricted;
1933-
if (!identical(restricted, thisModel)) variableInfoMatchesThis = false;
1934-
if (!identical(restricted, otherModel)) variableInfoMatchesOther = false;
1935-
}
1936-
if (variableInfoMatchesOther) {
1937-
for (Variable? variable in other.variableInfo.keys) {
1938-
if (!variableInfo.containsKey(variable)) {
1939-
variableInfoMatchesOther = false;
1940-
break;
1941-
}
1942-
}
1943-
}
1944-
assert(variableInfoMatchesThis ==
1945-
_variableInfosEqual(newVariableInfo, variableInfo));
1946-
assert(variableInfoMatchesOther ==
1947-
_variableInfosEqual(newVariableInfo, other.variableInfo));
1948-
if (variableInfoMatchesThis) {
1949-
newVariableInfo = variableInfo;
1950-
} else if (variableInfoMatchesOther) {
1951-
newVariableInfo = other.variableInfo;
1952-
}
1953-
1954-
return _identicalOrNew(this, other, newReachable, newVariableInfo);
1955-
}
1956-
19571875
/// Updates the state to indicate that the control flow path is unreachable.
19581876
FlowModel<Variable, Type> setUnreachable() {
19591877
if (!reachable.locallyReachable) return this;
@@ -2799,59 +2717,6 @@ class VariableModel<Variable extends Object, Type extends Object> {
27992717
ssaNode: writeCaptured ? null : new SsaNode<Variable, Type>(null));
28002718
}
28012719

2802-
/// Returns an updated model reflect a control path that is known to have
2803-
/// previously passed through some [other] state. See [FlowModel.restrict]
2804-
/// for details.
2805-
VariableModel<Variable, Type> restrict(
2806-
TypeOperations<Variable, Type> typeOperations,
2807-
VariableModel<Variable, Type> otherModel,
2808-
bool unsafe) {
2809-
if (allowLocalBooleanVarsToPromoteByDefault) {
2810-
// TODO(paulberry): when we hardcode
2811-
// allowLocalBooleanVarsToPromoteByDefault to `true`, we should remove
2812-
// this method entirely.
2813-
throw new StateError('This method should not be called anymore');
2814-
}
2815-
List<Type>? thisPromotedTypes = promotedTypes;
2816-
List<Type>? otherPromotedTypes = otherModel.promotedTypes;
2817-
bool newAssigned = assigned || otherModel.assigned;
2818-
// The variable can only be unassigned in this state if it was also
2819-
// unassigned in the other state or if the other state didn't complete
2820-
// normally. For the latter case the resulting state is unreachable but to
2821-
// avoid creating a variable model that is both assigned and unassigned we
2822-
// take the intersection below.
2823-
//
2824-
// This situation can occur in try-finally like:
2825-
//
2826-
// method() {
2827-
// var local;
2828-
// try {
2829-
// local = 0;
2830-
// return; // assigned
2831-
// } finally {
2832-
// local; // unassigned
2833-
// }
2834-
// local; // unreachable state
2835-
// }
2836-
//
2837-
bool newUnassigned = unassigned && otherModel.unassigned;
2838-
bool newWriteCaptured = writeCaptured || otherModel.writeCaptured;
2839-
List<Type>? newPromotedTypes;
2840-
if (newWriteCaptured) {
2841-
// Write-captured variables can't be promoted
2842-
newPromotedTypes = null;
2843-
} else if (unsafe) {
2844-
// There was an assignment to the variable in the "this" path, so none of
2845-
// the promotions from the "other" path can be used.
2846-
newPromotedTypes = thisPromotedTypes;
2847-
} else {
2848-
newPromotedTypes = rebasePromotedTypes(
2849-
typeOperations, thisPromotedTypes, otherPromotedTypes);
2850-
}
2851-
return _identicalOrNew(this, otherModel, newPromotedTypes, tested,
2852-
newAssigned, newUnassigned, newWriteCaptured ? null : ssaNode);
2853-
}
2854-
28552720
/// Updates `this` with a new set of properties.
28562721
VariableModel<Variable, Type> setProperties(
28572722
Map<String, VariableModel<Variable, Type>> newProperties) =>
@@ -3526,18 +3391,7 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
35263391

35273392
final AssignedVariables<Node, Variable> _assignedVariables;
35283393

3529-
/// Set this boolean to `true` to temporarily enable the feature of allowing
3530-
/// local boolean variables to influence promotion, for this flow analysis
3531-
/// session (see https://github.com/dart-lang/language/issues/1274). Once the
3532-
/// top level const [allowLocalBooleanVarsToPromoteByDefault] is changed to
3533-
/// `true`, this field will always be `true`, so it can be safely removed.
3534-
final bool allowLocalBooleanVarsToPromote;
3535-
3536-
_FlowAnalysisImpl(this.typeOperations, this._assignedVariables,
3537-
{bool allowLocalBooleanVarsToPromote = false})
3538-
: allowLocalBooleanVarsToPromote =
3539-
allowLocalBooleanVarsToPromoteByDefault ||
3540-
allowLocalBooleanVarsToPromote;
3394+
_FlowAnalysisImpl(this.typeOperations, this._assignedVariables);
35413395

35423396
@override
35433397
bool get isReachable => _current.reachable.overallReachable;
@@ -4188,17 +4042,13 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
41884042

41894043
@override
41904044
void tryFinallyStatement_end(Node finallyBlock) {
4191-
AssignedVariablesNodeInfo<Variable> info =
4192-
_assignedVariables._getInfoForNode(finallyBlock);
4045+
// We used to need info for `finally` blocks but we don't anymore.
4046+
assert(!_assignedVariables._hasInfoForNode(finallyBlock),
4047+
'No assigned variables info should have been stored for $finallyBlock');
41934048
_TryFinallyContext<Variable, Type> context =
41944049
_stack.removeLast() as _TryFinallyContext<Variable, Type>;
4195-
if (allowLocalBooleanVarsToPromote) {
4196-
_current = context._afterBodyAndCatches
4197-
.attachFinally(typeOperations, context._beforeFinally, _current);
4198-
} else {
4199-
_current = _current.restrict(
4200-
typeOperations, context._afterBodyAndCatches, info._written);
4201-
}
4050+
_current = context._afterBodyAndCatches
4051+
.attachFinally(typeOperations, context._beforeFinally, _current);
42024052
}
42034053

42044054
@override
@@ -4220,13 +4070,11 @@ class _FlowAnalysisImpl<Node extends Object, Statement extends Node,
42204070
_storeExpressionReference(expression, variableReference);
42214071
VariableModel<Variable, Type> variableModel =
42224072
variableReference.getInfo(_current.variableInfo);
4223-
if (allowLocalBooleanVarsToPromote) {
4224-
ExpressionInfo<Variable, Type>? expressionInfo = variableModel
4225-
.ssaNode?.expressionInfo
4226-
?.rebaseForward(typeOperations, _current);
4227-
if (expressionInfo != null) {
4228-
_storeExpressionInfo(expression, expressionInfo);
4229-
}
4073+
ExpressionInfo<Variable, Type>? expressionInfo = variableModel
4074+
.ssaNode?.expressionInfo
4075+
?.rebaseForward(typeOperations, _current);
4076+
if (expressionInfo != null) {
4077+
_storeExpressionInfo(expression, expressionInfo);
42304078
}
42314079
return variableModel.promotedTypes?.last;
42324080
}

pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/tryFinally.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
/*member: tryFinally:declared={a, b}, assigned={a, b}*/
5+
/*member: tryFinally:declared={a, b, d}, assigned={a, b}*/
66
tryFinally(int a, int b) {
77
/*assigned={a}*/ try /*declared={c}, assigned={a}*/ {
88
a = 0;
99
var c;
10-
} finally /*declared={d}, assigned={b}*/ {
10+
} finally {
1111
b = 0;
1212
var d;
1313
}
1414
}
1515

16-
/*member: tryCatchFinally:declared={a, b, c}, assigned={a, b, c}*/
16+
/*member: tryCatchFinally:declared={a, b, c, f}, assigned={a, b, c}*/
1717
tryCatchFinally(int a, int b, int c) {
1818
// Note: try/catch/finally is desugared into try/catch nested inside
1919
// try/finally. The comment preceding the "try" refers to the outer
@@ -25,7 +25,7 @@ tryCatchFinally(int a, int b, int c) {
2525
} on String {
2626
b = 0;
2727
var e;
28-
} finally /*declared={f}, assigned={c}*/ {
28+
} finally {
2929
c = 0;
3030
var f;
3131
}

pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -423,8 +423,6 @@ class Harness extends TypeOperations<Var, Type> {
423423
'num* - Object': Type('Never'),
424424
};
425425

426-
final bool allowLocalBooleanVarsToPromote;
427-
428426
final bool legacy;
429427

430428
final Map<String, bool> _subtypes = Map.of(_coreSubtypes);
@@ -435,7 +433,7 @@ class Harness extends TypeOperations<Var, Type> {
435433

436434
Map<String, Map<String, String>> _promotionExceptions = {};
437435

438-
Harness({this.allowLocalBooleanVarsToPromote = false, this.legacy = false});
436+
Harness({this.legacy = false});
439437

440438
@override
441439
Type get topType => Type('Object?');
@@ -512,8 +510,7 @@ class Harness extends TypeOperations<Var, Type> {
512510
? FlowAnalysis<Node, Statement, Expression, Var, Type>.legacy(
513511
this, assignedVariables)
514512
: FlowAnalysis<Node, Statement, Expression, Var, Type>(
515-
this, assignedVariables,
516-
allowLocalBooleanVarsToPromote: allowLocalBooleanVarsToPromote);
513+
this, assignedVariables);
517514
statements._visit(this, flow);
518515
flow.finish();
519516
}
@@ -1658,9 +1655,7 @@ class _TryFinally extends Statement {
16581655
assignedVariables.beginNode();
16591656
body._preVisit(assignedVariables);
16601657
assignedVariables.endNode(_bodyNode);
1661-
assignedVariables.beginNode();
16621658
finally_._preVisit(assignedVariables);
1663-
assignedVariables.endNode(_finallyNode);
16641659
}
16651660

16661661
@override

0 commit comments

Comments
 (0)