diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart index 1691a69ba4b..d277196a64e 100644 --- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart +++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart @@ -1900,9 +1900,6 @@ class FlowModel { /// [_FlowAnalysisImpl._promotionKeyStore]. final Map /*!*/ > variableInfo; - /// The empty map, used to [join] variables. - final Map> _emptyVariableMap = {}; - /// Creates a state object with the given [reachable] status. All variables /// are assumed to be unpromoted and already assigned, so joining another /// state with this one will have no effect on it. @@ -2493,7 +2490,6 @@ class FlowModel { TypeOperations typeOperations, FlowModel? first, FlowModel? second, - Map> emptyVariableMap, ) { if (first == null) return second!; if (second == null) return first; @@ -2511,10 +2507,7 @@ class FlowModel { Reachability newReachable = Reachability.join(first.reachable, second.reachable); Map> newVariableInfo = FlowModel.joinVariableInfo( - typeOperations, - first.variableInfo, - second.variableInfo, - emptyVariableMap); + typeOperations, first.variableInfo, second.variableInfo); return FlowModel._identicalOrNew( first, second, newReachable, newVariableInfo); @@ -2526,13 +2519,13 @@ class FlowModel { TypeOperations typeOperations, Map> first, Map> second, - Map> emptyMap, ) { if (identical(first, second)) return first; if (first.isEmpty || second.isEmpty) { - return emptyMap; + return const {}; } + // TODO(jensj): How often is this empty? Map> result = >{}; bool alwaysFirst = true; bool alwaysSecond = true; @@ -2552,7 +2545,7 @@ class FlowModel { if (alwaysFirst) return first; if (alwaysSecond && result.length == second.length) return second; - if (result.isEmpty) return emptyMap; + if (result.isEmpty) return const {}; return result; } @@ -2562,7 +2555,6 @@ class FlowModel { TypeOperations typeOperations, FlowModel? first, FlowModel? second, - Map> emptyVariableMap, ) { if (first == null) return second!.unsplit(); if (second == null) return first.unsplit(); @@ -2580,10 +2572,7 @@ class FlowModel { Reachability newReachable = Reachability.join(first.reachable, second.reachable).unsplit(); Map> newVariableInfo = FlowModel.joinVariableInfo( - typeOperations, - first.variableInfo, - second.variableInfo, - emptyVariableMap); + typeOperations, first.variableInfo, second.variableInfo); return FlowModel._identicalOrNew( first, second, newReachable, newVariableInfo); @@ -5153,7 +5142,7 @@ class _FlowAnalysisImpl _join(FlowModel? first, FlowModel? second) => - FlowModel.join(operations, first, second, _current._emptyVariableMap); + FlowModel.join(operations, first, second); /// Creates a promotion key representing a temporary variable that doesn't /// correspond to any variable in the user's source code. This is used by @@ -5174,7 +5163,7 @@ class _FlowAnalysisImpl _merge(FlowModel first, FlowModel? second) => - FlowModel.merge(operations, first, second, _current._emptyVariableMap); + FlowModel.merge(operations, first, second); /// Computes an updated flow model representing the result of a null check /// performed by a pattern. The returned flow model represents what is known diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart index 0ea0ece5f64..413722c56c8 100644 --- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart +++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart @@ -4613,7 +4613,6 @@ main() { var intType = Type('int'); var intQType = Type('int?'); var stringType = Type('String'); - const emptyMap = const >{}; setUp(() { x = h.promotionKeyStore.keyForVariable(Var('x')..type = Type('Object?')); @@ -4641,7 +4640,7 @@ main() { x: model(null), y: model([intType]) }; - expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2, emptyMap), { + expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2), { x: _matchVariableModel(chain: null, ofInterest: ['int']), y: _matchVariableModel(chain: null, ofInterest: ['int']) }); @@ -4653,8 +4652,7 @@ main() { x: model([intType]), y: model([stringType]) }; - expect(FlowModel.joinVariableInfo(h.typeOperations, p, p, emptyMap), - same(p)); + expect(FlowModel.joinVariableInfo(h.typeOperations, p, p), same(p)); }); test('one input empty', () { @@ -4663,10 +4661,11 @@ main() { y: model([stringType]) }; var p2 = >{}; - expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2, emptyMap), - same(emptyMap)); - expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1, emptyMap), - same(emptyMap)); + const expected = const >{}; + expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2), + same(expected)); + expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1), + same(expected)); }); test('promoted with unpromoted', () { @@ -4677,10 +4676,8 @@ main() { var expected = { x: _matchVariableModel(chain: null, ofInterest: ['int']) }; - expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2, emptyMap), - expected); - expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1, emptyMap), - expected); + expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2), expected); + expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1), expected); }); test('related type chains', () { @@ -4693,10 +4690,8 @@ main() { var expected = { x: _matchVariableModel(chain: ['int?'], ofInterest: ['int?', 'int']) }; - expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2, emptyMap), - expected); - expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1, emptyMap), - expected); + expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2), expected); + expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1), expected); }); test('unrelated type chains', () { @@ -4709,10 +4704,8 @@ main() { var expected = { x: _matchVariableModel(chain: null, ofInterest: ['String', 'int']) }; - expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2, emptyMap), - expected); - expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1, emptyMap), - expected); + expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2), expected); + expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1), expected); }); test('sub-map', () { @@ -4722,10 +4715,8 @@ main() { y: model([stringType]) }; var p2 = {x: xModel}; - expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2, emptyMap), - same(p2)); - expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1, emptyMap), - same(p2)); + expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2), same(p2)); + expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1), same(p2)); }); test('sub-map with matched subtype', () { @@ -4739,10 +4730,8 @@ main() { var expected = { x: _matchVariableModel(chain: ['int?'], ofInterest: ['int?', 'int']) }; - expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2, emptyMap), - expected); - expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1, emptyMap), - expected); + expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2), expected); + expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1), expected); }); test('sub-map with mismatched subtype', () { @@ -4756,10 +4745,8 @@ main() { var expected = { x: _matchVariableModel(chain: ['int?'], ofInterest: ['int?', 'int']) }; - expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2, emptyMap), - expected); - expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1, emptyMap), - expected); + expect(FlowModel.joinVariableInfo(h.typeOperations, p1, p2), expected); + expect(FlowModel.joinVariableInfo(h.typeOperations, p2, p1), expected); }); test('assigned', () { @@ -4767,8 +4754,7 @@ main() { var assigned = model(null, assigned: true); var p1 = {x: assigned, y: assigned, z: unassigned, w: unassigned}; var p2 = {x: assigned, y: unassigned, z: assigned, w: unassigned}; - var joined = - FlowModel.joinVariableInfo(h.typeOperations, p1, p2, emptyMap); + var joined = FlowModel.joinVariableInfo(h.typeOperations, p1, p2); expect(joined, { x: same(assigned), y: _matchVariableModel( @@ -4794,8 +4780,7 @@ main() { z: writeCapturedModel, w: intQModel }; - var joined = - FlowModel.joinVariableInfo(h.typeOperations, p1, p2, emptyMap); + var joined = FlowModel.joinVariableInfo(h.typeOperations, p1, p2); expect(joined, { x: same(writeCapturedModel), y: same(writeCapturedModel), @@ -4827,7 +4812,7 @@ main() { test('first is null', () { var s1 = FlowModel.withInfo(Reachability.initial.split(), emptyMap); - var result = FlowModel.merge(h.typeOperations, null, s1, emptyMap); + var result = FlowModel.merge(h.typeOperations, null, s1); expect(result.reachable, same(Reachability.initial)); }); @@ -4835,7 +4820,7 @@ main() { var splitPoint = Reachability.initial.split(); var afterSplit = splitPoint.split(); var s1 = FlowModel.withInfo(afterSplit, emptyMap); - var result = FlowModel.merge(h.typeOperations, s1, null, emptyMap); + var result = FlowModel.merge(h.typeOperations, s1, null); expect(result.reachable, same(splitPoint)); }); @@ -4848,7 +4833,7 @@ main() { var s2 = FlowModel.withInfo(afterSplit, { x: varModel([stringType]) }); - var result = FlowModel.merge(h.typeOperations, s1, s2, emptyMap); + var result = FlowModel.merge(h.typeOperations, s1, s2); expect(result.reachable, same(splitPoint)); expect(result.variableInfo[x]!.promotedTypes, isNull); }); @@ -4862,7 +4847,7 @@ main() { var s2 = FlowModel.withInfo(afterSplit, { x: varModel([stringType]) }); - var result = FlowModel.merge(h.typeOperations, s1, s2, emptyMap); + var result = FlowModel.merge(h.typeOperations, s1, s2); expect(result.reachable, same(splitPoint)); expect(result.variableInfo, same(s2.variableInfo)); }); @@ -4876,7 +4861,7 @@ main() { var s2 = FlowModel.withInfo(afterSplit.setUnreachable(), { x: varModel([stringType]) }); - var result = FlowModel.merge(h.typeOperations, s1, s2, emptyMap); + var result = FlowModel.merge(h.typeOperations, s1, s2); expect(result.reachable, same(splitPoint)); expect(result.variableInfo, same(s1.variableInfo)); }); @@ -4890,7 +4875,7 @@ main() { var s2 = FlowModel.withInfo(afterSplit.setUnreachable(), { x: varModel([stringType]) }); - var result = FlowModel.merge(h.typeOperations, s1, s2, emptyMap); + var result = FlowModel.merge(h.typeOperations, s1, s2); expect(result.reachable.locallyReachable, false); expect(result.reachable.parent, same(splitPoint.parent)); expect(result.variableInfo[x]!.promotedTypes, isNull);