[dart2js] Migrate locals_handler type_graph_node and type_system to nnbd
Change-Id: I77f66764943bcdf204744da6bcc1932381895c5d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/249964
Commit-Queue: Nate Biggs <natebiggs@google.com>
Reviewed-by: Joshua Litt <joshualitt@google.com>
diff --git a/pkg/compiler/lib/src/inferrer/engine.dart b/pkg/compiler/lib/src/inferrer/engine.dart
index 6cae1c6..f088516 100644
--- a/pkg/compiler/lib/src/inferrer/engine.dart
+++ b/pkg/compiler/lib/src/inferrer/engine.dart
@@ -65,6 +65,7 @@
@override
final JsClosedWorld closedWorld;
+ @override
final TypeSystem types;
final Map<ir.TreeNode, TypeInformation> concreteTypes = {};
final GlobalLocalsMap globalLocalsMap;
@@ -174,6 +175,7 @@
/// Returns the type for [nativeBehavior]. See documentation on
/// [NativeBehavior].
+ @override
TypeInformation typeOfNativeBehavior(NativeBehavior nativeBehavior) {
if (nativeBehavior == null) return types.dynamicType;
List<Object> typesReturned = nativeBehavior.typesReturned;
@@ -214,6 +216,7 @@
return returnType;
}
+ @override
void updateSelectorInMember(MemberEntity owner, CallType callType,
ir.Node node, Selector selector, AbstractValue mask) {
KernelGlobalTypeInferenceElementData data = dataOfMember(owner);
@@ -755,6 +758,7 @@
/// Update the inputs to parameters in the graph. [remove] tells whether
/// inputs must be added or removed. If [init] is false, parameters are
/// added to the work queue.
+ @override
void updateParameterInputs(TypeInformation caller, MemberEntity callee,
ArgumentsTypes arguments, Selector selector,
{bool remove, bool addToQueue = true}) {
@@ -846,6 +850,7 @@
///
/// Invariant: After graph construction, no [PlaceholderTypeInformation] nodes
/// should be present and a default type for each parameter should exist.
+ @override
TypeInformation getDefaultTypeOfParameter(Local parameter) {
return _defaultTypeOfParameter.putIfAbsent(parameter, () {
return PlaceholderTypeInformation(
@@ -1093,6 +1098,7 @@
}
/// Returns the type of [element] when being called with [selector].
+ @override
TypeInformation typeOfMemberWithSelector(
MemberEntity element, Selector selector) {
if (element.name == Identifiers.noSuchMethod_ &&
@@ -1176,6 +1182,7 @@
///
/// One category of elements that do not apply is runtime helpers that the
/// backend calls, but the optimizations don't see those calls.
+ @override
bool canFieldBeUsedForGlobalOptimizations(FieldEntity element) {
if (closedWorld.backendUsage.isFieldUsedByBackend(element)) {
return false;
@@ -1191,12 +1198,14 @@
///
/// One category of elements that do not apply is runtime helpers that the
/// backend calls, but the optimizations don't see those calls.
+ @override
bool canFunctionParametersBeUsedForGlobalOptimizations(
FunctionEntity function) {
return !closedWorld.backendUsage.isFunctionUsedByBackend(function);
}
/// Returns `true` if inference of parameter types is disabled for [member].
+ @override
bool assumeDynamic(MemberEntity member) {
return closedWorld.annotationsData.hasAssumeDynamic(member);
}
diff --git a/pkg/compiler/lib/src/inferrer/engine_interfaces.dart b/pkg/compiler/lib/src/inferrer/engine_interfaces.dart
index 80c7d3e..ce45629 100644
--- a/pkg/compiler/lib/src/inferrer/engine_interfaces.dart
+++ b/pkg/compiler/lib/src/inferrer/engine_interfaces.dart
@@ -2,22 +2,42 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:kernel/ast.dart' as ir;
+
import '../common/elements.dart';
import '../elements/entities.dart';
import '../js_backend/inferred_data.dart';
import '../js_backend/no_such_method_registry_interfaces.dart';
+import '../native/behavior.dart';
import '../universe/selector.dart';
import '../world_interfaces.dart';
import 'abstract_value_domain.dart';
+import 'locals_handler.dart';
+import 'type_graph_nodes.dart';
+import 'type_system.dart';
abstract class InferrerEngine {
AbstractValueDomain get abstractValueDomain;
+ TypeSystem get types;
JClosedWorld get closedWorld;
CommonElements get commonElements;
InferredDataBuilder get inferredDataBuilder;
FunctionEntity get mainElement;
NoSuchMethodData get noSuchMethodData;
+ TypeInformation typeOfNativeBehavior(NativeBehavior nativeBehavior);
+ bool canFieldBeUsedForGlobalOptimizations(FieldEntity element);
+ bool assumeDynamic(MemberEntity member);
+ TypeInformation getDefaultTypeOfParameter(Local parameter);
+ bool canFunctionParametersBeUsedForGlobalOptimizations(
+ FunctionEntity function);
+ TypeInformation typeOfMemberWithSelector(
+ MemberEntity element, Selector? selector);
+ void updateSelectorInMember(MemberEntity owner, CallType callType,
+ ir.Node? node, Selector? selector, AbstractValue? mask);
+ void updateParameterInputs(TypeInformation caller, MemberEntity callee,
+ ArgumentsTypes? arguments, Selector? selector,
+ {required bool remove, bool addToQueue = true});
bool returnsListElementType(Selector selector, AbstractValue mask);
bool returnsMapValueType(Selector selector, AbstractValue mask);
}
diff --git a/pkg/compiler/lib/src/inferrer/locals_handler.dart b/pkg/compiler/lib/src/inferrer/locals_handler.dart
index 69f77f5..a9c0265 100644
--- a/pkg/compiler/lib/src/inferrer/locals_handler.dart
+++ b/pkg/compiler/lib/src/inferrer/locals_handler.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart = 2.10
-
library locals_handler;
import 'dart:collection' show IterableMixin;
@@ -11,7 +9,7 @@
import '../elements/entities.dart';
import '../ir/util.dart';
import '../util/util.dart';
-import 'engine.dart';
+import 'engine_interfaces.dart';
import 'type_graph_nodes.dart';
/// A variable scope holds types for variables. It has a link to a
@@ -25,15 +23,15 @@
/// This is used for computing common parents efficiently.
final int _level;
- Map<Local, TypeInformation> variables;
+ Map<Local, TypeInformation>? variables;
/// The parent of this scope. Null for the root scope.
- final VariableScope parent;
+ final VariableScope? parent;
/// The [ir.Node] that created this scope.
- final ir.Node tryBlock;
+ final ir.Node? tryBlock;
- final VariableScope copyOf;
+ final VariableScope? copyOf;
VariableScope({this.parent})
: this.variables = null,
@@ -52,13 +50,13 @@
VariableScope.deepCopyOf(VariableScope other)
: variables = other.variables == null
? null
- : Map<Local, TypeInformation>.from(other.variables),
+ : Map<Local, TypeInformation>.from(other.variables!),
tryBlock = other.tryBlock,
copyOf = other.copyOf ?? other,
_level = other._level,
parent = other.parent == null
? null
- : VariableScope.deepCopyOf(other.parent);
+ : VariableScope.deepCopyOf(other.parent!);
/// `true` if this scope is for a try block.
bool get isTry => tryBlock != null;
@@ -70,50 +68,47 @@
VariableScope get identity => copyOf ?? this;
/// Returns the common parent between this and [other] based on [identity].
- VariableScope commonParent(VariableScope other) {
+ VariableScope? commonParent(VariableScope other) {
if (identity == other.identity) {
return identity;
} else if (_level > other._level) {
- return parent.commonParent(other);
+ return parent!.commonParent(other);
} else if (_level < other._level) {
- return commonParent(other.parent);
+ return commonParent(other.parent!);
} else if (_level > 0) {
- return parent.commonParent(other.parent);
+ return parent!.commonParent(other.parent!);
} else {
return null;
}
}
- TypeInformation operator [](Local variable) {
- TypeInformation result;
- if (variables == null || (result = variables[variable]) == null) {
- return parent == null ? null : parent[variable];
+ TypeInformation? operator [](Local variable) {
+ TypeInformation? result;
+ if (variables == null || (result = variables![variable]) == null) {
+ return parent == null ? null : parent![variable];
}
return result;
}
void operator []=(Local variable, TypeInformation mask) {
- assert(mask != null);
- if (variables == null) {
- variables = Map<Local, TypeInformation>();
- }
- variables[variable] = mask;
+ assert((mask as dynamic) != null); // TODO(48820): Remove when sound.
+ (variables ??= <Local, TypeInformation>{})[variable] = mask;
}
/// Calls [f] for all variables in this and parent scopes until and including
/// [scope]. [f] is called at most once for each variable.
void forEachLocalUntilScope(
- VariableScope scope, void f(Local variable, TypeInformation type)) {
+ VariableScope? scope, void f(Local variable, TypeInformation type)) {
_forEachLocalUntilScope(scope, f, Setlet<Local>(), this);
}
void _forEachLocalUntilScope(
- VariableScope scope,
+ VariableScope? scope,
void f(Local variable, TypeInformation type),
Setlet<Local> seenLocals,
VariableScope origin) {
if (variables != null) {
- variables.forEach((variable, type) {
+ variables!.forEach((variable, type) {
if (seenLocals.contains(variable)) return;
seenLocals.add(variable);
f(variable, type);
@@ -123,7 +118,7 @@
return;
}
if (parent != null) {
- parent._forEachLocalUntilScope(scope, f, seenLocals, origin);
+ parent!._forEachLocalUntilScope(scope, f, seenLocals, origin);
} else {
assert(
scope == null,
@@ -139,7 +134,7 @@
bool updates(Local variable) {
if (variables == null) return false;
- return variables.containsKey(variable);
+ return variables!.containsKey(variable);
}
String toStructuredText(String indent) {
@@ -155,18 +150,18 @@
sb.write('\n${indent} copyOf:VariableScope(${copyOf.hashCode})');
}
if (tryBlock != null) {
- sb.write('\n${indent} tryBlock: ${nodeToDebugString(tryBlock)}');
+ sb.write('\n${indent} tryBlock: ${nodeToDebugString(tryBlock!)}');
}
if (variables != null) {
sb.write('\n${indent} variables:');
- variables.forEach((Local local, TypeInformation type) {
+ variables!.forEach((Local local, TypeInformation type) {
sb.write('\n${indent} $local: ');
sb.write(type.toStructuredText('${indent} '));
});
}
if (parent != null) {
sb.write('\n${indent} parent:');
- parent._toStructuredText(sb, '${indent} ');
+ parent!._toStructuredText(sb, '${indent} ');
}
sb.write(']');
}
@@ -180,7 +175,7 @@
/// Tracks initializers via initializations and assignments.
class FieldInitializationScope {
- Map<FieldEntity, TypeInformation> fields;
+ Map<FieldEntity, TypeInformation>? fields;
bool isThisExposed;
/// `true` when control flow prevents accumulating definite assignments,
@@ -195,7 +190,7 @@
: isThisExposed = other.isThisExposed,
isIndefinite = other.isIndefinite;
- factory FieldInitializationScope.from(FieldInitializationScope other) {
+ static FieldInitializationScope? from(FieldInitializationScope? other) {
if (other == null) return null;
return FieldInitializationScope.internalFrom(other);
}
@@ -203,12 +198,11 @@
void updateField(FieldEntity field, TypeInformation type) {
if (isThisExposed) return;
if (isIndefinite) return;
- fields ??= Map<FieldEntity, TypeInformation>();
- fields[field] = type;
+ (fields ??= <FieldEntity, TypeInformation>{})[field] = type;
}
- TypeInformation readField(FieldEntity field) {
- return fields == null ? null : fields[field];
+ TypeInformation? readField(FieldEntity field) {
+ return fields == null ? null : fields![field];
}
void forEach(void f(FieldEntity element, TypeInformation type)) {
@@ -219,7 +213,7 @@
/// flow through either [thenScope] or [elseScope].
FieldInitializationScope mergeDiamondFlow(InferrerEngine inferrer,
FieldInitializationScope thenScope, FieldInitializationScope elseScope) {
- assert(elseScope != null);
+ assert((elseScope as dynamic) != null); // TODO(48820): Remove when sound.
// Quick bailout check. If [isThisExposed] or [isIndefinite] is true, we
// know the code following won't do anything.
@@ -230,7 +224,7 @@
elseScope.fields == null ? this : elseScope;
thenScope.forEach((FieldEntity field, TypeInformation type) {
- TypeInformation otherType = otherScope.readField(field);
+ final otherType = otherScope.readField(field);
if (otherType == null) return;
updateField(field, inferrer.types.allocateDiamondPhi(type, otherType));
});
@@ -246,10 +240,10 @@
final List<TypeInformation> positional;
final Map<String, TypeInformation> named;
- ArgumentsTypes(this.positional, Map<String, TypeInformation> named)
+ ArgumentsTypes(this.positional, Map<String, TypeInformation>? named)
: this.named = (named == null || named.isEmpty) ? const {} : named {
- assert(this.positional.every((TypeInformation type) => type != null));
- assert(this.named.values.every((TypeInformation type) => type != null));
+ assert(this.positional.every((TypeInformation? type) => type != null));
+ assert(this.named.values.every((TypeInformation? type) => type != null));
}
ArgumentsTypes.empty()
@@ -266,7 +260,8 @@
String toString() => "{ positional = $positional, named = $named }";
@override
- bool operator ==(other) {
+ bool operator ==(Object? other) {
+ if (other is! ArgumentsTypes) return false;
if (positional.length != other.positional.length) return false;
if (named.length != other.named.length) return false;
for (int i = 0; i < positional.length; i++) {
@@ -296,7 +291,7 @@
}
@override
- bool contains(Object type) {
+ bool contains(Object? type) {
return positional.contains(type) || named.containsValue(type);
}
}
@@ -341,26 +336,25 @@
LocalsHandler.deepCopyOf(LocalsHandler other)
: _locals = VariableScope.deepCopyOf(other._locals);
- TypeInformation use(Local local) {
+ TypeInformation? use(Local local) {
return _locals[local];
}
void update(InferrerEngine inferrer, Local local, TypeInformation type,
- LocalsHandler tryBlock) {
+ LocalsHandler? tryBlock) {
if (tryBlock != null) {
// We don't know if an assignment in a try block
// will be executed, so all assignments in that block are
// potential types after we have left it. We update the parent
// of the try block so that, at exit of the try block, we get
// the right phi for it.
- TypeInformation existing = tryBlock._locals.parent[local];
+ final existing = tryBlock._locals.parent![local];
if (existing != null) {
- TypeInformation phiType = inferrer.types.allocatePhi(
+ final phiType = inferrer.types.allocatePhi(
tryBlock._locals.tryBlock, local, existing,
isTry: tryBlock._locals.isTry);
- TypeInformation inputType =
- inferrer.types.addPhiInput(local, phiType, type);
- tryBlock._locals.parent[local] = inputType;
+ final inputType = inferrer.types.addPhiInput(local, phiType, type);
+ tryBlock._locals.parent![local] = inputType;
}
// Update the current handler unconditionally with the new
// type.
@@ -378,7 +372,7 @@
/// from both are merged with a phi type.
LocalsHandler mergeFlow(InferrerEngine inferrer, LocalsHandler other,
{bool inPlace = false}) {
- VariableScope common = _locals.commonParent(other._locals);
+ final common = _locals.commonParent(other._locals);
assert(
common != null,
"No common parent for\n"
@@ -387,11 +381,11 @@
assert(
common == _locals || _locals.variables == null,
"Non-empty common parent for\n"
- "1:${common.toStructuredText(' ')}\n"
+ "1:${common?.toStructuredText(' ')}\n"
"2:${_locals.toStructuredText(' ')}");
other._locals.forEachLocalUntilScope(common,
(Local local, TypeInformation type) {
- TypeInformation myType = _locals[local];
+ final myType = _locals[local];
if (myType == null) return; // Variable is only defined in [other].
if (type == myType) return;
_locals[local] =
@@ -404,13 +398,13 @@
/// flow through either [thenBranch] or [elseBranch].
LocalsHandler mergeDiamondFlow(InferrerEngine inferrer,
LocalsHandler thenBranch, LocalsHandler elseBranch) {
- assert(elseBranch != null);
+ assert((elseBranch as dynamic) != null); // TODO(48820): Remove when sound.
void mergeLocal(Local local) {
- TypeInformation myType = _locals[local];
+ final myType = _locals[local];
if (myType == null) return;
- TypeInformation elseType = elseBranch._locals[local];
- TypeInformation thenType = thenBranch._locals[local];
+ final elseType = elseBranch._locals[local]!;
+ final thenType = thenBranch._locals[local]!;
if (thenType == elseType) {
_locals[local] = thenType;
} else {
@@ -418,7 +412,7 @@
}
}
- VariableScope common = _locals.commonParent(thenBranch._locals);
+ final common = _locals.commonParent(thenBranch._locals);
assert(
common != null,
"No common parent for\n"
@@ -427,12 +421,12 @@
assert(
_locals.commonParent(elseBranch._locals) == common,
"Diff common parent for\n"
- "1:${common.toStructuredText(' ')}\n2:"
+ "1:${common?.toStructuredText(' ')}\n2:"
"${_locals.commonParent(elseBranch._locals)?.toStructuredText(' ')}");
assert(
common == _locals || _locals.variables == null,
"Non-empty common parent for\n"
- "common:${common.toStructuredText(' ')}\n"
+ "common:${common?.toStructuredText(' ')}\n"
"1:${_locals.toStructuredText(' ')}\n"
"2:${thenBranch._locals.toStructuredText(' ')}");
thenBranch._locals.forEachLocalUntilScope(common, (Local local, _) {
@@ -477,7 +471,7 @@
LocalsHandler mergeAfterBreaks(
InferrerEngine inferrer, Iterable<LocalsHandler> handlers,
{bool keepOwnLocals = true}) {
- ir.Node tryBlock = _locals.tryBlock;
+ final tryBlock = _locals.tryBlock;
// Use a separate locals handler to perform the merge in, so that Phi
// creation does not invalidate previous type knowledge while we might
// still look it up.
@@ -487,7 +481,7 @@
Set<Local> seenLocals = Setlet<Local>();
// Merge all other handlers.
for (LocalsHandler handler in handlers) {
- VariableScope common = _locals.commonParent(handler._locals);
+ final common = _locals.commonParent(handler._locals);
assert(
common != null,
"No common parent for\n"
@@ -496,11 +490,11 @@
assert(
common == _locals || _locals.variables == null,
"Non-empty common parent for\n"
- "common:${common.toStructuredText(' ')}\n"
+ "common:${common?.toStructuredText(' ')}\n"
"1:${_locals.toStructuredText(' ')}\n"
"2:${handler._locals.toStructuredText(' ')}");
handler._locals.forEachLocalUntilScope(common, (local, otherType) {
- TypeInformation myType = merged[local];
+ final myType = merged[local];
if (myType == null) return;
TypeInformation newType;
if (!seenLocals.contains(local)) {
@@ -509,7 +503,8 @@
isTry: merged.isTry);
seenLocals.add(local);
} else {
- newType = inferrer.types.addPhiInput(local, myType, otherType);
+ newType = inferrer.types.addPhiInput(
+ local, myType as PhiElementTypeInformation, otherType);
}
if (newType != myType) {
merged[local] = newType;
@@ -520,10 +515,10 @@
// [merged] to update the Phi nodes with original values.
if (keepOwnLocals) {
for (Local variable in seenLocals) {
- TypeInformation originalType = _locals[variable];
+ final originalType = _locals[variable];
if (originalType != null) {
- merged[variable] = inferrer.types
- .addPhiInput(variable, merged[variable], originalType);
+ merged[variable] = inferrer.types.addPhiInput(variable,
+ merged[variable] as PhiElementTypeInformation, originalType);
}
}
}
@@ -531,7 +526,8 @@
// actual locals handler.
merged.forEachLocalUntilScope(merged,
(Local variable, TypeInformation type) {
- _locals[variable] = inferrer.types.simplifyPhi(tryBlock, variable, type);
+ _locals[variable] = inferrer.types
+ .simplifyPhi(tryBlock, variable, type as PhiElementTypeInformation);
});
return this;
}
@@ -541,7 +537,7 @@
bool mergeAll(InferrerEngine inferrer, Iterable<LocalsHandler> handlers) {
bool changed = false;
handlers.forEach((LocalsHandler other) {
- VariableScope common = _locals.commonParent(other._locals);
+ final common = _locals.commonParent(other._locals);
assert(
common != null,
"No common parent for\n"
@@ -550,14 +546,14 @@
assert(
common == _locals || _locals.variables == null,
"Non-empty common parent for\n"
- "common:${common.toStructuredText(' ')}\n"
+ "common:${common?.toStructuredText(' ')}\n"
"1:${_locals.toStructuredText(' ')}\n"
"2:${other._locals.toStructuredText(' ')}");
other._locals.forEachLocalUntilScope(common, (local, otherType) {
- TypeInformation myType = _locals[local];
+ final myType = _locals[local];
if (myType == null) return;
- TypeInformation newType =
- inferrer.types.addPhiInput(local, myType, otherType);
+ TypeInformation newType = inferrer.types
+ .addPhiInput(local, myType as PhiElementTypeInformation, otherType);
if (newType != myType) {
changed = true;
_locals[local] = newType;
@@ -579,8 +575,8 @@
void endLoop(InferrerEngine inferrer, ir.Node loop) {
_locals.forEachLocal((Local variable, TypeInformation type) {
- TypeInformation newType =
- inferrer.types.simplifyPhi(loop, variable, type);
+ final newType = inferrer.types
+ .simplifyPhi(loop, variable, type as PhiElementTypeInformation);
if (newType != type) {
_locals[variable] = newType;
}
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 8f28c04..6a698dc 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart = 2.10
-
library compiler.src.inferrer.type_graph_nodes;
import 'dart:collection' show IterableBase;
@@ -16,11 +14,11 @@
import '../elements/types.dart';
import '../universe/selector.dart' show Selector;
import '../util/util.dart' show Setlet;
-import '../world.dart' show JClosedWorld;
+import '../world_interfaces.dart' show JClosedWorld;
import 'abstract_value_domain.dart';
import 'debug.dart' as debug;
import 'locals_handler.dart' show ArgumentsTypes;
-import 'engine.dart';
+import 'engine_interfaces.dart';
import 'type_system.dart';
/// Common class for all nodes in the graph. The current nodes are:
@@ -46,10 +44,10 @@
AbstractValue type;
/// The graph node of the member this [TypeInformation] node belongs to.
- final MemberTypeInformation context;
+ final MemberTypeInformation? context;
/// The element this [TypeInformation] node belongs to.
- MemberEntity get contextMember => context?.member;
+ MemberEntity? get contextMember => context?.member;
ParameterInputs get inputs => _inputs;
@@ -189,7 +187,7 @@
/// The [Element] where this [TypeInformation] was created. May be `null`
/// for some [TypeInformation] nodes, where we do not need to store
/// the information.
- MemberEntity get owner => (context != null) ? context.member : null;
+ MemberEntity? get owner => (context != null) ? context?.member : null;
/// Returns whether the type cannot change after it has been
/// inferred.
@@ -341,10 +339,11 @@
@override
Iterator<TypeInformation> get iterator => _inputs.keys.iterator;
@override
- Iterable<TypeInformation> where(Function f) => _inputs.keys.where(f);
+ Iterable<TypeInformation> where(bool Function(TypeInformation) f) =>
+ _inputs.keys.where(f);
@override
- bool contains(Object info) => _inputs.containsKey(info);
+ bool contains(Object? info) => _inputs.containsKey(info);
@override
String toString() => _inputs.keys.toList().toString();
@@ -380,10 +379,10 @@
bool disableInferenceForClosures = true;
ElementTypeInformation._internal(
- AbstractValueDomain abstractValueDomain, MemberTypeInformation context)
+ AbstractValueDomain abstractValueDomain, MemberTypeInformation? context)
: super(abstractValueDomain.emptyType, context);
ElementTypeInformation._withInputs(AbstractValueDomain abstractValueDomain,
- MemberTypeInformation context, ParameterInputs inputs)
+ MemberTypeInformation? context, ParameterInputs inputs)
: super.withInputs(abstractValueDomain.emptyType, context, inputs);
String getInferredSignature(TypeSystem types);
@@ -410,7 +409,7 @@
// Strict `bool` value is computed in cleanup(). Also used as a flag to see if
// cleanup has been called.
- bool _isCalledOnce = null;
+ bool? _isCalledOnce = null;
/// Whether this member is invoked via indirect dynamic calls. In that case
/// the exact number of call sites cannot be computed precisely.
@@ -423,7 +422,7 @@
///
/// The global information is summarized in [cleanup], after which [_callers]
/// is set to `null`.
- Map<MemberEntity, Setlet<ir.Node /*?*/ >> _callers;
+ Map<MemberEntity, Setlet<ir.Node?>>? _callers;
MemberTypeInformation._internal(
AbstractValueDomain abstractValueDomain, this._member)
@@ -434,22 +433,24 @@
@override
String get debugName => '$member';
- void addCall(MemberEntity caller, ir.Node /*?*/ node) {
- _callers ??= <MemberEntity, Setlet<ir.Node /*?*/ >>{};
- _callers.putIfAbsent(caller, () => Setlet()).add(node);
+ void addCall(MemberEntity caller, ir.Node? node) {
+ (_callers ??= <MemberEntity, Setlet<ir.Node?>>{})
+ .putIfAbsent(caller, () => Setlet())
+ .add(node);
}
- void removeCall(MemberEntity caller, ir.Node /*?*/ node) {
- if (_callers == null) return;
- Setlet calls = _callers[caller];
+ void removeCall(MemberEntity caller, Object node) {
+ final callers = _callers;
+ if (callers == null) return;
+ final calls = callers[caller];
if (calls == null) return;
calls.remove(node);
if (calls.isEmpty) {
- _callers.remove(caller);
+ callers.remove(caller);
}
}
- Iterable<MemberEntity> get callersForTesting {
+ Iterable<MemberEntity>? get callersForTesting {
return _callers?.keys;
}
@@ -464,10 +465,11 @@
}
bool _computeIsCalledOnce() {
+ final callers = _callers;
if (_calledIndirectly) return false;
- if (_callers == null) return false;
+ if (callers == null) return false;
int count = 0;
- for (var set in _callers.values) {
+ for (var set in callers.values) {
count += set.length;
if (count > 1) return false;
}
@@ -488,9 +490,9 @@
@override
bool get isStable => super.isStable && !isClosurized;
- AbstractValue handleSpecialCases(InferrerEngine inferrer);
+ AbstractValue? handleSpecialCases(InferrerEngine inferrer);
- AbstractValue _handleFunctionCase(
+ AbstractValue? _handleFunctionCase(
FunctionEntity function, InferrerEngine inferrer) {
if (inferrer.closedWorld.nativeData.isNativeMember(function)) {
// Use the type annotation as the type for native elements. We
@@ -527,7 +529,7 @@
@override
AbstractValue computeType(InferrerEngine inferrer) {
- AbstractValue special = handleSpecialCases(inferrer);
+ final special = handleSpecialCases(inferrer);
if (special != null) return potentiallyNarrowType(special, inferrer);
return potentiallyNarrowType(
inferrer.types.computeTypeMask(inputs), inferrer);
@@ -554,36 +556,37 @@
@override
String getInferredSignature(TypeSystem types) {
- return types.getInferredSignatureOfMethod(_member);
+ return types.getInferredSignatureOfMethod(_member as FunctionEntity);
}
}
class FieldTypeInformation extends MemberTypeInformation {
- FieldEntity get _field => _member;
+ @override
+ final FieldEntity _member;
final DartType _type;
FieldTypeInformation(
- AbstractValueDomain abstractValueDomain, FieldEntity element, this._type)
- : super._internal(abstractValueDomain, element);
+ AbstractValueDomain abstractValueDomain, this._member, this._type)
+ : super._internal(abstractValueDomain, _member);
@override
- AbstractValue handleSpecialCases(InferrerEngine inferrer) {
- if (!inferrer.canFieldBeUsedForGlobalOptimizations(_field) ||
- inferrer.assumeDynamic(_field)) {
+ AbstractValue? handleSpecialCases(InferrerEngine inferrer) {
+ if (!inferrer.canFieldBeUsedForGlobalOptimizations(_member) ||
+ inferrer.assumeDynamic(_member)) {
// Do not infer types for fields that have a corresponding annotation or
// are assigned by synthesized calls
giveUp(inferrer);
return safeType(inferrer);
}
- if (inferrer.closedWorld.nativeData.isNativeMember(_field)) {
+ if (inferrer.closedWorld.nativeData.isNativeMember(_member)) {
// Use the type annotation as the type for native elements. We
// also give up on inferring to make sure this element never
// goes in the work queue.
giveUp(inferrer);
return inferrer
.typeOfNativeBehavior(inferrer.closedWorld.nativeData
- .getNativeFieldLoadBehavior(_field))
+ .getNativeFieldLoadBehavior(_member))
.type;
}
return null;
@@ -599,7 +602,7 @@
bool hasStableType(InferrerEngine inferrer) {
// The number of inputs of non-final fields is
// not stable. Therefore such a field cannot be stable.
- if (!_field.isAssignable) {
+ if (!_member.isAssignable) {
return false;
}
return super.hasStableType(inferrer);
@@ -607,16 +610,17 @@
}
class GetterTypeInformation extends MemberTypeInformation {
- FunctionEntity get _getter => _member;
+ @override
+ final FunctionEntity _member;
final FunctionType _type;
- GetterTypeInformation(AbstractValueDomain abstractValueDomain,
- FunctionEntity element, this._type)
- : super._internal(abstractValueDomain, element);
+ GetterTypeInformation(
+ AbstractValueDomain abstractValueDomain, this._member, this._type)
+ : super._internal(abstractValueDomain, _member);
@override
- AbstractValue handleSpecialCases(InferrerEngine inferrer) {
- return _handleFunctionCase(_getter, inferrer);
+ AbstractValue? handleSpecialCases(InferrerEngine inferrer) {
+ return _handleFunctionCase(_member, inferrer);
}
@override
@@ -627,15 +631,15 @@
}
class SetterTypeInformation extends MemberTypeInformation {
- FunctionEntity get _setter => _member;
+ @override
+ final FunctionEntity _member;
- SetterTypeInformation(
- AbstractValueDomain abstractValueDomain, FunctionEntity element)
- : super._internal(abstractValueDomain, element);
+ SetterTypeInformation(AbstractValueDomain abstractValueDomain, this._member)
+ : super._internal(abstractValueDomain, _member);
@override
- AbstractValue handleSpecialCases(InferrerEngine inferrer) {
- return _handleFunctionCase(_setter, inferrer);
+ AbstractValue? handleSpecialCases(InferrerEngine inferrer) {
+ return _handleFunctionCase(_member, inferrer);
}
@override
@@ -646,22 +650,23 @@
}
class MethodTypeInformation extends MemberTypeInformation {
- FunctionEntity get _method => _member;
+ @override
+ final FunctionEntity _member;
final FunctionType _type;
- MethodTypeInformation(AbstractValueDomain abstractValueDomain,
- FunctionEntity element, this._type)
- : super._internal(abstractValueDomain, element);
+ MethodTypeInformation(
+ AbstractValueDomain abstractValueDomain, this._member, this._type)
+ : super._internal(abstractValueDomain, _member);
@override
- AbstractValue handleSpecialCases(InferrerEngine inferrer) {
- return _handleFunctionCase(_method, inferrer);
+ AbstractValue? handleSpecialCases(InferrerEngine inferrer) {
+ return _handleFunctionCase(_member, inferrer);
}
@override
AbstractValue _potentiallyNarrowType(
AbstractValue mask, InferrerEngine inferrer) {
- if (inferrer.commonElements.isLateReadCheck(_method)) {
+ if (inferrer.commonElements.isLateReadCheck(_member)) {
mask = inferrer.abstractValueDomain.excludeLateSentinel(mask);
}
return _narrowType(inferrer.closedWorld, mask, _type.returnType);
@@ -672,31 +677,31 @@
}
class FactoryConstructorTypeInformation extends MemberTypeInformation {
- ConstructorEntity get _constructor => _member;
+ @override
+ final ConstructorEntity _member;
final FunctionType _type;
- FactoryConstructorTypeInformation(AbstractValueDomain abstractValueDomain,
- ConstructorEntity element, this._type)
- : super._internal(abstractValueDomain, element);
+ FactoryConstructorTypeInformation(
+ AbstractValueDomain abstractValueDomain, this._member, this._type)
+ : super._internal(abstractValueDomain, _member);
@override
- AbstractValue handleSpecialCases(InferrerEngine inferrer) {
+ AbstractValue? handleSpecialCases(InferrerEngine inferrer) {
AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
- if (_constructor.isFromEnvironmentConstructor) {
- if (_constructor.enclosingClass == inferrer.commonElements.intClass) {
+ if (_member.isFromEnvironmentConstructor) {
+ if (_member.enclosingClass == inferrer.commonElements.intClass) {
giveUp(inferrer);
return abstractValueDomain.includeNull(abstractValueDomain.intType);
- } else if (_constructor.enclosingClass ==
- inferrer.commonElements.boolClass) {
+ } else if (_member.enclosingClass == inferrer.commonElements.boolClass) {
giveUp(inferrer);
return abstractValueDomain.includeNull(abstractValueDomain.boolType);
- } else if (_constructor.enclosingClass ==
+ } else if (_member.enclosingClass ==
inferrer.commonElements.stringClass) {
giveUp(inferrer);
return abstractValueDomain.includeNull(abstractValueDomain.stringType);
}
}
- return _handleFunctionCase(_constructor, inferrer);
+ return _handleFunctionCase(_member, inferrer);
}
@override
@@ -712,15 +717,16 @@
}
class GenerativeConstructorTypeInformation extends MemberTypeInformation {
- ConstructorEntity get _constructor => _member;
+ @override
+ final FunctionEntity _member;
GenerativeConstructorTypeInformation(
- AbstractValueDomain abstractValueDomain, ConstructorEntity element)
- : super._internal(abstractValueDomain, element);
+ AbstractValueDomain abstractValueDomain, this._member)
+ : super._internal(abstractValueDomain, _member);
@override
- AbstractValue handleSpecialCases(InferrerEngine inferrer) {
- return _handleFunctionCase(_constructor, inferrer);
+ AbstractValue? handleSpecialCases(InferrerEngine inferrer) {
+ return _handleFunctionCase(_member, inferrer);
}
@override
@@ -796,13 +802,12 @@
_isTearOffClosureParameter = true;
// We have to add a flow-edge for the default value (if it exists), as we
// might not see all call-sites and thus miss the use of it.
- TypeInformation defaultType =
- inferrer.getDefaultTypeOfParameter(_parameter);
- if (defaultType != null) defaultType.addUser(this);
+ final defaultType = inferrer.getDefaultTypeOfParameter(_parameter);
+ defaultType.addUser(this);
}
// TODO(herhut): Cleanup into one conditional.
- AbstractValue handleSpecialCases(InferrerEngine inferrer) {
+ AbstractValue? handleSpecialCases(InferrerEngine inferrer) {
if (!inferrer.canFunctionParametersBeUsedForGlobalOptimizations(_method) ||
inferrer.assumeDynamic(_method)) {
// Do not infer types for parameters that have a corresponding annotation
@@ -890,7 +895,7 @@
@override
AbstractValue computeType(InferrerEngine inferrer) {
- AbstractValue special = handleSpecialCases(inferrer);
+ final special = handleSpecialCases(inferrer);
if (special != null) return special;
return potentiallyNarrowType(
inferrer.types.computeTypeMask(inputs), inferrer);
@@ -953,7 +958,7 @@
forIn,
}
-bool validCallType(CallType callType, ir.Node /*?*/ call, Selector selector) {
+bool validCallType(CallType callType, ir.Node? call, Selector selector) {
switch (callType) {
case CallType.access:
return call is ir.Node;
@@ -962,7 +967,6 @@
case CallType.forIn:
return call is ir.ForInStatement;
}
- throw StateError('Unexpected call type $callType.');
}
/// A [CallSiteTypeInformation] is a call found in the AST, or a
@@ -975,10 +979,10 @@
/// and [selector] and [receiver] fields for dynamic calls.
abstract class CallSiteTypeInformation extends TypeInformation
with ApplyableTypeInformation {
- final ir.Node /*?*/ _call;
+ final ir.Node? _call;
final MemberEntity caller;
- final Selector selector;
- final ArgumentsTypes arguments;
+ final Selector? selector;
+ final ArgumentsTypes? arguments;
final bool inLoop;
CallSiteTypeInformation(
@@ -990,7 +994,7 @@
this.arguments,
this.inLoop)
: super.noInputs(abstractValueDomain.emptyType, context) {
- assert(_call is ir.Node || (_call == null && selector.name == '=='));
+ assert(_call is ir.Node || (_call == null && selector?.name == '=='));
}
@override
@@ -1011,7 +1015,7 @@
StaticCallSiteTypeInformation(
AbstractValueDomain abstractValueDomain,
MemberTypeInformation context,
- ir.Node /*?*/ call,
+ ir.Node? call,
MemberEntity enclosing,
this.calledElement,
Selector selector,
@@ -1029,10 +1033,10 @@
@override
void addToGraph(InferrerEngine inferrer) {
MemberTypeInformation callee = _getCalledTypeInfo(inferrer);
- callee.addCall(caller, _call);
+ callee.addCall(caller, _call!);
callee.addUser(this);
if (arguments != null) {
- arguments.forEach((info) => info.addUser(this));
+ arguments!.forEach((info) => info.addUser(this));
}
inferrer.updateParameterInputs(this, calledElement, arguments, selector,
remove: false, addToQueue: false);
@@ -1072,7 +1076,7 @@
bool hasStableType(InferrerEngine inferrer) {
bool isStable = _getCalledTypeInfo(inferrer).isStable;
return isStable &&
- (arguments == null || arguments.every((info) => info.isStable)) &&
+ (arguments == null || arguments!.every((info) => info.isStable)) &&
super.hasStableType(inferrer);
}
@@ -1081,7 +1085,7 @@
ElementTypeInformation callee = _getCalledTypeInfo(inferrer);
callee.removeUser(this);
if (arguments != null) {
- arguments.forEach((info) => info.removeUser(this));
+ arguments!.forEach((info) => info.removeUser(this));
}
super.removeAndClearReferences(inferrer);
}
@@ -1107,7 +1111,7 @@
IndirectDynamicCallSiteTypeInformation(
AbstractValueDomain abstractValueDomain,
MemberTypeInformation context,
- ir.Node /*?*/ call,
+ ir.Node? call,
this.dynamicCall,
MemberEntity enclosing,
Selector selector,
@@ -1123,20 +1127,22 @@
void addToGraph(InferrerEngine inferrer) {
receiver.addUser(this);
dynamicCall.receiver.addInput(receiver);
- List<TypeInformation> positional = arguments.positional;
+ final args = arguments!;
+ List<TypeInformation> positional = args.positional;
+ final dynamicCallArgs = dynamicCall.arguments!;
for (int i = 0; i < positional.length; i++) {
positional[i].addUser(this);
- dynamicCall.arguments.positional[i].addInput(positional[i]);
+ dynamicCallArgs.positional[i].addInput(positional[i]);
}
- arguments.named.forEach((name, namedInfo) {
- dynamicCall.arguments.named[name].addInput(namedInfo);
+ args.named.forEach((name, namedInfo) {
+ dynamicCallArgs.named[name]!.addInput(namedInfo);
});
dynamicCall.addUser(this);
}
@override
AbstractValue computeType(InferrerEngine inferrer) {
- AbstractValue typeMask = _computeTypedSelector(inferrer);
+ final typeMask = _computeTypedSelector(inferrer);
inferrer.updateSelectorInMember(
caller, CallType.access, _call, selector, typeMask);
@@ -1151,7 +1157,7 @@
return result;
}
- AbstractValue _computeTypedSelector(InferrerEngine inferrer) {
+ AbstractValue? _computeTypedSelector(InferrerEngine inferrer) {
AbstractValue receiverType = receiver.type;
if (mask == receiverType) return mask;
return receiverType == inferrer.abstractValueDomain.dynamicType
@@ -1185,7 +1191,7 @@
dynamicCall.removeUser(this);
receiver.removeUser(this);
if (arguments != null) {
- arguments.forEach((info) => info.removeUser(this));
+ arguments!.forEach((info) => info.removeUser(this));
}
super.removeAndClearReferences(inferrer);
}
@@ -1197,16 +1203,16 @@
final TypeInformation receiver;
final AbstractValue mask;
final bool isConditional;
- bool _hasClosureCallTargets;
+ bool? _hasClosureCallTargets;
/// Cached concrete targets of this call.
- Iterable<MemberEntity> _concreteTargets;
+ Iterable<MemberEntity>? _concreteTargets;
DynamicCallSiteTypeInformation(
AbstractValueDomain abstractValueDomain,
MemberTypeInformation context,
this._callType,
- T call,
+ T? call,
MemberEntity enclosing,
Selector selector,
this.mask,
@@ -1223,28 +1229,29 @@
if (_callType == CallType.indirectAccess) {
callee._calledIndirectly = true;
} else {
- callee.addCall(caller, _call);
+ callee.addCall(caller, _call!);
}
}
void _removeCall(MemberTypeInformation callee) {
if (_callType != CallType.indirectAccess) {
- callee.removeCall(caller, _call);
+ callee.removeCall(caller, _call!);
}
}
@override
void addToGraph(InferrerEngine inferrer) {
- assert(receiver != null);
- AbstractValue typeMask = computeTypedSelector(inferrer);
+ assert((receiver as dynamic) != null); // TODO(48820): Remove when sound.
+ final typeMask = computeTypedSelector(inferrer);
_hasClosureCallTargets =
- inferrer.closedWorld.includesClosureCall(selector, typeMask);
- _concreteTargets = inferrer.closedWorld.locateMembers(selector, typeMask);
+ inferrer.closedWorld.includesClosureCall(selector!, typeMask);
+ final concreteTargets = _concreteTargets =
+ inferrer.closedWorld.locateMembers(selector!, typeMask);
receiver.addUser(this);
if (arguments != null) {
- arguments.forEach((info) => info.addUser(this));
+ arguments!.forEach((info) => info.addUser(this));
}
- for (MemberEntity element in _concreteTargets) {
+ for (MemberEntity element in concreteTargets) {
MemberTypeInformation callee =
inferrer.types.getInferredTypeOfMember(element);
_addCall(callee);
@@ -1255,17 +1262,17 @@
}
/// `true` if this invocation can hit a 'call' method on a closure.
- bool get hasClosureCallTargets => _hasClosureCallTargets;
+ bool get hasClosureCallTargets => _hasClosureCallTargets!;
/// All concrete targets of this invocation. If [hasClosureCallTargets] is
/// `true` the invocation can additional target an unknown set of 'call'
/// methods on closures.
- Iterable<MemberEntity> get concreteTargets => _concreteTargets;
+ Iterable<MemberEntity> get concreteTargets => _concreteTargets!;
@override
- Iterable<MemberEntity> get callees => _concreteTargets;
+ Iterable<MemberEntity> get callees => _concreteTargets!;
- AbstractValue computeTypedSelector(InferrerEngine inferrer) {
+ AbstractValue? computeTypedSelector(InferrerEngine inferrer) {
AbstractValue receiverType = receiver.type;
if (mask != receiverType) {
return receiverType == inferrer.abstractValueDomain.dynamicType
@@ -1277,11 +1284,11 @@
}
bool targetsIncludeComplexNoSuchMethod(InferrerEngine inferrer) {
- return _concreteTargets.any((MemberEntity e) {
+ return _concreteTargets!.any((MemberEntity e) {
return e.isFunction &&
e.isInstanceMember &&
e.name == Identifiers.noSuchMethod_ &&
- inferrer.noSuchMethodData.isComplex(e);
+ inferrer.noSuchMethodData.isComplex(e as FunctionEntity);
});
}
@@ -1292,31 +1299,31 @@
///
/// Returns the more precise TypeInformation, or `null` to defer to the
/// library code.
- TypeInformation handleIntrisifiedSelector(
- Selector selector, AbstractValue mask, InferrerEngine inferrer) {
+ TypeInformation? handleIntrisifiedSelector(
+ Selector selector, AbstractValue? mask, InferrerEngine inferrer) {
AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
if (mask == null) return null;
if (abstractValueDomain.isIntegerOrNull(mask).isPotentiallyFalse) {
return null;
}
if (!selector.isCall && !selector.isOperator) return null;
- if (!arguments.named.isEmpty) return null;
- if (arguments.positional.length > 1) return null;
+ final args = arguments!;
+ if (!args.named.isEmpty) return null;
+ if (args.positional.length > 1) return null;
- bool isInt(info) =>
+ bool isInt(TypeInformation info) =>
abstractValueDomain.isIntegerOrNull(info.type).isDefinitelyTrue;
- bool isEmpty(info) =>
+ bool isEmpty(TypeInformation info) =>
abstractValueDomain.isEmpty(info.type).isDefinitelyTrue;
- bool isUInt31(info) => abstractValueDomain
+ bool isUInt31(TypeInformation info) => abstractValueDomain
.isUInt31(abstractValueDomain.excludeNull(info.type))
.isDefinitelyTrue;
- bool isPositiveInt(info) =>
+ bool isPositiveInt(TypeInformation info) =>
abstractValueDomain.isPositiveIntegerOrNull(info.type).isDefinitelyTrue;
TypeInformation tryLater() => inferrer.types.nonNullEmptyType;
- TypeInformation argument =
- arguments.isEmpty ? null : arguments.positional.first;
+ final argument = args.isEmpty ? null : args.positional.first;
String name = selector.name;
// These are type inference rules only for useful cases that are not
@@ -1331,7 +1338,7 @@
case '%':
case 'remainder':
case '~/':
- if (isEmpty(argument)) return tryLater();
+ if (isEmpty(argument!)) return tryLater();
if (isPositiveInt(receiver) && isPositiveInt(argument)) {
// uint31 + uint31 -> uint32
if (name == '+' && isUInt31(receiver) && isUInt31(argument)) {
@@ -1346,35 +1353,35 @@
case '|':
case '^':
- if (isEmpty(argument)) return tryLater();
+ if (isEmpty(argument!)) return tryLater();
if (isUInt31(receiver) && isUInt31(argument)) {
return inferrer.types.uint31Type;
}
return null;
case '>>':
- if (isEmpty(argument)) return tryLater();
+ if (isEmpty(argument!)) return tryLater();
if (isUInt31(receiver)) {
return inferrer.types.uint31Type;
}
return null;
case '>>>':
- if (isEmpty(argument)) return tryLater();
+ if (isEmpty(argument!)) return tryLater();
if (isUInt31(receiver)) {
return inferrer.types.uint31Type;
}
return null;
case '&':
- if (isEmpty(argument)) return tryLater();
+ if (isEmpty(argument!)) return tryLater();
if (isUInt31(receiver) || isUInt31(argument)) {
return inferrer.types.uint31Type;
}
return null;
case '-':
- if (isEmpty(argument)) return tryLater();
+ if (isEmpty(argument!)) return tryLater();
if (isInt(argument)) {
return inferrer.types.intType;
}
@@ -1385,9 +1392,7 @@
return inferrer.types.intType;
case 'abs':
- return arguments.hasNoArguments()
- ? inferrer.types.positiveIntType
- : null;
+ return args.hasNoArguments() ? inferrer.types.positiveIntType : null;
default:
return null;
@@ -1398,19 +1403,21 @@
AbstractValue computeType(InferrerEngine inferrer) {
JClosedWorld closedWorld = inferrer.closedWorld;
AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
- Iterable<MemberEntity> oldTargets = _concreteTargets;
- AbstractValue typeMask = computeTypedSelector(inferrer);
+ final oldTargets = _concreteTargets!;
+ final typeMask = computeTypedSelector(inferrer);
+ final localSelector = selector!;
inferrer.updateSelectorInMember(
- caller, _callType, _call, selector, typeMask);
+ caller, _callType, _call, localSelector, typeMask);
_hasClosureCallTargets =
- closedWorld.includesClosureCall(selector, typeMask);
- _concreteTargets = closedWorld.locateMembers(selector, typeMask);
+ closedWorld.includesClosureCall(localSelector, typeMask);
+ final concreteTargets =
+ _concreteTargets = closedWorld.locateMembers(localSelector, typeMask);
// Update the call graph if the targets could have changed.
- if (!identical(_concreteTargets, oldTargets)) {
+ if (!identical(concreteTargets, oldTargets)) {
// Add calls to new targets to the graph.
- _concreteTargets
+ concreteTargets
.where((target) => !oldTargets.contains(target))
.forEach((MemberEntity element) {
MemberTypeInformation callee =
@@ -1423,7 +1430,7 @@
// Walk over the old targets, and remove calls that cannot happen anymore.
oldTargets
- .where((target) => !_concreteTargets.contains(target))
+ .where((target) => !concreteTargets.contains(target))
.forEach((MemberEntity element) {
MemberTypeInformation callee =
inferrer.types.getInferredTypeOfMember(element);
@@ -1437,18 +1444,18 @@
// Walk over the found targets, and compute the joined union type mask
// for all these targets.
AbstractValue result;
- if (_hasClosureCallTargets) {
+ if (_hasClosureCallTargets!) {
result = abstractValueDomain.dynamicType;
} else {
result = inferrer.types
- .joinTypeMasks(_concreteTargets.map((MemberEntity element) {
+ .joinTypeMasks(concreteTargets.map((MemberEntity element) {
if (typeMask != null &&
- inferrer.returnsListElementType(selector, typeMask)) {
+ inferrer.returnsListElementType(localSelector, typeMask)) {
return abstractValueDomain.getContainerElementType(receiver.type);
} else if (typeMask != null &&
- inferrer.returnsMapValueType(selector, typeMask)) {
+ inferrer.returnsMapValueType(localSelector, typeMask)) {
if (abstractValueDomain.isDictionary(typeMask)) {
- AbstractValue arg = arguments.positional[0].type;
+ AbstractValue arg = arguments!.positional[0].type;
ConstantValue value = abstractValueDomain.getPrimitiveValue(arg);
if (value is StringConstantValue) {
String key = value.stringValue;
@@ -1476,8 +1483,8 @@
}
return abstractValueDomain.getMapValueType(typeMask);
} else {
- TypeInformation info =
- handleIntrisifiedSelector(selector, typeMask, inferrer);
+ final info =
+ handleIntrisifiedSelector(localSelector, typeMask, inferrer);
if (info != null) return info.type;
return inferrer.typeOfMemberWithSelector(element, selector).type;
}
@@ -1495,16 +1502,19 @@
@override
void giveUp(InferrerEngine inferrer, {bool clearInputs = true}) {
if (!abandonInferencing) {
- inferrer.updateSelectorInMember(caller, _callType, _call, selector, mask);
- Iterable<MemberEntity> oldTargets = _concreteTargets;
+ final call = _call!;
+ inferrer.updateSelectorInMember(caller, _callType, call, selector, mask);
+ final oldTargets = concreteTargets;
+ final localSelector = selector!;
_hasClosureCallTargets =
- inferrer.closedWorld.includesClosureCall(selector, mask);
- _concreteTargets = inferrer.closedWorld.locateMembers(selector, mask);
- for (MemberEntity element in _concreteTargets) {
+ inferrer.closedWorld.includesClosureCall(localSelector, mask);
+ final newConcreteTargets = _concreteTargets =
+ inferrer.closedWorld.locateMembers(localSelector, mask);
+ for (MemberEntity element in newConcreteTargets) {
if (!oldTargets.contains(element)) {
MemberTypeInformation callee =
inferrer.types.getInferredTypeOfMember(element);
- callee.addCall(caller, _call);
+ callee.addCall(caller, call);
inferrer.updateParameterInputs(this, element, arguments, selector,
remove: false, addToQueue: true);
}
@@ -1515,13 +1525,13 @@
@override
void removeAndClearReferences(InferrerEngine inferrer) {
- for (MemberEntity element in _concreteTargets) {
+ for (MemberEntity element in concreteTargets) {
MemberTypeInformation callee =
inferrer.types.getInferredTypeOfMember(element);
callee.removeUser(this);
}
if (arguments != null) {
- arguments.forEach((info) => info.removeUser(this));
+ arguments!.forEach((info) => info.removeUser(this));
}
super.removeAndClearReferences(inferrer);
}
@@ -1537,9 +1547,9 @@
@override
bool hasStableType(InferrerEngine inferrer) {
return receiver.isStable &&
- _concreteTargets.every((MemberEntity element) =>
+ concreteTargets.every((MemberEntity element) =>
inferrer.types.getInferredTypeOfMember(element).isStable) &&
- (arguments == null || arguments.every((info) => info.isStable)) &&
+ (arguments == null || arguments!.every((info) => info.isStable)) &&
super.hasStableType(inferrer);
}
}
@@ -1550,7 +1560,7 @@
ClosureCallSiteTypeInformation(
AbstractValueDomain abstractValueDomain,
MemberTypeInformation context,
- ir.Node /*?*/ call,
+ ir.Node? call,
MemberEntity enclosing,
Selector selector,
this.closure,
@@ -1561,7 +1571,7 @@
@override
void addToGraph(InferrerEngine inferrer) {
- arguments.forEach((info) => info.addUser(this));
+ arguments!.forEach((info) => info.addUser(this));
closure.addUser(this);
}
@@ -1763,7 +1773,7 @@
bool inferred = false;
InferredTypeInformation(AbstractValueDomain abstractValueDomain,
- MemberTypeInformation context, TypeInformation parentType)
+ MemberTypeInformation? context, TypeInformation? parentType)
: super(abstractValueDomain.emptyType, context) {
if (parentType != null) addInput(parentType);
}
@@ -1789,14 +1799,14 @@
final AbstractValue originalType;
/// The length at the allocation site.
- final int originalLength;
+ final int? originalLength;
/// The length after the container has been traced.
- int inferredLength;
+ late int inferredLength;
ListTypeInformation(
AbstractValueDomain abstractValueDomain,
- MemberTypeInformation context,
+ MemberTypeInformation? context,
this.originalType,
this.elementType,
this.originalLength)
@@ -1850,7 +1860,7 @@
/// elements in a [ListTypeInformation].
class ElementInContainerTypeInformation extends InferredTypeInformation {
ElementInContainerTypeInformation(AbstractValueDomain abstractValueDomain,
- MemberTypeInformation context, elementType)
+ MemberTypeInformation? context, elementType)
: super(abstractValueDomain, context, elementType);
@override
@@ -1869,7 +1879,7 @@
final AbstractValue originalType;
SetTypeInformation(
- MemberTypeInformation context, this.originalType, this.elementType)
+ MemberTypeInformation? context, this.originalType, this.elementType)
: super(originalType, context) {
elementType.addUser(this);
}
@@ -1917,7 +1927,7 @@
/// [SetTypeInformation].
class ElementInSetTypeInformation extends InferredTypeInformation {
ElementInSetTypeInformation(AbstractValueDomain abstractValueDomain,
- MemberTypeInformation context, elementType)
+ MemberTypeInformation? context, elementType)
: super(abstractValueDomain, context, elementType);
@override
@@ -1945,32 +1955,32 @@
bool get inDictionaryMode => !bailedOut && _allKeysAreStrings;
- MapTypeInformation(MemberTypeInformation context, this.originalType,
+ MapTypeInformation(MemberTypeInformation? context, this.originalType,
this.keyType, this.valueType)
: super(originalType, context) {
keyType.addUser(this);
valueType.addUser(this);
}
- TypeInformation addEntryInput(AbstractValueDomain abstractValueDomain,
+ TypeInformation? addEntryInput(AbstractValueDomain abstractValueDomain,
TypeInformation key, TypeInformation value,
[bool nonNull = false]) {
- TypeInformation newInfo = null;
+ ValueInMapTypeInformation? newInfo = null;
if (_allKeysAreStrings && key is StringLiteralTypeInformation) {
String keyString = key.asString();
typeInfoMap.putIfAbsent(keyString, () {
newInfo = ValueInMapTypeInformation(
abstractValueDomain, context, null, nonNull);
- return newInfo;
+ return newInfo!;
});
- typeInfoMap[keyString].addInput(value);
+ typeInfoMap[keyString]!.addInput(value);
} else {
_allKeysAreStrings = false;
typeInfoMap.clear();
}
keyType.addInput(key);
valueType.addInput(value);
- if (newInfo != null) newInfo.addUser(this);
+ newInfo?.addUser(this);
return newInfo;
}
@@ -1981,12 +1991,12 @@
if (_allKeysAreStrings && other.inDictionaryMode) {
other.typeInfoMap.forEach((keyString, value) {
typeInfoMap.putIfAbsent(keyString, () {
- TypeInformation newInfo = ValueInMapTypeInformation(
+ final newInfo = ValueInMapTypeInformation(
abstractValueDomain, context, null, false);
newInfos.add(newInfo);
return newInfo;
});
- typeInfoMap[keyString].addInput(value);
+ typeInfoMap[keyString]!.addInput(value);
});
} else {
_allKeysAreStrings = false;
@@ -2018,7 +2028,7 @@
if (inDictionaryMode) {
Map<String, AbstractValue> mappings = Map<String, AbstractValue>();
for (var key in typeInfoMap.keys) {
- mappings[key] = typeInfoMap[key].type;
+ mappings[key] = typeInfoMap[key]!.type;
}
return inferrer.abstractValueDomain.createDictionaryValue(
abstractValueDomain.getGeneralization(originalType),
@@ -2045,14 +2055,14 @@
} else if (abstractValueDomain.isDictionary(type)) {
assert(inDictionaryMode);
for (String key in typeInfoMap.keys) {
- TypeInformation value = typeInfoMap[key];
+ final value = typeInfoMap[key]!;
if (!abstractValueDomain.containsDictionaryKey(type, key) &&
abstractValueDomain.containsAll(value.type).isDefinitelyFalse &&
abstractValueDomain.isNull(value.type).isDefinitelyFalse) {
return toTypeMask(inferrer);
}
if (abstractValueDomain.getDictionaryValueForKey(type, key) !=
- typeInfoMap[key].type) {
+ typeInfoMap[key]!.type) {
return toTypeMask(inferrer);
}
}
@@ -2099,7 +2109,7 @@
/// for the keys in a [MapTypeInformation]
class KeyInMapTypeInformation extends InferredTypeInformation {
KeyInMapTypeInformation(AbstractValueDomain abstractValueDomain,
- MemberTypeInformation context, TypeInformation keyType)
+ MemberTypeInformation? context, TypeInformation keyType)
: super(abstractValueDomain, context, keyType);
@override
@@ -2120,7 +2130,7 @@
final bool nonNull;
ValueInMapTypeInformation(AbstractValueDomain abstractValueDomain,
- MemberTypeInformation context, TypeInformation valueType,
+ MemberTypeInformation? context, TypeInformation? valueType,
[this.nonNull = false])
: super(abstractValueDomain, context, valueType);
@@ -2143,13 +2153,13 @@
/// A [PhiElementTypeInformation] is an union of
/// [ElementTypeInformation], that is local to a method.
class PhiElementTypeInformation extends TypeInformation {
- final ir.Node branchNode;
- final Local variable;
+ final ir.Node? branchNode;
+ final Local? variable;
final bool isTry;
PhiElementTypeInformation(AbstractValueDomain abstractValueDomain,
- MemberTypeInformation context, this.branchNode, this.variable,
- {this.isTry})
+ MemberTypeInformation? context, this.branchNode, this.variable,
+ {required this.isTry})
: super(abstractValueDomain.emptyType, context);
@override
@@ -2186,7 +2196,7 @@
final FunctionEntity _element;
ClosureTypeInformation(AbstractValueDomain abstractValueDomain,
- MemberTypeInformation context, this._element)
+ MemberTypeInformation? context, this._element)
: super(abstractValueDomain.emptyType, context);
FunctionEntity get closure => _element;
@@ -2227,7 +2237,7 @@
/// Set to true once analysis is completed.
bool analyzed = false;
- Set<TypeInformation> _flowsInto;
+ Set<TypeInformation>? _flowsInto;
/// The set of [TypeInformation] nodes where values from the traced node could
/// flow in.
@@ -2241,7 +2251,7 @@
if (_flowsInto == null) {
_flowsInto = nodes.toSet();
} else {
- _flowsInto.addAll(nodes);
+ _flowsInto!.addAll(nodes);
}
}
}
@@ -2326,7 +2336,7 @@
if (isNullable) {
otherType = abstractValueDomain.includeNull(otherType);
}
- if (type == null) return otherType;
+ assert((type as dynamic) != null); // TODO(48820): Remove when sound.
AbstractValue newType = abstractValueDomain.intersection(type, otherType);
return abstractValueDomain.isLateSentinel(type).isPotentiallyTrue
? abstractValueDomain.includeLateSentinel(newType)
diff --git a/pkg/compiler/lib/src/inferrer/type_system.dart b/pkg/compiler/lib/src/inferrer/type_system.dart
index 9a90a88..34abce3 100644
--- a/pkg/compiler/lib/src/inferrer/type_system.dart
+++ b/pkg/compiler/lib/src/inferrer/type_system.dart
@@ -2,14 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart = 2.10
-
import 'package:kernel/ast.dart' as ir;
import '../common.dart';
import '../constants/values.dart' show BoolConstantValue;
import '../elements/entities.dart';
import '../elements/types.dart';
-import '../world.dart';
+import '../world_interfaces.dart';
import 'abstract_value_domain.dart';
import 'type_graph_nodes.dart';
@@ -30,7 +28,7 @@
void forEachParameter(FunctionEntity function, void f(Local parameter));
/// Returns whether [node] is valid as a general phi node.
- bool checkPhiNode(ir.Node node);
+ bool checkPhiNode(ir.Node? node);
/// Returns whether [node] is valid as a loop phi node.
bool checkLoopPhiNode(ir.Node node);
@@ -81,8 +79,7 @@
final Set<TypeInformation> allocatedClosures = Set<TypeInformation>();
/// Cache of [ConcreteTypeInformation].
- final Map<AbstractValue, TypeInformation> concreteTypes =
- Map<AbstractValue, TypeInformation>();
+ final Map<AbstractValue, ConcreteTypeInformation> concreteTypes = {};
/// Cache of some primitive constant types.
final Map<Object, TypeInformation> primitiveConstantTypes = {};
@@ -113,17 +110,15 @@
allocatedTypes,
].expand((x) => x);
- TypeSystem(this._closedWorld, this.strategy) {
- nonNullEmptyType = getConcreteTypeFor(_abstractValueDomain.emptyType);
- }
+ TypeSystem(this._closedWorld, this.strategy);
AbstractValueDomain get _abstractValueDomain =>
_closedWorld.abstractValueDomain;
/// Used to group [TypeInformation] nodes by the element that triggered their
/// creation.
- MemberTypeInformation _currentMember = null;
- MemberTypeInformation get currentMember => _currentMember;
+ MemberTypeInformation? _currentMember = null;
+ MemberTypeInformation? get currentMember => _currentMember;
void withMember(MemberEntity element, void action()) {
assert(_currentMember == null,
@@ -133,157 +128,81 @@
_currentMember = null;
}
- TypeInformation nullTypeCache;
- TypeInformation get nullType {
- if (nullTypeCache != null) return nullTypeCache;
- return nullTypeCache = getConcreteTypeFor(_abstractValueDomain.nullType);
- }
+ late final TypeInformation nullType =
+ getConcreteTypeFor(_abstractValueDomain.nullType);
- TypeInformation intTypeCache;
- TypeInformation get intType {
- if (intTypeCache != null) return intTypeCache;
- return intTypeCache = getConcreteTypeFor(_abstractValueDomain.intType);
- }
+ late final TypeInformation intType =
+ getConcreteTypeFor(_abstractValueDomain.intType);
- TypeInformation uint32TypeCache;
- TypeInformation get uint32Type {
- if (uint32TypeCache != null) return uint32TypeCache;
- return uint32TypeCache =
- getConcreteTypeFor(_abstractValueDomain.uint32Type);
- }
+ late final TypeInformation uint32Type =
+ getConcreteTypeFor(_abstractValueDomain.uint32Type);
- TypeInformation uint31TypeCache;
- TypeInformation get uint31Type {
- if (uint31TypeCache != null) return uint31TypeCache;
- return uint31TypeCache =
- getConcreteTypeFor(_abstractValueDomain.uint31Type);
- }
+ late final TypeInformation uint31Type =
+ getConcreteTypeFor(_abstractValueDomain.uint31Type);
- TypeInformation positiveIntTypeCache;
- TypeInformation get positiveIntType {
- if (positiveIntTypeCache != null) return positiveIntTypeCache;
- return positiveIntTypeCache =
- getConcreteTypeFor(_abstractValueDomain.positiveIntType);
- }
+ late final TypeInformation positiveIntType =
+ getConcreteTypeFor(_abstractValueDomain.positiveIntType);
- TypeInformation numTypeCache;
- TypeInformation get numType {
- if (numTypeCache != null) return numTypeCache;
- return numTypeCache = getConcreteTypeFor(_abstractValueDomain.numType);
- }
+ late final TypeInformation numType =
+ getConcreteTypeFor(_abstractValueDomain.numType);
- TypeInformation boolTypeCache;
- TypeInformation get boolType {
- if (boolTypeCache != null) return boolTypeCache;
- return boolTypeCache = getConcreteTypeFor(_abstractValueDomain.boolType);
- }
+ late final TypeInformation boolType =
+ getConcreteTypeFor(_abstractValueDomain.boolType);
- TypeInformation functionTypeCache;
- TypeInformation get functionType {
- if (functionTypeCache != null) return functionTypeCache;
- return functionTypeCache =
- getConcreteTypeFor(_abstractValueDomain.functionType);
- }
+ late final TypeInformation functionType =
+ getConcreteTypeFor(_abstractValueDomain.functionType);
- TypeInformation listTypeCache;
- TypeInformation get listType {
- if (listTypeCache != null) return listTypeCache;
- return listTypeCache = getConcreteTypeFor(_abstractValueDomain.listType);
- }
+ late final TypeInformation listType =
+ getConcreteTypeFor(_abstractValueDomain.listType);
- TypeInformation constListTypeCache;
- TypeInformation get constListType {
- if (constListTypeCache != null) return constListTypeCache;
- return constListTypeCache =
- getConcreteTypeFor(_abstractValueDomain.constListType);
- }
+ late final TypeInformation constListType =
+ getConcreteTypeFor(_abstractValueDomain.constListType);
- TypeInformation fixedListTypeCache;
- TypeInformation get fixedListType {
- if (fixedListTypeCache != null) return fixedListTypeCache;
- return fixedListTypeCache =
- getConcreteTypeFor(_abstractValueDomain.fixedListType);
- }
+ late final TypeInformation fixedListType =
+ getConcreteTypeFor(_abstractValueDomain.fixedListType);
- TypeInformation growableListTypeCache;
- TypeInformation get growableListType {
- if (growableListTypeCache != null) return growableListTypeCache;
- return growableListTypeCache =
- getConcreteTypeFor(_abstractValueDomain.growableListType);
- }
+ late final TypeInformation growableListType =
+ getConcreteTypeFor(_abstractValueDomain.growableListType);
- TypeInformation _mutableArrayType;
- TypeInformation get mutableArrayType => _mutableArrayType ??=
+ late final TypeInformation mutableArrayType =
getConcreteTypeFor(_abstractValueDomain.mutableArrayType);
- TypeInformation setTypeCache;
- TypeInformation get setType =>
- setTypeCache ??= getConcreteTypeFor(_abstractValueDomain.setType);
+ late final TypeInformation setType =
+ getConcreteTypeFor(_abstractValueDomain.setType);
- TypeInformation constSetTypeCache;
- TypeInformation get constSetType => constSetTypeCache ??=
+ late final TypeInformation constSetType =
getConcreteTypeFor(_abstractValueDomain.constSetType);
- TypeInformation mapTypeCache;
- TypeInformation get mapType {
- if (mapTypeCache != null) return mapTypeCache;
- return mapTypeCache = getConcreteTypeFor(_abstractValueDomain.mapType);
- }
+ late final TypeInformation mapType =
+ getConcreteTypeFor(_abstractValueDomain.mapType);
- TypeInformation constMapTypeCache;
- TypeInformation get constMapType {
- if (constMapTypeCache != null) return constMapTypeCache;
- return constMapTypeCache =
- getConcreteTypeFor(_abstractValueDomain.constMapType);
- }
+ late final TypeInformation constMapType =
+ getConcreteTypeFor(_abstractValueDomain.constMapType);
- TypeInformation stringTypeCache;
- TypeInformation get stringType {
- if (stringTypeCache != null) return stringTypeCache;
- return stringTypeCache =
- getConcreteTypeFor(_abstractValueDomain.stringType);
- }
+ late final TypeInformation stringType =
+ getConcreteTypeFor(_abstractValueDomain.stringType);
- TypeInformation typeTypeCache;
- TypeInformation get typeType {
- if (typeTypeCache != null) return typeTypeCache;
- return typeTypeCache = getConcreteTypeFor(_abstractValueDomain.typeType);
- }
+ late final TypeInformation typeType =
+ getConcreteTypeFor(_abstractValueDomain.typeType);
- TypeInformation dynamicTypeCache;
- TypeInformation get dynamicType {
- if (dynamicTypeCache != null) return dynamicTypeCache;
- return dynamicTypeCache =
- getConcreteTypeFor(_abstractValueDomain.dynamicType);
- }
+ late final TypeInformation dynamicType =
+ getConcreteTypeFor(_abstractValueDomain.dynamicType);
- TypeInformation asyncFutureTypeCache;
// Subtype of Future returned by async methods.
- TypeInformation get asyncFutureType {
- if (asyncFutureTypeCache != null) return asyncFutureTypeCache;
- return asyncFutureTypeCache =
- getConcreteTypeFor(_abstractValueDomain.asyncFutureType);
- }
+ late final TypeInformation asyncFutureType =
+ getConcreteTypeFor(_abstractValueDomain.asyncFutureType);
- TypeInformation syncStarIterableTypeCache;
- TypeInformation get syncStarIterableType {
- if (syncStarIterableTypeCache != null) return syncStarIterableTypeCache;
- return syncStarIterableTypeCache =
- getConcreteTypeFor(_abstractValueDomain.syncStarIterableType);
- }
+ late final TypeInformation syncStarIterableType =
+ getConcreteTypeFor(_abstractValueDomain.syncStarIterableType);
- TypeInformation asyncStarStreamTypeCache;
- TypeInformation get asyncStarStreamType {
- if (asyncStarStreamTypeCache != null) return asyncStarStreamTypeCache;
- return asyncStarStreamTypeCache =
- getConcreteTypeFor(_abstractValueDomain.asyncStarStreamType);
- }
+ late final TypeInformation asyncStarStreamType =
+ getConcreteTypeFor(_abstractValueDomain.asyncStarStreamType);
- TypeInformation _lateSentinelType;
- TypeInformation get lateSentinelType => _lateSentinelType ??=
+ late final TypeInformation lateSentinelType =
getConcreteTypeFor(_abstractValueDomain.lateSentinelType);
- TypeInformation nonNullEmptyType;
+ late final TypeInformation nonNullEmptyType =
+ getConcreteTypeFor(_abstractValueDomain.emptyType);
TypeInformation stringLiteralType(String value) {
return StringLiteralTypeInformation(
@@ -312,7 +231,7 @@
/// Returns the least upper bound between [firstType] and
/// [secondType].
TypeInformation computeLUB(
- TypeInformation firstType, TypeInformation secondType) {
+ TypeInformation? firstType, TypeInformation secondType) {
if (firstType == null) return secondType;
if (firstType == secondType) return firstType;
if (firstType == nonNullEmptyType) return secondType;
@@ -431,7 +350,7 @@
/// Returns the internal inferrer representation for [mask].
ConcreteTypeInformation getConcreteTypeFor(AbstractValue mask) {
- assert(mask != null);
+ assert((mask as dynamic) != null); // TODO(48820): Remove when sound.
return concreteTypes.putIfAbsent(mask, () {
return ConcreteTypeInformation(mask);
});
@@ -471,24 +390,24 @@
return type == nullType;
}
- TypeInformation allocateList(
- TypeInformation type, ir.TreeNode node, MemberEntity enclosing,
- [TypeInformation elementType, int length]) {
+ TypeInformation allocateList(TypeInformation type, ir.TreeNode node,
+ MemberEntity enclosing, TypeInformation elementType,
+ [int? length]) {
assert(strategy.checkListNode(node));
- ClassEntity typedDataClass = _closedWorld.commonElements.typedDataClass;
- bool isTypedArray = typedDataClass != null &&
+ final typedDataClass = _closedWorld.commonElements.typedDataClass;
+ bool isTypedArray =
_closedWorld.classHierarchy.isInstantiated(typedDataClass) &&
- _abstractValueDomain
- .isInstanceOfOrNull(type.type, typedDataClass)
- .isDefinitelyTrue;
+ _abstractValueDomain
+ .isInstanceOfOrNull(type.type, typedDataClass)
+ .isDefinitelyTrue;
bool isConst = (type.type == _abstractValueDomain.constListType);
bool isFixed = (type.type == _abstractValueDomain.fixedListType) ||
isConst ||
isTypedArray;
bool isElementInferred = isConst || isTypedArray;
- int inferredLength = isFixed ? length : null;
- AbstractValue elementTypeMask =
+ final inferredLength = isFixed ? length : null;
+ final elementTypeMask =
isElementInferred ? elementType.type : dynamicType.type;
AbstractValue mask = _abstractValueDomain.createContainerValue(
type.type, node, enclosing, elementTypeMask, inferredLength);
@@ -512,9 +431,8 @@
return result;
}
- TypeInformation allocateSet(
- TypeInformation type, ir.TreeNode node, MemberEntity enclosing,
- [TypeInformation elementType]) {
+ TypeInformation allocateSet(TypeInformation type, ir.TreeNode node,
+ MemberEntity enclosing, TypeInformation elementType) {
assert(strategy.checkSetNode(node));
bool isConst = type.type == _abstractValueDomain.constSetType;
@@ -532,44 +450,47 @@
}
TypeInformation allocateMap(
- ConcreteTypeInformation type, ir.TreeNode node, MemberEntity element,
- [List<TypeInformation> keyTypes, List<TypeInformation> valueTypes]) {
+ ConcreteTypeInformation type,
+ ir.TreeNode node,
+ MemberEntity element,
+ List<TypeInformation> keyTypes,
+ List<TypeInformation> valueTypes) {
assert(strategy.checkMapNode(node));
assert(keyTypes.length == valueTypes.length);
bool isFixed = (type.type == _abstractValueDomain.constMapType);
- TypeInformation keyType, valueType;
+ PhiElementTypeInformation? keyType, valueType;
for (int i = 0; i < keyTypes.length; ++i) {
- TypeInformation type = keyTypes[i];
+ final typeForKey = keyTypes[i];
keyType = keyType == null
- ? allocatePhi(null, null, type, isTry: false)
- : addPhiInput(null, keyType, type);
+ ? allocatePhi(null, null, typeForKey, isTry: false)
+ : addPhiInput(null, keyType, typeForKey);
- type = valueTypes[i];
+ final typeForValue = valueTypes[i];
valueType = valueType == null
- ? allocatePhi(null, null, type, isTry: false)
- : addPhiInput(null, valueType, type);
+ ? allocatePhi(null, null, typeForValue, isTry: false)
+ : addPhiInput(null, valueType, typeForValue);
}
- keyType =
+ final simplifiedKeyType =
keyType == null ? nonNullEmpty() : simplifyPhi(null, null, keyType);
- valueType =
+ final simplifiedValueType =
valueType == null ? nonNullEmpty() : simplifyPhi(null, null, valueType);
AbstractValue keyTypeMask, valueTypeMask;
if (isFixed) {
- keyTypeMask = keyType.type;
- valueTypeMask = valueType.type;
+ keyTypeMask = simplifiedKeyType.type;
+ valueTypeMask = simplifiedValueType.type;
} else {
keyTypeMask = valueTypeMask = dynamicType.type;
}
AbstractValue mask = _abstractValueDomain.createMapValue(
type.type, node, element, keyTypeMask, valueTypeMask);
- TypeInformation keyTypeInfo =
- KeyInMapTypeInformation(_abstractValueDomain, currentMember, keyType);
- TypeInformation valueTypeInfo = ValueInMapTypeInformation(
- _abstractValueDomain, currentMember, valueType);
+ final keyTypeInfo = KeyInMapTypeInformation(
+ _abstractValueDomain, currentMember, simplifiedKeyType);
+ final valueTypeInfo = ValueInMapTypeInformation(
+ _abstractValueDomain, currentMember, simplifiedValueType);
allocatedTypes.add(keyTypeInfo);
allocatedTypes.add(valueTypeInfo);
@@ -577,7 +498,7 @@
MapTypeInformation(currentMember, mask, keyTypeInfo, valueTypeInfo);
for (int i = 0; i < keyTypes.length; ++i) {
- TypeInformation newType = map.addEntryInput(
+ final newType = map.addEntryInput(
_abstractValueDomain, keyTypes[i], valueTypes[i], true);
if (newType != null) allocatedTypes.add(newType);
}
@@ -610,7 +531,7 @@
}
PhiElementTypeInformation _addPhi(
- ir.Node node, Local variable, TypeInformation inputType, bool isTry) {
+ ir.Node? node, Local? variable, TypeInformation inputType, bool isTry) {
PhiElementTypeInformation result = PhiElementTypeInformation(
_abstractValueDomain, currentMember, node, variable,
isTry: isTry);
@@ -622,8 +543,8 @@
/// Returns a new type for holding the potential types of [element].
/// [inputType] is the first incoming type of the phi.
PhiElementTypeInformation allocatePhi(
- ir.Node node, Local variable, TypeInformation inputType,
- {bool isTry}) {
+ ir.Node? node, Local? variable, TypeInformation inputType,
+ {required bool isTry}) {
assert(strategy.checkPhiNode(node));
// Check if [inputType] is a phi for a local updated in
// the try/catch block [node]. If it is, no need to allocate a new
@@ -643,7 +564,7 @@
/// from other merging uses.
PhiElementTypeInformation allocateLoopPhi(
ir.Node node, Local variable, TypeInformation inputType,
- {bool isTry}) {
+ {required bool isTry}) {
assert(strategy.checkLoopPhiNode(node));
return _addPhi(node, variable, inputType, isTry);
}
@@ -653,14 +574,14 @@
/// implementation of this method could just return that incoming
/// input type.
TypeInformation simplifyPhi(
- ir.Node node, Local variable, PhiElementTypeInformation phiType) {
+ ir.Node? node, Local? variable, PhiElementTypeInformation phiType) {
assert(phiType.branchNode == node);
if (phiType.inputs.length == 1) return phiType.inputs.first;
return phiType;
}
/// Adds [newType] as an input of [phiType].
- PhiElementTypeInformation addPhiInput(Local variable,
+ PhiElementTypeInformation addPhiInput(Local? variable,
PhiElementTypeInformation phiType, TypeInformation newType) {
phiType.addInput(newType);
return phiType;
@@ -697,7 +618,7 @@
list.add(mask);
}
- AbstractValue newType = null;
+ AbstractValue? newType;
for (AbstractValue mask in list) {
newType =
newType == null ? mask : _abstractValueDomain.union(newType, mask);
diff --git a/pkg/compiler/test/analyses/dart2js_allowed.json b/pkg/compiler/test/analyses/dart2js_allowed.json
index 107ef15..746d0ef61 100644
--- a/pkg/compiler/test/analyses/dart2js_allowed.json
+++ b/pkg/compiler/test/analyses/dart2js_allowed.json
@@ -27,15 +27,6 @@
"Dynamic access of 'memberContext'.": 1,
"Dynamic access of 'name'.": 1
},
- "pkg/compiler/lib/src/inferrer/locals_handler.dart": {
- "Dynamic access of 'length'.": 2,
- "Dynamic access of 'named'.": 2,
- "Dynamic access of 'positional'.": 2,
- "Dynamic invocation of '[]'.": 2
- },
- "pkg/compiler/lib/src/inferrer/type_graph_nodes.dart": {
- "Dynamic access of 'type'.": 4
- },
"pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart": {
"Dynamic access of 'forwardTo'.": 1,
"Dynamic access of 'isForwarding'.": 1