From ccd063bda58652622bb73d4e0afad376a04ef924 Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Tue, 27 Jul 2021 17:50:47 +0000 Subject: [PATCH] Migrate pkg/vm to null safety, part 3 TEST=ci Issue: https://github.com/dart-lang/sdk/issues/46620 Change-Id: I1ab793eec6ffd7e01cee1e6641138e96a4f4d9fc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/207864 Commit-Queue: Alexander Markov Reviewed-by: Martin Kustermann --- .../transformations/type_flow/analysis.dart | 274 ++++----- .../lib/transformations/type_flow/calls.dart | 19 +- .../type_flow/native_code.dart | 49 +- .../type_flow/protobuf_handler.dart | 34 +- .../type_flow/signature_shaking.dart | 78 +-- .../transformations/type_flow/summary.dart | 146 +++-- .../type_flow/summary_collector.dart | 548 +++++++++--------- .../type_flow/table_selector_assigner.dart | 21 +- .../type_flow/transformer.dart | 298 +++++----- .../lib/transformations/type_flow/types.dart | 128 ++-- .../type_flow/unboxing_info.dart | 20 +- .../lib/transformations/type_flow/utils.dart | 12 +- pkg/vm/pubspec.yaml | 1 + .../type_flow/summary_collector_test.dart | 4 +- 14 files changed, 795 insertions(+), 837 deletions(-) diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart index 83c9a500b10..75eff47e919 100644 --- a/pkg/vm/lib/transformations/type_flow/analysis.dart +++ b/pkg/vm/lib/transformations/type_flow/analysis.dart @@ -2,10 +2,7 @@ // 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.9 - /// Global type flow analysis. -library kernel.transformations.analysis; import 'dart:collection'; import 'dart:core' hide Type; @@ -51,24 +48,28 @@ import '../pragma.dart'; /// Maintains set of dependent invocations. class _DependencyTracker { - Set<_Invocation> _dependentInvocations; + Set<_Invocation>? _dependentInvocations; void addDependentInvocation(_Invocation invocation) { if (!identical(invocation, this)) { - _dependentInvocations ??= new Set<_Invocation>(); - _dependentInvocations.add(invocation); + var dependentInvocations = _dependentInvocations; + if (dependentInvocations == null) { + _dependentInvocations = dependentInvocations = Set<_Invocation>(); + } + dependentInvocations.add(invocation); } } void invalidateDependentInvocations(_WorkList workList) { - if (_dependentInvocations != null) { + final dependentInvocations = _dependentInvocations; + if (dependentInvocations != null) { if (kPrintTrace) { tracePrint(' - CHANGED: $this'); - for (var di in _dependentInvocations) { + for (var di in dependentInvocations) { tracePrint(' - invalidating $di'); } } - _dependentInvocations.forEach(workList.invalidateInvocation); + dependentInvocations.forEach(workList.invalidateInvocation); } } } @@ -83,12 +84,12 @@ abstract class _Invocation extends _DependencyTracker final Selector selector; final Args args; - Type result; + Type? result; /// Result of the invocation calculated before invocation was invalidated. /// Used to check if the re-analysis of the invocation yields the same /// result or not (to avoid invalidation of callers if result hasn't changed). - Type invalidatedResult; + Type? invalidatedResult; /// Number of times result of this invocation was invalidated. int invalidationCounter = 0; @@ -108,7 +109,7 @@ abstract class _Invocation extends _DependencyTracker /// Returns result of this invocation if its available without /// further analysis, or `null` if it's not available. /// Used for recursive calls while this invocation is being processed. - Type get resultForRecursiveInvocation => result; + Type? get resultForRecursiveInvocation => result; /// Use [type] as a current computed result of this invocation. /// If this invocation was invalidated, and the invalidated result is @@ -116,7 +117,6 @@ abstract class _Invocation extends _DependencyTracker /// Result type may be saturated if this invocation was invalidated /// too many times. void setResult(TypeFlowAnalysis typeFlowAnalysis, Type type) { - assert(type != null); result = type; if (invalidatedResult != null) { @@ -132,8 +132,8 @@ abstract class _Invocation extends _DependencyTracker // the analysis, result is saturated after invocation is invalidated // at least [_Invocation.invalidationLimit] times. if (invalidationCounter > _Invocation.invalidationLimit) { - result = - result.union(invalidatedResult, typeFlowAnalysis.hierarchyCache); + result = result! + .union(invalidatedResult!, typeFlowAnalysis.hierarchyCache); } } invalidatedResult = null; @@ -192,11 +192,12 @@ class _DirectInvocation extends _Invocation { // they could fail bounds checks. // // TODO(sjindel): Use [TypeCheck] to avoid bounds checks. - if (selector.member.function != null) { - typeChecksNeeded = selector.member.function.typeParameters - .any((t) => t.isGenericCovariantImpl); + final function = selector.member.function; + if (function != null) { + typeChecksNeeded = + function.typeParameters.any((t) => t.isGenericCovariantImpl); } else { - Field field = selector.member; + Field field = selector.member as Field; if (selector.callKind == CallKind.PropertySet) { // TODO(dartbug.com/40615): Use TFA results to improve this criterion. typeChecksNeeded = field.isGenericCovariantImpl; @@ -277,13 +278,10 @@ class _DirectInvocation extends _Invocation { fieldValue.isInitialized = true; return const EmptyType(); } - - // Make dartanalyzer happy. - throw 'Unexpected call kind ${selector.callKind}'; } Type _processFunction(TypeFlowAnalysis typeFlowAnalysis) { - final Member member = selector.member; + final Member member = selector.member!; if (selector.memberAgreesToCallKind(member)) { if (_argumentsValid()) { final summary = typeFlowAnalysis.getSummary(member); @@ -326,13 +324,12 @@ class _DirectInvocation extends _Invocation { } bool _argumentsValid() { - final function = selector.member.function; - assert(function != null); - + final member = selector.member!; + final function = member.function!; final int positionalArguments = args.positionalCount; - final int firstParamIndex = numTypeParams(selector.member) + - (hasReceiverArg(selector.member) ? 1 : 0); + final int firstParamIndex = + numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0); final int requiredParameters = firstParamIndex + function.requiredParameterCount; if (positionalArguments < requiredParameters) { @@ -361,9 +358,9 @@ class _DirectInvocation extends _Invocation { class _DispatchableInvocation extends _Invocation { bool _isPolymorphic = false; - Set _callSites; // Populated only if not polymorphic. - Member _monomorphicTarget; - _DirectInvocation _monomorphicDirectInvocation; + Set? _callSites; // Populated only if not polymorphic. + Member? _monomorphicTarget; + _DirectInvocation? _monomorphicDirectInvocation; @override set typeChecksNeeded(bool value) { @@ -434,7 +431,8 @@ class _DispatchableInvocation extends _Invocation { if (!_isPolymorphic) { assert(target == _monomorphicTarget); - _monomorphicDirectInvocation = directInvocation; + _monomorphicDirectInvocation = + directInvocation as _DirectInvocation; } type = typeFlowAnalysis.workList.processInvocation(directInvocation); @@ -486,13 +484,13 @@ class _DispatchableInvocation extends _Invocation { final bool isNullableReceiver = receiver is NullableType; if (isNullableReceiver) { - receiver = (receiver as NullableType).baseType; + receiver = receiver.baseType; assert(receiver is! NullableType); } if (selector is InterfaceSelector) { final staticReceiverType = new ConeType(typeFlowAnalysis.hierarchyCache - .getTFClass(selector.member.enclosingClass)); + .getTFClass(selector.member!.enclosingClass!)); receiver = receiver.intersection( staticReceiverType, typeFlowAnalysis.hierarchyCache); assert(receiver is! NullableType); @@ -507,7 +505,7 @@ class _DispatchableInvocation extends _Invocation { // invocation to the receiver class. A new allocated class discovered // in the receiver cone will invalidate this invocation. receiver = typeFlowAnalysis.hierarchyCache - .specializeTypeCone((receiver as ConeType).cls, allowWideCone: false); + .specializeTypeCone(receiver.cls, allowWideCone: false); } assert(targets.isEmpty); @@ -535,7 +533,7 @@ class _DispatchableInvocation extends _Invocation { Class nullClass = typeFlowAnalysis.environment.coreTypes.deprecatedNullClass; - Member target = typeFlowAnalysis.hierarchyCache.hierarchy + Member? target = typeFlowAnalysis.hierarchyCache.hierarchy .getDispatchTarget(nullClass, selector.name, setter: selector.isSetter); if (target != null) { @@ -552,7 +550,7 @@ class _DispatchableInvocation extends _Invocation { TypeFlowAnalysis typeFlowAnalysis) { final TFClass cls = receiver.cls; - Member target = + Member? target = (cls as _TFClassImpl).getDispatchTarget(selector, typeFlowAnalysis); if (target != null) { @@ -647,8 +645,9 @@ class _DispatchableInvocation extends _Invocation { if (_isPolymorphic) { callSite.setPolymorphic(); } else { - if (_monomorphicTarget != null) { - callSite.addTarget(_monomorphicTarget); + final monomorphicTarget = _monomorphicTarget; + if (monomorphicTarget != null) { + callSite.addTarget(monomorphicTarget); } } @@ -660,18 +659,20 @@ class _DispatchableInvocation extends _Invocation { /// Notify call sites monitoring this invocation about changes in /// polymorphism of this invocation. void _notifyCallSites() { - if (_callSites != null) { - _callSites.forEach(_notifyCallSite); + final callSites = _callSites; + if (callSites != null) { + callSites.forEach(_notifyCallSite); } } @override - Type get resultForRecursiveInvocation { + Type? get resultForRecursiveInvocation { if (result != null) { return result; } - if (_monomorphicDirectInvocation != null) { - return _monomorphicDirectInvocation.resultForRecursiveInvocation; + final monomorphicDirectInvocation = _monomorphicDirectInvocation; + if (monomorphicDirectInvocation != null) { + return monomorphicDirectInvocation.resultForRecursiveInvocation; } return null; } @@ -683,30 +684,30 @@ class _DispatchableInvocation extends _Invocation { /// 1) Add 1..N concrete types ordered by classId OR add 1 arbitrary type. /// 2) Make type nullable. class _ReceiverTypeBuilder { - Type _type; - List _list; + Type? _type; + List? _list; bool _nullable = false; /// Appends a ConcreteType. May be called multiple times. /// Should not be used in conjunction with [addType]. void addConcreteType(ConcreteType type) { - if (_list == null) { - if (_type == null) { + final list = _list; + if (list == null) { + final Type? t = _type; + if (t == null) { _type = type; return; } + final ct = t as ConcreteType; - assert(_type is ConcreteType); - assert(_type != type); - - _list = []; - _list.add(_type); - + assert(ct != type); + assert(ct.cls.id < type.cls.id); + _list = [ct, type]; _type = null; + } else { + assert(list.last.cls.id < type.cls.id); + list.add(type); } - - assert(_list.last.cls.id < type.cls.id); - _list.add(type); } /// Appends an arbitrary Type. May be called only once. @@ -723,12 +724,13 @@ class _ReceiverTypeBuilder { /// Returns union of added types. Type toType() { - Type t = _type; + Type? t = _type; if (t == null) { - if (_list == null) { + final list = _list; + if (list == null) { t = const EmptyType(); } else { - t = new SetType(_list); + t = SetType(list); } } else { assert(_list == null); @@ -753,7 +755,7 @@ class _SelectorApproximation { static const int maxInvocationsPerSelector = 5000; int count = 0; - _Invocation approximation; + _Invocation? approximation; } /// Maintains ([Selector], [Args]) => [_Invocation] cache. @@ -771,7 +773,7 @@ class _InvocationsCache { _Invocation invocation = (selector is DirectSelector) ? new _DirectInvocation(selector, args) : new _DispatchableInvocation(selector, args); - _Invocation result = _invocations.lookup(invocation); + _Invocation? result = _invocations.lookup(invocation); if (result != null) { return result; } @@ -784,14 +786,16 @@ class _InvocationsCache { final sa = (_approximations[selector] ??= new _SelectorApproximation()); if (sa.count >= _SelectorApproximation.maxInvocationsPerSelector) { - if (sa.approximation == null) { + _Invocation? approximation = sa.approximation; + if (approximation == null) { final rawArgs = _typeFlowAnalysis.summaryCollector.rawArguments(selector); - sa.approximation = new _DispatchableInvocation(selector, rawArgs); + sa.approximation = + approximation = _DispatchableInvocation(selector, rawArgs); Statistics.approximateInvocationsCreated++; } Statistics.approximateInvocationsUsed++; - return sa.approximation; + return approximation; } ++sa.count; @@ -809,8 +813,8 @@ class _InvocationsCache { class _FieldValue extends _DependencyTracker { final Field field; final Type staticType; - final Summary typeGuardSummary; - Type value; + final Summary? typeGuardSummary; + Type value = const EmptyType(); /// Flag indicating if field initializer was executed. bool isInitialized = false; @@ -825,8 +829,6 @@ class _FieldValue extends _DependencyTracker { : staticType = typesBuilder.fromStaticType(field.type, true) { if (field.initializer == null && _isDefaultValueOfFieldObservable()) { value = new Type.nullable(const EmptyType()); - } else { - value = const EmptyType(); } } @@ -839,8 +841,7 @@ class _FieldValue extends _DependencyTracker { return true; } - final enclosingClass = field.enclosingClass; - assert(enclosingClass != null); + final enclosingClass = field.enclosingClass!; // Default value is not observable if every generative constructor // is redirecting or initializes the field. @@ -856,10 +857,11 @@ class _FieldValue extends _DependencyTracker { }); } - void ensureInitialized(TypeFlowAnalysis typeFlowAnalysis, Type receiverType) { + void ensureInitialized( + TypeFlowAnalysis typeFlowAnalysis, Type? receiverType) { if (field.initializer != null) { assert(field.isStatic == (receiverType == null)); - final args = !field.isStatic ? [receiverType] : const []; + final args = !field.isStatic ? [receiverType!] : const []; final initializerInvocation = typeFlowAnalysis._invocationsCache .getInvocation( new DirectSelector(field, callKind: CallKind.FieldInitializer), @@ -870,17 +872,18 @@ class _FieldValue extends _DependencyTracker { } } - Type getValue(TypeFlowAnalysis typeFlowAnalysis, Type receiverType) { + Type getValue(TypeFlowAnalysis typeFlowAnalysis, Type? receiverType) { ensureInitialized(typeFlowAnalysis, receiverType); addDependentInvocation(typeFlowAnalysis.currentInvocation); + final typeGuardSummary = this.typeGuardSummary; return (typeGuardSummary != null) - ? typeGuardSummary.apply(Args([receiverType, value]), + ? typeGuardSummary.apply(Args([receiverType!, value]), typeFlowAnalysis.hierarchyCache, typeFlowAnalysis) : value; } void setValue( - Type newValue, TypeFlowAnalysis typeFlowAnalysis, Type receiverType) { + Type newValue, TypeFlowAnalysis typeFlowAnalysis, Type? receiverType) { // Make sure type cones are specialized before putting them into field // value, in order to ensure that dependency is established between // cone's base type and corresponding field setter. @@ -907,10 +910,11 @@ class _FieldValue extends _DependencyTracker { // final hierarchy = typeFlowAnalysis.hierarchyCache; // TODO(sjindel/tfa): Perform narrowing inside 'TypeCheck'. + final typeGuardSummary = this.typeGuardSummary; final narrowedNewValue = typeGuardSummary != null ? typeGuardSummary - .apply( - new Args([receiverType, newValue]), hierarchy, typeFlowAnalysis) + .apply(new Args([receiverType!, newValue]), hierarchy, + typeFlowAnalysis) .intersection(staticType, hierarchy) : newValue.specialize(hierarchy).intersection(staticType, hierarchy); Type newType = @@ -952,28 +956,26 @@ class _TFClassImpl extends TFClass { /// Flag indicating if this class has a noSuchMethod() method not inherited /// from Object. /// Lazy initialized by ClassHierarchyCache.hasNonTrivialNoSuchMethod(). - bool hasNonTrivialNoSuchMethod; + bool? hasNonTrivialNoSuchMethod; _TFClassImpl(int id, Class classNode, this.supertypes) : super(id, classNode) { supertypes.add(this); } - ConcreteType _concreteType; - ConcreteType get concreteType => - _concreteType ??= new ConcreteType(this, null); + late final ConcreteType concreteType = ConcreteType(this, null); - Type _specializedConeType; + Type? _specializedConeType; Type get specializedConeType => _specializedConeType ??= _calculateConeTypeSpecialization(); bool get hasWideCone => _allocatedSubtypes.length > maxAllocatedTypesInSetSpecializations; - WideConeType _wideConeType; + late final WideConeType _wideConeType = WideConeType(this); WideConeType get wideConeType { assert(hasWideCone); - return _wideConeType ??= new WideConeType(this); + return _wideConeType; } Type _calculateConeTypeSpecialization() { @@ -999,14 +1001,16 @@ class _TFClassImpl extends TFClass { _specializedConeType = null; // Reset cached specialization. } - Member getDispatchTarget( + Member? getDispatchTarget( Selector selector, TypeFlowAnalysis typeFlowAnalysis) { - Member target = _dispatchTargets[selector]; + Member? target = _dispatchTargets[selector]; if (target == null) { target = typeFlowAnalysis.hierarchyCache.hierarchy.getDispatchTarget( classNode, selector.name, setter: selector.isSetter); - _dispatchTargets[selector] = target; + if (target != null) { + _dispatchTargets[selector] = target; + } } return target; } @@ -1021,10 +1025,11 @@ class GenericInterfacesInfoImpl implements GenericInterfacesInfo { final cachedFlattenedTypeArgs = >{}; final cachedFlattenedTypeArgsForNonGeneric = >{}; - RuntimeTypeTranslatorImpl closedTypeTranslator; + late final RuntimeTypeTranslatorImpl closedTypeTranslator; - GenericInterfacesInfoImpl(this.hierarchy) { - closedTypeTranslator = RuntimeTypeTranslatorImpl.forClosedTypes(this); + GenericInterfacesInfoImpl(CoreTypes coreTypes, this.hierarchy) { + closedTypeTranslator = + RuntimeTypeTranslatorImpl.forClosedTypes(coreTypes, this); } List flattenedTypeArgumentsFor(Class klass, {bool useCache: true}) { @@ -1049,7 +1054,7 @@ class GenericInterfacesInfoImpl implements GenericInterfacesInfo { if (klass == iface) return 0; final pair = new SubtypePair(klass, iface); - int offset = supertypeOffsetsCache[pair]; + int? offset = supertypeOffsetsCache[pair]; if (offset != null) return offset; @@ -1064,16 +1069,16 @@ class GenericInterfacesInfoImpl implements GenericInterfacesInfo { } List flattenedTypeArgumentsForNonGeneric(Class klass) { - List result = cachedFlattenedTypeArgsForNonGeneric[klass]; + List? result = cachedFlattenedTypeArgsForNonGeneric[klass]; if (result != null) return result; List flattenedTypeArgs = flattenedTypeArgumentsFor(klass, useCache: false); - result = new List.filled(flattenedTypeArgs.length, null); - for (int i = 0; i < flattenedTypeArgs.length; ++i) { - final translated = closedTypeTranslator.translate(flattenedTypeArgs[i]); + result = []; + for (DartType arg in flattenedTypeArgs) { + final translated = closedTypeTranslator.translate(arg); assert(translated is RuntimeType || translated is UnknownType); - result[i] = translated; + result.add(translated as Type); } cachedFlattenedTypeArgsForNonGeneric[klass] = result; return result; @@ -1108,10 +1113,8 @@ class _ClassHierarchyCache extends TypeHierarchy { _ClassHierarchyCache(this._typeFlowAnalysis, this.hierarchy, this.genericInterfacesInfo, this.environment, bool nullSafety) : objectNoSuchMethod = hierarchy.getDispatchTarget( - environment.coreTypes.objectClass, noSuchMethodName), - super(environment.coreTypes, nullSafety) { - assert(objectNoSuchMethod != null); - } + environment.coreTypes.objectClass, noSuchMethodName)!, + super(environment.coreTypes, nullSafety); @override _TFClassImpl getTFClass(Class c) { @@ -1198,10 +1201,13 @@ class _ClassHierarchyCache extends TypeHierarchy { bool hasNonTrivialNoSuchMethod(TFClass c) { final classImpl = c as _TFClassImpl; - classImpl.hasNonTrivialNoSuchMethod ??= - (hierarchy.getDispatchTarget(c.classNode, noSuchMethodName) != - objectNoSuchMethod); - return classImpl.hasNonTrivialNoSuchMethod; + bool? value = classImpl.hasNonTrivialNoSuchMethod; + if (value == null) { + classImpl.hasNonTrivialNoSuchMethod = value = + (hierarchy.getDispatchTarget(c.classNode, noSuchMethodName) != + objectNoSuchMethod); + } + return value; } _DynamicTargetSet getDynamicTargetSet(DynamicSelector selector) { @@ -1294,10 +1300,11 @@ class _WorkList { } bool invalidateProtobufFields() { - if (_typeFlowAnalysis.protobufHandler == null) { + final protobufHandler = _typeFlowAnalysis.protobufHandler; + if (protobufHandler == null) { return false; } - final fields = _typeFlowAnalysis.protobufHandler.getInvalidatedFields(); + final fields = protobufHandler.getInvalidatedFields(); if (fields.isEmpty) { return false; } @@ -1305,7 +1312,7 @@ class _WorkList { for (var field in fields) { assert(field.isStatic); // Reset summary in order to rebuild it. - _typeFlowAnalysis._summaries[field] = null; + _typeFlowAnalysis._summaries.remove(field); // Invalidate (and enqueue) field initializer invocation. final initializerInvocation = _typeFlowAnalysis._invocationsCache .getInvocation( @@ -1328,10 +1335,11 @@ class _WorkList { } Type processInvocation(_Invocation invocation) { - if (invocation.result != null) { + Type? result = invocation.result; + if (result != null) { // Already processed. Statistics.usedCachedResultsOfInvocations++; - return invocation.result; + return result; } // Test if tracing is enabled to avoid expensive message formatting. @@ -1374,18 +1382,18 @@ class _WorkList { -1); } processing.remove(invocation); - return invocation.invalidatedResult; + return invocation.invalidatedResult!; } callStack.add(invocation); pending.remove(invocation); - Type result = invocation.process(_typeFlowAnalysis); + result = invocation.process(_typeFlowAnalysis); invocation.setResult(_typeFlowAnalysis, result); // setResult may saturate result to ensure convergence. - result = invocation.result; + result = invocation.result!; // Invocation is still pending - it was invalidated while being processed. // Move result to invalidatedResult. @@ -1434,12 +1442,12 @@ class TypeFlowAnalysis implements EntryPointsListener, CallHandler { final TypeEnvironment environment; final LibraryIndex libraryIndex; final PragmaAnnotationParser annotationMatcher; - final ProtobufHandler protobufHandler; - NativeCodeOracle nativeCodeOracle; - _ClassHierarchyCache hierarchyCache; - SummaryCollector summaryCollector; - _InvocationsCache _invocationsCache; - _WorkList workList; + final ProtobufHandler? protobufHandler; + late NativeCodeOracle nativeCodeOracle; + late _ClassHierarchyCache hierarchyCache; + late SummaryCollector summaryCollector; + late _InvocationsCache _invocationsCache; + late _WorkList workList; GenericInterfacesInfo _genericInterfacesInfo; final Map _summaries = {}; @@ -1459,7 +1467,7 @@ class TypeFlowAnalysis implements EntryPointsListener, CallHandler { this.environment, this.libraryIndex, this.protobufHandler, - PragmaAnnotationParser matcher) + PragmaAnnotationParser? matcher) : annotationMatcher = matcher ?? new ConstantPragmaAnnotationParser(coreTypes) { nativeCodeOracle = new NativeCodeOracle(libraryIndex, annotationMatcher); @@ -1488,9 +1496,9 @@ class TypeFlowAnalysis implements EntryPointsListener, CallHandler { } _FieldValue getFieldValue(Field field) { - _FieldValue fieldValue = _fieldValues[field]; + _FieldValue? fieldValue = _fieldValues[field]; if (fieldValue == null) { - Summary typeGuardSummary = null; + Summary? typeGuardSummary = null; if (field.isGenericCovariantImpl) { typeGuardSummary = summaryCollector.createSummary(field, fieldSummaryType: FieldSummaryType.kFieldGuard); @@ -1548,24 +1556,24 @@ class TypeFlowAnalysis implements EntryPointsListener, CallHandler { bool isClassAllocated(Class c) => hierarchyCache.allocatedClasses.contains(c); - Call callSite(TreeNode node) => summaryCollector.callSites[node]; + Call? callSite(TreeNode node) => summaryCollector.callSites[node]; - TypeCheck explicitCast(AsExpression cast) => + TypeCheck? explicitCast(AsExpression cast) => summaryCollector.explicitCasts[cast]; - TypeCheck isTest(IsExpression node) => summaryCollector.isTests[node]; + TypeCheck? isTest(IsExpression node) => summaryCollector.isTests[node]; - NarrowNotNull nullTest(TreeNode node) => summaryCollector.nullTests[node]; + NarrowNotNull? nullTest(TreeNode node) => summaryCollector.nullTests[node]; - Type fieldType(Field field) => _fieldValues[field]?.value; + Type? fieldType(Field field) => _fieldValues[field]?.value; - Args argumentTypes(Member member) => _summaries[member]?.argumentTypes; + Args? argumentTypes(Member member) => _summaries[member]?.argumentTypes; - Type argumentType(Member member, VariableDeclaration memberParam) { + Type? argumentType(Member member, VariableDeclaration memberParam) { return _summaries[member]?.argumentType(member, memberParam); } - List uncheckedParameters(Member member) => + List? uncheckedParameters(Member member) => _summaries[member]?.uncheckedParameters; bool isTearOffTaken(Member member) => _tearOffTaken.contains(member); @@ -1599,7 +1607,7 @@ class TypeFlowAnalysis implements EntryPointsListener, CallHandler { /// ---- Implementation of [CallHandler] interface. ---- @override - Type applyCall(Call callSite, Selector selector, Args args, + Type applyCall(Call? callSite, Selector selector, Args args, {bool isResultUsed: true, bool processImmediately: true}) { _Invocation invocation = _invocationsCache.getInvocation(selector, args); @@ -1629,7 +1637,7 @@ class TypeFlowAnalysis implements EntryPointsListener, CallHandler { workList.enqueueInvocation(invocation); } - return null; + return const EmptyType(); } } @@ -1680,7 +1688,7 @@ class TypeFlowAnalysis implements EntryPointsListener, CallHandler { } @override - void recordTearOff(Procedure target) { + void recordTearOff(Member target) { _tearOffTaken.add(target); } } diff --git a/pkg/vm/lib/transformations/type_flow/calls.dart b/pkg/vm/lib/transformations/type_flow/calls.dart index 060500a29c9..dd16279d343 100644 --- a/pkg/vm/lib/transformations/type_flow/calls.dart +++ b/pkg/vm/lib/transformations/type_flow/calls.dart @@ -2,10 +2,7 @@ // 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.9 - /// Declares classes which describe a call: selectors and arguments. -library vm.transformations.type_flow.calls; import 'dart:core' hide Type; @@ -30,10 +27,10 @@ abstract class Selector { Selector(this.callKind); /// Interface or concrete target, may be null. - Member get member; + Member? get member; /// Selector name. - Name get name => member.name; + Name get name => member!.name; bool get isSetter => (callKind == CallKind.PropertySet); @@ -46,6 +43,7 @@ abstract class Selector { /// Static approximation of Dart return type. DartType get staticReturnType { + final member = this.member; if (member == null) { return const DynamicType(); } @@ -61,7 +59,6 @@ abstract class Selector { case CallKind.SetFieldInConstructor: return const NeverType.nonNullable(); } - return null; } bool memberAgreesToCallKind(Member member) { @@ -79,7 +76,6 @@ abstract class Selector { case CallKind.SetFieldInConstructor: return member is Field; } - return false; } String get _callKindPrefix { @@ -94,7 +90,6 @@ abstract class Selector { case CallKind.FieldInitializer: return 'init '; } - return ''; } } @@ -169,7 +164,7 @@ class DynamicSelector extends Selector { DynamicSelector(CallKind callKind, this.name) : super(callKind); @override - Member get member => null; + Member? get member => null; @override int get hashCode => (super.hashCode ^ name.hashCode + 37) & kHashMask; @@ -189,7 +184,8 @@ class Args { final List values; final List names; - int _hashCode; + @override + late final int hashCode = _computeHashCode(); Args(this.values, {this.names = const []}) { assert(isSorted(names)); @@ -206,9 +202,6 @@ class Args { T get receiver => values[0]; - @override - int get hashCode => _hashCode ??= _computeHashCode(); - int _computeHashCode() { int hash = 1231; for (var v in values) { diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart index 7a5baf9c75b..061137995f5 100644 --- a/pkg/vm/lib/transformations/type_flow/native_code.dart +++ b/pkg/vm/lib/transformations/type_flow/native_code.dart @@ -2,10 +2,7 @@ // 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.9 - /// Handling of native code and entry points. -library vm.transformations.type_flow.native_code; import 'dart:core' hide Type; @@ -35,24 +32,21 @@ abstract class EntryPointsListener { /// Record the fact that given member is called from this. void recordMemberCalledViaThis(Member target); - /// Record the fact that given method is torn off. - void recordTearOff(Procedure target) {} + /// Record the fact that given member is torn off. + void recordTearOff(Member target) {} } class PragmaEntryPointsVisitor extends RecursiveVisitor { final EntryPointsListener entryPoints; final NativeCodeOracle nativeCodeOracle; final PragmaAnnotationParser matcher; - Class currentClass = null; PragmaEntryPointsVisitor( - this.entryPoints, this.nativeCodeOracle, this.matcher) { - assert(matcher != null); - } + this.entryPoints, this.nativeCodeOracle, this.matcher); - PragmaEntryPointType _annotationsDefineRoot(List annotations) { + PragmaEntryPointType? _annotationsDefineRoot(List annotations) { for (var annotation in annotations) { - ParsedPragma pragma = matcher.parsePragma(annotation); + ParsedPragma? pragma = matcher.parsePragma(annotation); if (pragma == null) continue; if (pragma is ParsedEntryPointPragma) return pragma.type; } @@ -72,7 +66,6 @@ class PragmaEntryPointsVisitor extends RecursiveVisitor { } nativeCodeOracle.addClassReferencedFromNativeCode(klass); } - currentClass = klass; klass.visitChildren(this); } @@ -88,8 +81,7 @@ class PragmaEntryPointsVisitor extends RecursiveVisitor { } Member target = proc; while (target is Procedure && target.isRedirectingFactory) { - target = getRedirectingFactoryBody(target).target; - assert(target != null); + target = getRedirectingFactoryBody(target)!.target!; assert( (target is Procedure && target.isFactory) || target is Constructor); } @@ -152,7 +144,7 @@ class PragmaEntryPointsVisitor extends RecursiveVisitor { } entryPoints .addRawCall(new DirectSelector(ctor, callKind: CallKind.Method)); - entryPoints.addAllocatedClass(currentClass); + entryPoints.addAllocatedClass(ctor.enclosingClass); nativeCodeOracle.setMemberReferencedFromNativeCode(ctor); } } @@ -201,9 +193,7 @@ class NativeCodeOracle { final Set _classesReferencedFromNativeCode = new Set(); final PragmaAnnotationParser _matcher; - NativeCodeOracle(this._libraryIndex, this._matcher) { - assert(_matcher != null); - } + NativeCodeOracle(this._libraryIndex, this._matcher); void addClassReferencedFromNativeCode(Class klass) { _classesReferencedFromNativeCode.add(klass); @@ -219,9 +209,9 @@ class NativeCodeOracle { bool isMemberReferencedFromNativeCode(Member member) => _membersReferencedFromNativeCode.contains(member); - PragmaRecognizedType recognizedType(Member member) { + PragmaRecognizedType? recognizedType(Member member) { for (var annotation in member.annotations) { - ParsedPragma pragma = _matcher.parsePragma(annotation); + ParsedPragma? pragma = _matcher.parsePragma(annotation); if (pragma is ParsedRecognized) { return pragma.type; } @@ -229,15 +219,16 @@ class NativeCodeOracle { return null; } - bool isRecognized(Member member, [List expectedTypes]) { - PragmaRecognizedType type = recognizedType(member); + bool isRecognized(Member member, + [List? expectedTypes]) { + PragmaRecognizedType? type = recognizedType(member); return type != null && (expectedTypes == null || expectedTypes.contains(type)); } bool hasDisableUnboxedParameters(Member member) { for (var annotation in member.annotations) { - ParsedPragma pragma = _matcher.parsePragma(annotation); + ParsedPragma? pragma = _matcher.parsePragma(annotation); if (pragma is ParsedDisableUnboxedParameters) { if (member.enclosingLibrary.importUri.scheme != "dart") { throw "ERROR: Cannot use @pragma(vm:disable-unboxed-parameters) outside core libraries."; @@ -255,11 +246,11 @@ class NativeCodeOracle { EntryPointsListener entryPointsListener, TypesBuilder typesBuilder, RuntimeTypeTranslator translator) { - TypeExpr returnType = null; - bool nullable = null; + TypeExpr? returnType = null; + bool? nullable = null; for (var annotation in member.annotations) { - ParsedPragma pragma = _matcher.parsePragma(annotation); + ParsedPragma? pragma = _matcher.parsePragma(annotation); if (pragma == null) continue; if (pragma is ParsedResultTypeByTypePragma || pragma is ParsedResultTypeByPathPragma || @@ -278,8 +269,8 @@ class NativeCodeOracle { returnType = entryPointsListener.addAllocatedClass(type.classNode); if (pragma.resultTypeUsesPassedTypeArguments) { returnType = translator.instantiateConcreteType( - returnType, - member.function.typeParameters + returnType as ConcreteType, + member.function!.typeParameters .map((t) => TypeParameterType( t, TypeParameterType.computeNullabilityFromBound(t))) .toList()); @@ -314,7 +305,7 @@ class NativeCodeOracle { return returnType; } else { return typesBuilder.fromStaticType( - member.function.returnType, nullable ?? true); + member.function!.returnType, nullable ?? true); } } } diff --git a/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart b/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart index a4b0bbcc474..c0175a48d7b 100644 --- a/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart +++ b/pkg/vm/lib/transformations/type_flow/protobuf_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.9 - import 'package:kernel/ast.dart'; import 'package:kernel/clone.dart' show CloneVisitorNotMembers; import 'package:kernel/core_types.dart' show CoreTypes; @@ -47,14 +45,14 @@ class ProtobufHandler { final Procedure _builderInfoAddMethod; // Type of BuilderInfo.add(). - FunctionType _typeOfBuilderInfoAddOfNull; + late FunctionType _typeOfBuilderInfoAddOfNull; final _messageClasses = {}; final _invalidatedClasses = <_MessageClass>{}; /// Creates [ProtobufHandler] instance for [component]. /// Returns null if protobuf library is not used. - static ProtobufHandler forComponent( + static ProtobufHandler? forComponent( Component component, CoreTypes coreTypes) { final libraryIndex = LibraryIndex(component, [protobufLibraryUri]); if (!libraryIndex.containsLibrary(protobufLibraryUri)) { @@ -68,12 +66,12 @@ class ProtobufHandler { libraryIndex.getClass(protobufLibraryUri, 'GeneratedMessage'), _tagNumberClass = libraryIndex.getClass(protobufLibraryUri, 'TagNumber'), - _tagNumberField = libraryIndex.getMember( - protobufLibraryUri, 'TagNumber', 'tagNumber'), + _tagNumberField = + libraryIndex.getField(protobufLibraryUri, 'TagNumber', 'tagNumber'), _builderInfoClass = libraryIndex.getClass(protobufLibraryUri, 'BuilderInfo'), - _builderInfoAddMethod = - libraryIndex.getMember(protobufLibraryUri, 'BuilderInfo', 'add') { + _builderInfoAddMethod = libraryIndex.getProcedure( + protobufLibraryUri, 'BuilderInfo', 'add') { final functionType = _builderInfoAddMethod.getterType as FunctionType; _typeOfBuilderInfoAddOfNull = Substitution.fromPairs( functionType.typeParameters, const [NullType()]) @@ -130,8 +128,9 @@ class ProtobufHandler { List getInvalidatedFields() { final fields = []; for (var cls in _invalidatedClasses) { - if (cls._metadataField != null) { - fields.add(cls._metadataField); + final field = cls._metadataField; + if (field != null) { + fields.add(field); } } _invalidatedClasses.clear(); @@ -143,14 +142,15 @@ class ProtobufHandler { ++Statistics.protobufMetadataInitializersUpdated; Statistics.protobufMetadataFieldsPruned -= cls.numberOfFieldsPruned; - final field = cls._metadataField; - if (cls._originalInitializer == null) { - cls._originalInitializer = field.initializer; + final field = cls._metadataField!; + Expression? originalInitializer = cls._originalInitializer; + if (originalInitializer == null) { + cls._originalInitializer = originalInitializer = field.initializer!; } final cloner = CloneVisitorNotMembers(); - field.initializer = cloner.clone(cls._originalInitializer)..parent = field; + field.initializer = cloner.clone(originalInitializer)..parent = field; final transformer = _MetadataTransformer(this, cls); - field.initializer.accept(transformer); + field.initializer!.accept(transformer); _invalidatedClasses.remove(cls); cls.numberOfFieldsPruned = transformer.numberOfFieldsPruned; @@ -168,8 +168,8 @@ class ProtobufHandler { } class _MessageClass { - Field _metadataField; - Expression _originalInitializer; + Field? _metadataField; + Expression? _originalInitializer; final _usedTags = {}; int numberOfFieldsPruned = 0; } diff --git a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart index a61e2229c56..5ae2e165b9b 100644 --- a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart +++ b/pkg/vm/lib/transformations/type_flow/signature_shaking.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.9 - import 'package:kernel/ast.dart'; import 'package:kernel/external_name.dart'; import 'package:kernel/type_environment.dart'; @@ -57,7 +55,7 @@ class SignatureShaker { SignatureShaker(this.typeFlowAnalysis, this.tableSelectorAssigner); - _ProcedureInfo _infoForMember(Member member) { + _ProcedureInfo? _infoForMember(Member member) { if (!(member is Procedure && (member.kind == ProcedureKind.Method || member.kind == ProcedureKind.Factory) || @@ -89,7 +87,7 @@ class SignatureShaker { } while (worklist.isNotEmpty) { _ParameterInfo param = worklist.removeLast(); - for (_ParameterInfo dependencyParam in param.useDependencies) { + for (_ParameterInfo dependencyParam in param.useDependencies!) { if (!dependencyParam.isRead) { dependencyParam.isRead = true; if (dependencyParam.useDependencies != null) { @@ -141,7 +139,7 @@ class _ProcedureInfo { return positional.any((param) => param.canBeEliminated || (param.isAlwaysPassed && - param.index >= function.requiredParameterCount)) || + param.index! >= function.requiredParameterCount)) || named.values .any((param) => param.canBeEliminated || param.isAlwaysPassed); } @@ -149,7 +147,7 @@ class _ProcedureInfo { class _ParameterInfo { final _ProcedureInfo info; - final int index; + final int? index; int passCount = 0; bool isRead = false; @@ -160,7 +158,7 @@ class _ParameterInfo { /// List of parameter variables which were passed as arguments via this /// parameter. When this parameter is considered used, all [useDependencies] /// parameters should be transitively marked as read. - List<_ParameterInfo> useDependencies = null; + List<_ParameterInfo>? useDependencies = null; _ParameterInfo(this.info, this.index); @@ -177,7 +175,7 @@ class _ParameterInfo { void observeParameter( Member member, VariableDeclaration param, SignatureShaker shaker) { - final Type type = shaker.typeFlowAnalysis.argumentType(member, param); + final Type? type = shaker.typeFlowAnalysis.argumentType(member, param); // A parameter is considered constant if the TFA has inferred it to have a // constant value in every implementation. The constant value inferred does @@ -214,19 +212,19 @@ class _Collect extends RecursiveVisitor { _Collect(this.shaker); void enterFunction(Member member) { - final _ProcedureInfo info = shaker._infoForMember(member); + final _ProcedureInfo? info = shaker._infoForMember(member); if (info == null) return; localParameters.clear(); useDependencies.clear(); - final FunctionNode fun = member.function; + final FunctionNode fun = member.function!; for (int i = 0; i < fun.positionalParameters.length; i++) { final VariableDeclaration param = fun.positionalParameters[i]; localParameters[param] = info.ensurePositional(i) ..observeParameter(member, param, shaker); } for (VariableDeclaration param in fun.namedParameters) { - localParameters[param] = info.ensureNamed(param.name) + localParameters[param] = info.ensureNamed(param.name!) ..observeParameter(member, param, shaker); } @@ -270,19 +268,22 @@ class _Collect extends RecursiveVisitor { void addUseDependency(Expression arg, _ParameterInfo param) { if (arg is VariableGet) { - _ParameterInfo localParam = localParameters[arg.variable]; + _ParameterInfo? localParam = localParameters[arg.variable]; if (localParam != null && !localParam.isUsed) { // This is a parameter passed as an argument. Mark it as a use // dependency. - param.useDependencies ??= []; - param.useDependencies.add(localParam); + var paramUseDependencies = param.useDependencies; + if (paramUseDependencies == null) { + param.useDependencies = paramUseDependencies = []; + } + paramUseDependencies.add(localParam); useDependencies.add(arg); } } } void collectCall(Member member, Arguments args) { - final _ProcedureInfo info = shaker._infoForMember(member); + final _ProcedureInfo? info = shaker._infoForMember(member); if (info == null) return; for (int i = 0; i < args.positional.length; i++) { @@ -306,7 +307,10 @@ class _Collect extends RecursiveVisitor { @override void visitSuperMethodInvocation(SuperMethodInvocation node) { - collectCall(node.interfaceTarget, node.arguments); + final interfaceTarget = node.interfaceTarget; + if (interfaceTarget != null) { + collectCall(interfaceTarget, node.arguments); + } super.visitSuperMethodInvocation(node); } @@ -338,7 +342,7 @@ class _Collect extends RecursiveVisitor { class _Transform extends RecursiveVisitor { final SignatureShaker shaker; - StaticTypeContext typeContext; + late StaticTypeContext typeContext; final Map eliminatedParams = {}; final Set unusedParams = {}; final List addedInitializers = []; @@ -349,16 +353,15 @@ class _Transform extends RecursiveVisitor { Member member, _ParameterInfo param, VariableDeclaration variable) { Constant value; if (param.isConstant) { - Type type = shaker.typeFlowAnalysis.argumentType(member, variable); + Type type = shaker.typeFlowAnalysis.argumentType(member, variable)!; if (type is ConcreteType) { - assert(type.constant != null); - value = type.constant; + value = type.constant!; } else { assert(type is NullableType && type.baseType is EmptyType); value = NullConstant(); } } else { - value = (variable.initializer as ConstantExpression)?.constant ?? + value = (variable.initializer as ConstantExpression?)?.constant ?? NullConstant(); } eliminatedParams[variable] = value; @@ -370,10 +373,10 @@ class _Transform extends RecursiveVisitor { eliminatedParams.clear(); unusedParams.clear(); - final _ProcedureInfo info = shaker._infoForMember(member); + final _ProcedureInfo? info = shaker._infoForMember(member); if (info == null || !info.eligible || info.callCount == 0) return; - final FunctionNode function = member.function; + final FunctionNode function = member.function!; if (!info.transformNeeded(function)) return; @@ -404,9 +407,9 @@ class _Transform extends RecursiveVisitor { // as required positional parameters, alphabetically by name. final List sortedNamed = function.namedParameters .toList() - ..sort((var1, var2) => var1.name.compareTo(var2.name)); + ..sort((var1, var2) => var1.name!.compareTo(var2.name!)); for (VariableDeclaration variable in sortedNamed) { - final _ParameterInfo param = info.named[variable.name]; + final _ParameterInfo param = info.named[variable.name!]!; if (param.isAlwaysPassed) { if (param.isUsed) { if (param.canBeEliminated) { @@ -451,7 +454,7 @@ class _Transform extends RecursiveVisitor { // 4. All named parameters that are not always passed and can't be // eliminated, as named parameters in alphabetical order. for (VariableDeclaration variable in sortedNamed) { - final _ParameterInfo param = info.named[variable.name]; + final _ParameterInfo param = info.named[variable.name!]!; if (!param.isAlwaysPassed) { if (param.isUsed) { if (param.canBeEliminated) { @@ -475,7 +478,7 @@ class _Transform extends RecursiveVisitor { @override void visitVariableGet(VariableGet node) { - Constant constantValue = eliminatedParams[node.variable]; + Constant? constantValue = eliminatedParams[node.variable]; if (constantValue != null) { node.replaceWith(ConstantExpression(constantValue)); } @@ -511,7 +514,7 @@ class _Transform extends RecursiveVisitor { void Function(Expression, _ParameterInfo) fun) { for (int i = args.named.length - 1; i >= 0; i--) { final NamedExpression namedExp = args.named[i]; - fun(namedExp.value, info.named[namedExp.name]); + fun(namedExp.value, info.named[namedExp.name]!); } for (int i = args.positional.length - 1; i >= 0; i--) { fun(args.positional[i], info.positional[i]); @@ -519,8 +522,8 @@ class _Transform extends RecursiveVisitor { } void transformCall( - Member target, TreeNode call, Expression receiver, Arguments args) { - final _ProcedureInfo info = shaker._infoForMember(target); + Member target, TreeNode call, Expression? receiver, Arguments args) { + final _ProcedureInfo? info = shaker._infoForMember(target); if (info == null || !info.eligible) return; bool transformNeeded = false; @@ -544,7 +547,7 @@ class _Transform extends RecursiveVisitor { Map hoisted = {}; if (hoistingNeeded) { if (call is Initializer) { - final Constructor constructor = call.parent; + final Constructor constructor = call.parent as Constructor; forEachArgumentRev(args, info, (Expression arg, _ParameterInfo param) { if (mayHaveOrSeeSideEffects(arg) && !isUnusedParam(arg)) { VariableDeclaration argVar = VariableDeclaration(null, @@ -557,8 +560,8 @@ class _Transform extends RecursiveVisitor { } }); } else { - final TreeNode parent = call.parent; - Expression current = call; + final TreeNode parent = call.parent!; + Expression current = call as Expression; forEachArgumentRev(args, info, (Expression arg, _ParameterInfo param) { if (mayHaveOrSeeSideEffects(arg) && !isUnusedParam(arg)) { VariableDeclaration argVar = VariableDeclaration(null, @@ -606,7 +609,7 @@ class _Transform extends RecursiveVisitor { final List sortedNamed = args.named.toList() ..sort((var1, var2) => var1.name.compareTo(var2.name)); for (NamedExpression arg in sortedNamed) { - final _ParameterInfo param = info.named[arg.name]; + final _ParameterInfo param = info.named[arg.name]!; if (param.isAlwaysPassed && !param.canBeEliminated) { positional.add(getMaybeHoistedArg(arg.value)); } @@ -625,7 +628,7 @@ class _Transform extends RecursiveVisitor { // eliminated, as named parameters in alphabetical order. // (Arguments are kept in original order.) for (NamedExpression arg in args.named) { - final _ParameterInfo param = info.named[arg.name]; + final _ParameterInfo param = info.named[arg.name]!; if (!param.isAlwaysPassed && !param.canBeEliminated) { arg.value = getMaybeHoistedArg(arg.value)..parent = arg; named.add(arg); @@ -644,7 +647,10 @@ class _Transform extends RecursiveVisitor { @override void visitSuperMethodInvocation(SuperMethodInvocation node) { super.visitSuperMethodInvocation(node); - transformCall(node.interfaceTarget, node, null, node.arguments); + final interfaceTarget = node.interfaceTarget; + if (interfaceTarget != null) { + transformCall(interfaceTarget, node, null, node.arguments); + } } @override diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart index dcae2df4576..fb18cec1bed 100644 --- a/pkg/vm/lib/transformations/type_flow/summary.dart +++ b/pkg/vm/lib/transformations/type_flow/summary.dart @@ -2,10 +2,7 @@ // 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.9 - /// Type flow summary of a member, function or initializer. -library vm.transformations.type_flow.summary; import 'dart:core' hide Type; @@ -18,7 +15,7 @@ import 'utils.dart'; abstract class CallHandler { Type applyCall(Call callSite, Selector selector, Args args, - {bool isResultUsed}); + {required bool isResultUsed}); void typeCheckTriggered(); void addAllocatedClass(Class c); } @@ -27,14 +24,10 @@ abstract class CallHandler { abstract class Statement extends TypeExpr { /// Index of this statement in the [Summary]. int index = -1; - Summary summary; + late Summary summary; @override - Type getComputedType(List types) { - final type = types[index]; - assert(type != null); - return type; - } + Type getComputedType(List types) => types[index]!; String get label => "t$index"; @@ -48,7 +41,7 @@ abstract class Statement extends TypeExpr { void accept(StatementVisitor visitor); /// Execute this statement and compute its resulting type. - Type apply(List computedTypes, TypeHierarchy typeHierarchy, + Type apply(List computedTypes, TypeHierarchy typeHierarchy, CallHandler callHandler); } @@ -74,9 +67,9 @@ class Parameter extends Statement { // [staticType] is null if no narrowing should be performed. This happens for // type parameters and for parameters whose type is narrowed by a [TypeCheck] // statement. - final Type staticTypeForNarrowing; + final Type? staticTypeForNarrowing; - Type defaultValue; + Type? defaultValue; Type _argumentType = const EmptyType(); Parameter(this.name, this.staticTypeForNarrowing); @@ -97,7 +90,7 @@ class Parameter extends Statement { } @override - Type apply(List computedTypes, TypeHierarchy typeHierarchy, + Type apply(List computedTypes, TypeHierarchy typeHierarchy, CallHandler callHandler) => throw 'Unable to apply _Parameter'; @@ -110,7 +103,7 @@ class Parameter extends Statement { } Type _observeNotPassed(TypeHierarchy typeHierarchy) { - final Type argType = defaultValue.specialize(typeHierarchy); + final Type argType = defaultValue!.specialize(typeHierarchy); _observeArgumentType(argType, typeHierarchy); return argType; } @@ -130,7 +123,7 @@ class Narrow extends Statement { String dump() => "$label = _Narrow ($arg to $type)"; @override - Type apply(List computedTypes, TypeHierarchy typeHierarchy, + Type apply(List computedTypes, TypeHierarchy typeHierarchy, CallHandler callHandler) => arg.getComputedType(computedTypes).intersection(type, typeHierarchy); } @@ -147,11 +140,11 @@ class NarrowNotNull extends Narrow { // Shared NarrowNotNull instances which are used when the outcome is // known at summary creation time. - static final NarrowNotNull alwaysNotNull = NarrowNotNull(null) + static final NarrowNotNull alwaysNotNull = NarrowNotNull(const EmptyType()) .._flags = canBeNotNullFlag; - static final NarrowNotNull alwaysNull = NarrowNotNull(null) + static final NarrowNotNull alwaysNull = NarrowNotNull(const EmptyType()) .._flags = canBeNullFlag; - static final NarrowNotNull unknown = NarrowNotNull(null) + static final NarrowNotNull unknown = NarrowNotNull(const EmptyType()) .._flags = canBeNullFlag | canBeNotNullFlag; bool get isAlwaysNull => (_flags & canBeNotNullFlag) == 0; @@ -173,14 +166,14 @@ class NarrowNotNull extends Narrow { } @override - Type apply(List computedTypes, TypeHierarchy typeHierarchy, + Type apply(List computedTypes, TypeHierarchy typeHierarchy, CallHandler callHandler) => handleArgument(arg.getComputedType(computedTypes)); } /// Joins values from multiple sources. Its type is a union of [values]. class Join extends Statement { - final String _name; + final String? _name; final DartType staticType; final List values = []; // TODO(alexmarkov): Set @@ -197,15 +190,14 @@ class Join extends Statement { " (${values.join(", ")})"; @override - Type apply(List computedTypes, TypeHierarchy typeHierarchy, + Type apply(List computedTypes, TypeHierarchy typeHierarchy, CallHandler callHandler) { - Type type = null; - assert(values.isNotEmpty); + Type? type = null; for (var value in values) { final valueType = value.getComputedType(computedTypes); type = type != null ? type.union(valueType, typeHierarchy) : valueType; } - return type; + return type!; } } @@ -222,7 +214,7 @@ class Use extends Statement { String dump() => "$label = _Use ($arg)"; @override - Type apply(List computedTypes, TypeHierarchy typeHierarchy, + Type apply(List computedTypes, TypeHierarchy typeHierarchy, CallHandler callHandler) => throw 'Use statements should be removed during summary normalization'; } @@ -231,7 +223,7 @@ class Use extends Statement { class Call extends Statement { final Selector selector; final Args args; - final Type staticResultType; + final Type? staticResultType; Call(this.selector, this.args, this.staticResultType, bool isInstanceCreation) { @@ -252,9 +244,10 @@ class Call extends Statement { String dump() => "$label${isResultUsed ? '*' : ''} = _Call $selector $args"; @override - Type apply(List computedTypes, TypeHierarchy typeHierarchy, + Type apply(List computedTypes, TypeHierarchy typeHierarchy, CallHandler callHandler) { - final List argTypes = new List.filled(args.values.length, null); + final List argTypes = + new List.filled(args.values.length, const EmptyType()); for (int i = 0; i < args.values.length; i++) { final Type type = args.values[i].getComputedType(computedTypes); if (type == const EmptyType()) { @@ -271,14 +264,15 @@ class Call extends Statement { callHandler .addAllocatedClass((argTypes[0] as ConcreteType).cls.classNode); } - final Stopwatch timer = kPrintTimings ? (new Stopwatch()..start()) : null; + final Stopwatch? timer = kPrintTimings ? (new Stopwatch()..start()) : null; Type result = callHandler.applyCall( this, selector, new Args(argTypes, names: args.names), isResultUsed: isResultUsed); - summary.calleeTime += kPrintTimings ? timer.elapsedMicroseconds : 0; + summary.calleeTime += kPrintTimings ? timer!.elapsedMicroseconds : 0; if (isInstanceCreation) { result = argTypes[0]; } else if (isResultUsed) { + final staticResultType = this.staticResultType; if (staticResultType != null) { result = result.intersection(staticResultType, typeHierarchy); } @@ -302,9 +296,9 @@ class Call extends Statement { static const int kReceiverMayBeInt = (1 << 6); static const int kInstanceCreation = (1 << 7); - Member _monomorphicTarget; + Member? _monomorphicTarget; - Member get monomorphicTarget => _monomorphicTarget; + Member? get monomorphicTarget => _monomorphicTarget; bool get isMonomorphic => (_flags & kMonomorphic) != 0; @@ -396,18 +390,19 @@ class Extract extends Statement { "/$paramIndex]${nullability.suffix})"; @override - Type apply(List computedTypes, TypeHierarchy typeHierarchy, + Type apply(List computedTypes, TypeHierarchy typeHierarchy, CallHandler callHandler) { Type argType = arg.getComputedType(computedTypes); - Type extractedType; + Type? extractedType; void extractType(ConcreteType c) { - if (c.typeArgs == null) { + final typeArgs = c.typeArgs; + if (typeArgs == null) { extractedType = const UnknownType(); } else { final interfaceOffset = typeHierarchy.genericInterfaceOffsetFor( c.cls.classNode, referenceClass); - final typeArg = c.typeArgs[interfaceOffset + paramIndex]; + final typeArg = typeArgs[interfaceOffset + paramIndex]; Type extracted = typeArg; if (typeArg is RuntimeType) { final argNullability = typeArg.nullability; @@ -472,16 +467,15 @@ class CreateConcreteType extends Statement { } @override - Type apply(List computedTypes, TypeHierarchy typeHierarchy, + Type apply(List computedTypes, TypeHierarchy typeHierarchy, CallHandler callHandler) { bool hasRuntimeType = false; - final types = new List.filled(flattenedTypeArgs.length, null); - for (int i = 0; i < types.length; ++i) { + final types = List.generate(flattenedTypeArgs.length, (int i) { final computed = flattenedTypeArgs[i].getComputedType(computedTypes); assert(computed is RuntimeType || computed is UnknownType); if (computed is RuntimeType) hasRuntimeType = true; - types[i] = computed; - } + return computed; + }); return new ConcreteType(cls, hasRuntimeType ? types : null); } } @@ -505,14 +499,13 @@ class CreateRuntimeType extends Statement { "${nullability.suffix})"; @override - Type apply(List computedTypes, TypeHierarchy typeHierarchy, + Type apply(List computedTypes, TypeHierarchy typeHierarchy, CallHandler callHandler) { - final types = new List.filled(flattenedTypeArgs.length, null); - for (int i = 0; i < types.length; ++i) { - final computed = flattenedTypeArgs[i].getComputedType(computedTypes); - assert(computed is RuntimeType || computed is UnknownType); + final types = []; + for (TypeExpr arg in flattenedTypeArgs) { + final computed = arg.getComputedType(computedTypes); if (computed is UnknownType) return const UnknownType(); - types[i] = computed; + types.add(computed as RuntimeType); } DartType dartType; if (klass == typeHierarchy.coreTypes.deprecatedFutureOrClass) { @@ -545,17 +538,15 @@ class TypeCheck extends Statement { // "unchecked" entrypoint. bool isTestedOnlyOnCheckedEntryPoint; - VariableDeclaration get parameter => - node is VariableDeclaration ? node : null; + bool get isParameterCheck => node is VariableDeclaration; + VariableDeclaration get parameterVariable => node as VariableDeclaration; bool alwaysPass = true; bool alwaysFail = true; - TypeCheck(this.arg, this.type, this.node, this.staticType, this.kind) { - assert(node != null); - isTestedOnlyOnCheckedEntryPoint = - parameter != null && !parameter.isCovariant; - } + TypeCheck(this.arg, this.type, this.node, this.staticType, this.kind) + : isTestedOnlyOnCheckedEntryPoint = + node is VariableDeclaration && !node.isCovariant; @override void accept(StatementVisitor visitor) => visitor.visitTypeCheck(this); @@ -568,7 +559,7 @@ class TypeCheck extends Statement { } @override - Type apply(List computedTypes, TypeHierarchy typeHierarchy, + Type apply(List computedTypes, TypeHierarchy typeHierarchy, CallHandler callHandler) { Type argType = arg.getComputedType(computedTypes); Type checkType = type.getComputedType(computedTypes); @@ -624,11 +615,11 @@ class Summary { int requiredParameterCount; List _statements = []; - TypeExpr result = null; - Type resultType = EmptyType(); + TypeExpr result = const EmptyType(); + Type resultType = const EmptyType(); // Analysis time of callees. Populated only if kPrintTimings. - int calleeTime; + int calleeTime = 0; Summary(this.name, {this.parameterCount: 0, @@ -658,7 +649,7 @@ class Summary { /// Apply this summary to the given arguments and return the resulting type. Type apply(Args arguments, TypeHierarchy typeHierarchy, CallHandler callHandler) { - final Stopwatch timer = kPrintTimings ? (new Stopwatch()..start()) : null; + final Stopwatch? timer = kPrintTimings ? (new Stopwatch()..start()) : null; final int oldCalleeTime = calleeTime; calleeTime = 0; final args = arguments.values; @@ -677,7 +668,7 @@ class Summary { // // The first `parameterCount` statements are Parameters. - List types = new List.filled(_statements.length, null); + List types = new List.filled(_statements.length, null); for (int i = 0; i < positionalArgCount; i++) { final Parameter param = _statements[i] as Parameter; @@ -687,9 +678,9 @@ class Summary { } final argType = args[i].specialize(typeHierarchy); param._observeArgumentType(argType, typeHierarchy); - if (param.staticTypeForNarrowing != null) { - types[i] = - argType.intersection(param.staticTypeForNarrowing, typeHierarchy); + final staticTypeForNarrowing = param.staticTypeForNarrowing; + if (staticTypeForNarrowing != null) { + types[i] = argType.intersection(staticTypeForNarrowing, typeHierarchy); } else { // TODO(sjindel/tfa): Narrowing is performed inside a [TypeCheck] later. types[i] = args[i]; @@ -710,9 +701,10 @@ class Summary { args[positionalArgCount + argIndex].specialize(typeHierarchy); argIndex++; param._observeArgumentType(argType, typeHierarchy); - if (param.staticTypeForNarrowing != null) { + final staticTypeForNarrowing = param.staticTypeForNarrowing; + if (staticTypeForNarrowing != null) { types[i] = - argType.intersection(param.staticTypeForNarrowing, typeHierarchy); + argType.intersection(staticTypeForNarrowing, typeHierarchy); } else { types[i] = argType; } @@ -741,7 +733,7 @@ class Summary { resultType = resultType.union(computedType, typeHierarchy); if (kPrintTimings) { - final dirtyTime = timer.elapsedMicroseconds; + final dirtyTime = timer!.elapsedMicroseconds; final pureTime = dirtyTime < calleeTime ? 0 : (dirtyTime - calleeTime); Statistics.numSummaryApplications.add(name); Statistics.dirtySummaryAnalysisTime.add(name, dirtyTime); @@ -753,9 +745,9 @@ class Summary { } Args get argumentTypes { - final argTypes = new List.filled(parameterCount, null); - final argNames = new List.filled( - parameterCount - positionalParameterCount, null); + final argTypes = new List.filled(parameterCount, const EmptyType()); + final argNames = + new List.filled(parameterCount - positionalParameterCount, ''); for (int i = 0; i < parameterCount; i++) { Parameter param = _statements[i] as Parameter; argTypes[i] = param.argumentType; @@ -769,7 +761,7 @@ class Summary { Type argumentType(Member member, VariableDeclaration memberParam) { final int firstParamIndex = numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0); - final positional = member.function.positionalParameters; + final positional = member.function!.positionalParameters; for (int i = 0; i < positional.length; i++) { if (positional[i] == memberParam) { final Parameter param = _statements[firstParamIndex + i] as Parameter; @@ -791,8 +783,8 @@ class Summary { for (Statement statement in _statements) { if (statement is TypeCheck && statement.alwaysPass && - statement.parameter != null) { - params.add(statement.parameter); + statement.isParameterCheck) { + params.add(statement.parameterVariable); } } return params; @@ -808,17 +800,17 @@ class Summary { (hasReceiverArg(member) ? 1 : 0) + numTypeParams(member); final Map paramsByName = {}; for (int i = implicit; i < parameterCount; i++) { - final Parameter param = statements[i]; + final Parameter param = statements[i] as Parameter; paramsByName[param.name] = param; } - FunctionNode function = member.function; + FunctionNode function = member.function!; statements.length = implicit; for (VariableDeclaration param in function.positionalParameters) { - statements.add(paramsByName[param.name]); + statements.add(paramsByName[param.name]!); } positionalParameterCount = statements.length; for (VariableDeclaration param in function.namedParameters) { - statements.add(paramsByName[param.name]); + statements.add(paramsByName[param.name]!); } parameterCount = statements.length; requiredParameterCount = implicit + function.requiredParameterCount; diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart index cd78792995e..d2157f75069 100644 --- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart +++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart @@ -2,10 +2,7 @@ // 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.9 - /// Creation of type flow summaries out of kernel AST. -library vm.transformations.type_flow.summary_collector; import 'dart:core' hide Type; @@ -14,6 +11,7 @@ import 'package:kernel/ast.dart' hide Statement, StatementVisitor; import 'package:kernel/ast.dart' as ast show Statement, StatementVisitor; import 'package:kernel/class_hierarchy.dart' show ClassHierarchy, ClosedWorldClassHierarchy; +import 'package:kernel/core_types.dart' show CoreTypes; import 'package:kernel/type_environment.dart' show StaticTypeContext, SubtypeCheckMode, TypeEnvironment; import 'package:kernel/type_algebra.dart' show Substitution; @@ -239,7 +237,7 @@ class _FallthroughDetector extends ast.StatementVisitor { // function and checks if control can fall through them or not. bool controlCanFallThrough(FunctionNode function) { - return function.body.accept(this); + return function.body!.accept(this); } @override @@ -285,11 +283,11 @@ class _FallthroughDetector extends ast.StatementVisitor { bool visitContinueSwitchStatement(ContinueSwitchStatement node) => false; @override - bool visitIfStatement(IfStatement node) => - node.then == null || - node.otherwise == null || - node.then.accept(this) || - node.otherwise.accept(this); + bool visitIfStatement(IfStatement node) { + final otherwise = node.otherwise; + if (otherwise == null) return true; + return node.then.accept(this) || otherwise.accept(this); + } @override bool visitReturnStatement(ReturnStatement node) => false; @@ -323,7 +321,7 @@ class _VariablesInfoCollector extends RecursiveVisitor { final List varDeclarations = []; /// Set of captured variables. - Set captured; + Set? captured; /// Set of variables which were modified for each loop, switch statement /// and try block statement. Doesn't include captured variables and @@ -334,10 +332,10 @@ class _VariablesInfoCollector extends RecursiveVisitor { int numVariablesAtFunctionEntry = 0; /// Active loops, switch statements and try blocks. - List activeStatements; + List? activeStatements; /// Number of variables at entry of active statements. - List numVariablesAtActiveStatements; + List? numVariablesAtActiveStatements; _VariablesInfoCollector(Member member) { member.accept(this); @@ -345,8 +343,10 @@ class _VariablesInfoCollector extends RecursiveVisitor { int get numVariables => varDeclarations.length; - bool isCaptured(VariableDeclaration variable) => - captured != null && captured.contains(variable); + bool isCaptured(VariableDeclaration variable) { + final captured = this.captured; + return captured != null && captured.contains(variable); + } Set getModifiedVariables(ast.Statement st) { return modifiedSets[st] ?? const {}; @@ -387,14 +387,15 @@ class _VariablesInfoCollector extends RecursiveVisitor { } void _useVariable(VariableDeclaration variable, bool isVarAssignment) { - final index = varIndex[variable]; + final index = varIndex[variable]!; if (_isDeclaredBefore(index, numVariablesAtFunctionEntry)) { _captureVariable(variable); return; } + final activeStatements = this.activeStatements; if (isVarAssignment && activeStatements != null) { for (int i = activeStatements.length - 1; i >= 0; --i) { - if (_isDeclaredBefore(index, numVariablesAtActiveStatements[i])) { + if (_isDeclaredBefore(index, numVariablesAtActiveStatements![i])) { final st = activeStatements[i]; (modifiedSets[st] ??= {}).add(index); } else { @@ -410,8 +411,8 @@ class _VariablesInfoCollector extends RecursiveVisitor { } void _endCollectingModifiedVariables() { - activeStatements.removeLast(); - numVariablesAtActiveStatements.removeLast(); + activeStatements!.removeLast(); + numVariablesAtActiveStatements!.removeLast(); } @override @@ -457,7 +458,7 @@ class _VariablesInfoCollector extends RecursiveVisitor { @override visitTryCatch(TryCatch node) { _startCollectingModifiedVariables(node); - node.body?.accept(this); + node.body.accept(this); _endCollectingModifiedVariables(); visitList(node.catches, this); } @@ -465,9 +466,9 @@ class _VariablesInfoCollector extends RecursiveVisitor { @override visitTryFinally(TryFinally node) { _startCollectingModifiedVariables(node); - node.body?.accept(this); + node.body.accept(this); _endCollectingModifiedVariables(); - node.finalizer?.accept(this); + node.finalizer.accept(this); } @override @@ -489,7 +490,7 @@ class _VariablesInfoCollector extends RecursiveVisitor { visitList(node.variables, this); _startCollectingModifiedVariables(node); node.condition?.accept(this); - node.body?.accept(this); + node.body.accept(this); visitList(node.updates, this); _endCollectingModifiedVariables(); } @@ -521,7 +522,7 @@ Iterable getSelectors(ClassHierarchy hierarchy, Class cls, enum FieldSummaryType { kFieldGuard, kInitializer } /// Create a type flow summary for a member from the kernel AST. -class SummaryCollector extends RecursiveResultVisitor { +class SummaryCollector extends RecursiveResultVisitor { final Target target; final TypeEnvironment _environment; final ClosedWorldClassHierarchy _hierarchy; @@ -529,7 +530,7 @@ class SummaryCollector extends RecursiveResultVisitor { final TypesBuilder _typesBuilder; final NativeCodeOracle _nativeCodeOracle; final GenericInterfacesInfo _genericInterfacesInfo; - final ProtobufHandler _protobufHandler; + final ProtobufHandler? _protobufHandler; final Map callSites = {}; final Map explicitCasts = @@ -540,13 +541,13 @@ class SummaryCollector extends RecursiveResultVisitor { final Set _nullMethodsAndGetters = {}; final Set _nullSetters = {}; - Summary _summary; - _VariablesInfoCollector _variablesInfo; + Summary _summary = Summary(''); + late _VariablesInfoCollector _variablesInfo; // Current value of each variable. May contain null if variable is not // declared yet, or EmptyType if current location is unreachable // (e.g. after return or throw). - List _variableValues; + List _variableValues = const []; // Contains Joins which accumulate all values of certain variables. // Used only when all variable values should be merged regardless of control @@ -558,30 +559,30 @@ class SummaryCollector extends RecursiveResultVisitor { // If _variableCells[i] != null, then all values are accumulated in the // _variableCells[i]. _variableValues[i] does not change and remains equal // to _variableCells[i]. - List _variableCells; + List _variableCells = const []; // Counts number of Joins inserted for each variable. Only used to set // readable names for such joins (foo_0, foo_1 etc.) - List _variableVersions; + List _variableVersions = const []; // State of variables after corresponding LabeledStatement. // Used to collect states from BreakStatements. - Map> _variableValuesAfterLabeledStatements; + Map>? _variableValuesAfterLabeledStatements; // Joins corresponding to variables on entry to switch cases. // Used to propagate state from ContinueSwitchStatement to a target case. - Map> _joinsAtSwitchCases; + Map>? _joinsAtSwitchCases; // Join which accumulates all return values. - Join _returnValue; + Join? _returnValue; - Parameter _receiver; - ConstantAllocationCollector constantAllocationCollector; - RuntimeTypeTranslatorImpl _translator; - StaticTypeContext _staticTypeContext; + Parameter? _receiver; + late ConstantAllocationCollector constantAllocationCollector; + late RuntimeTypeTranslatorImpl _translator; + StaticTypeContext? _staticTypeContext; // Currently only used for factory constructors. - Map _fnTypeVariables; + Map? _fnTypeVariables; SummaryCollector( this.target, @@ -592,7 +593,6 @@ class SummaryCollector extends RecursiveResultVisitor { this._nativeCodeOracle, this._genericInterfacesInfo, this._protobufHandler) { - assert(_genericInterfacesInfo != null); constantAllocationCollector = new ConstantAllocationCollector(this); _nullMethodsAndGetters.addAll(getSelectors( _hierarchy, _environment.coreTypes.deprecatedNullClass, @@ -615,8 +615,8 @@ class SummaryCollector extends RecursiveResultVisitor { _staticTypeContext = new StaticTypeContext(member, _environment); _variablesInfo = new _VariablesInfoCollector(member); _variableValues = - new List.filled(_variablesInfo.numVariables, null); - _variableCells = new List.filled(_variablesInfo.numVariables, null); + new List.filled(_variablesInfo.numVariables, null); + _variableCells = new List.filled(_variablesInfo.numVariables, null); _variableVersions = new List.filled(_variablesInfo.numVariables, 0); _variableValuesAfterLabeledStatements = null; _joinsAtSwitchCases = null; @@ -633,25 +633,24 @@ class SummaryCollector extends RecursiveResultVisitor { parameterCount: numArgs, positionalParameterCount: numArgs); // TODO(alexmarkov): subclass cone _receiver = _declareParameter("this", - _environment.coreTypes.legacyRawType(member.enclosingClass), null, + _environment.coreTypes.legacyRawType(member.enclosingClass!), null, isReceiver: true); } else { _summary = new Summary(summaryName); } - _translator = new RuntimeTypeTranslatorImpl( - this, _summary, _receiver, null, _genericInterfacesInfo); + _translator = new RuntimeTypeTranslatorImpl(_environment.coreTypes, + _summary, _receiver, null, _genericInterfacesInfo); if (fieldSummaryType == FieldSummaryType.kInitializer) { - assert(member.initializer != null); - _summary.result = _visit(member.initializer); + _summary.result = _visit(member.initializer!); } else { final Parameter valueParam = _declareParameter("value", member.type, null); _summary.result = _typeCheck(valueParam, member.type, member); } } else { - FunctionNode function = member.function; + final FunctionNode function = member.function!; final numTypeParameters = numTypeParams(member); final firstParamIndex = (hasReceiver ? 1 : 0) + numTypeParameters; @@ -666,43 +665,42 @@ class SummaryCollector extends RecursiveResultVisitor { firstParamIndex + function.requiredParameterCount); if (numTypeParameters > 0) { - _fnTypeVariables = {}; - for (int i = 0; i < numTypeParameters; ++i) { - _fnTypeVariables[function.typeParameters[i]] = - _declareParameter(function.typeParameters[i].name, null, null); - } + _fnTypeVariables = { + for (TypeParameter tp in function.typeParameters) + tp: _declareParameter(tp.name!, null, null) + }; } if (hasReceiver) { // TODO(alexmarkov): subclass cone _receiver = _declareParameter("this", - _environment.coreTypes.legacyRawType(member.enclosingClass), null, + _environment.coreTypes.legacyRawType(member.enclosingClass!), null, isReceiver: true); } - _translator = new RuntimeTypeTranslatorImpl( - this, _summary, _receiver, _fnTypeVariables, _genericInterfacesInfo); + _translator = new RuntimeTypeTranslatorImpl(_environment.coreTypes, + _summary, _receiver, _fnTypeVariables, _genericInterfacesInfo); // Handle forwarding stubs. We need to check types against the types of // the forwarding stub's target, [member.concreteForwardingStubTarget]. - FunctionNode useTypesFrom = member.function; - if (member is Procedure && - member.isForwardingStub && - member.concreteForwardingStubTarget != null) { + FunctionNode useTypesFrom = function; + if (member is Procedure && member.isForwardingStub) { final target = member.concreteForwardingStubTarget; - if (target is Field) { - useTypesFrom = FunctionNode(null, positionalParameters: [ - VariableDeclaration("value", type: target.type) - ]); - } else { - useTypesFrom = member.concreteForwardingStubTarget.function; + if (target != null) { + if (target is Field) { + useTypesFrom = FunctionNode(null, positionalParameters: [ + VariableDeclaration("value", type: target.type) + ]); + } else { + useTypesFrom = target.function!; + } } } for (int i = 0; i < function.positionalParameters.length; ++i) { final decl = function.positionalParameters[i]; _declareParameter( - decl.name, + decl.name!, _useTypeCheckForParameter(decl) ? null : useTypesFrom.positionalParameters[i].type, @@ -711,7 +709,7 @@ class SummaryCollector extends RecursiveResultVisitor { for (int i = 0; i < function.namedParameters.length; ++i) { final decl = function.namedParameters[i]; _declareParameter( - decl.name, + decl.name!, _useTypeCheckForParameter(decl) ? null : useTypesFrom.namedParameters[i].type, @@ -740,7 +738,7 @@ class SummaryCollector extends RecursiveResultVisitor { assert(count == _summary.parameterCount); _returnValue = new Join("%result", function.returnType); - _summary.add(_returnValue); + _summary.add(_returnValue!); if (member is Constructor) { // Make sure instance field initializers are visited. @@ -750,7 +748,7 @@ class SummaryCollector extends RecursiveResultVisitor { new DirectSelector(f, callKind: CallKind.FieldInitializer)); } } - member.initializers.forEach(_visit); + member.initializers.forEach(_visitWithoutResult); } if (function.body == null) { @@ -760,15 +758,15 @@ class SummaryCollector extends RecursiveResultVisitor { // Runtime type could be more precise than static type, so // calculate intersection. final typeCheck = _typeCheck(type, function.returnType, function); - _returnValue.values.add(typeCheck); + _returnValue!.values.add(typeCheck); } else { - _returnValue.values.add(type); + _returnValue!.values.add(type); } } else { - _visit(function.body); + _visitWithoutResult(function.body!); if (_fallthroughDetector.controlCanFallThrough(function)) { - _returnValue.values.add(_nullType); + _returnValue!.values.add(_nullType); } } @@ -776,15 +774,15 @@ class SummaryCollector extends RecursiveResultVisitor { // In addition to what is returned from the function body, // operator == performs implicit comparison with null // and returns bool. - _returnValue.values.add(_boolType); + _returnValue!.values.add(_boolType); } - _summary.result = _returnValue; + _summary.result = _returnValue!; } member.annotations.forEach(_visit); - member.enclosingClass?.annotations?.forEach(_visit); - member.enclosingLibrary?.annotations?.forEach(_visit); + member.enclosingClass?.annotations.forEach(_visit); + member.enclosingLibrary.annotations.forEach(_visit); _staticTypeContext = null; @@ -808,9 +806,7 @@ class SummaryCollector extends RecursiveResultVisitor { } Args rawArguments(Selector selector) { - final member = selector.member; - assert(member != null); - + final member = selector.member!; final List args = []; final List names = []; @@ -822,15 +818,14 @@ class SummaryCollector extends RecursiveResultVisitor { if (hasReceiverArg(member)) { assert(member.enclosingClass != null); final receiver = - new ConeType(_typesBuilder.getTFClass(member.enclosingClass)); + new ConeType(_typesBuilder.getTFClass(member.enclosingClass!)); args.add(receiver); } switch (selector.callKind) { case CallKind.Method: if (member is! Field) { - final function = member.function; - assert(function != null); + final function = member.function!; final int paramCount = function.positionalParameters.length + function.namedParameters.length; @@ -840,7 +835,7 @@ class SummaryCollector extends RecursiveResultVisitor { if (function.namedParameters.isNotEmpty) { for (var param in function.namedParameters) { - names.add(param.name); + names.add(param.name!); } // TODO(dartbug.com/32292): make sure parameters are sorted in // kernel AST and remove this sorting. @@ -864,11 +859,15 @@ class SummaryCollector extends RecursiveResultVisitor { return new Args(args, names: names); } - TypeExpr _visit(TreeNode node) => node.accept(this); + TypeExpr _visit(Expression node) => node.accept(this)!; - Args _visitArguments(TypeExpr receiver, Arguments arguments, + void _visitWithoutResult(TreeNode node) { + node.accept(this); + } + + Args _visitArguments(TypeExpr? receiver, Arguments arguments, {bool passTypeArguments: false}) { - final args = []; + final List args = []; if (passTypeArguments) { for (var type in arguments.types) { args.add(_translator.translate(type)); @@ -890,7 +889,7 @@ class SummaryCollector extends RecursiveResultVisitor { } names.sort(); for (var name in names) { - args.add(map[name]); + args.add(map[name]!); } return new Args(args, names: names); } else { @@ -899,9 +898,9 @@ class SummaryCollector extends RecursiveResultVisitor { } Parameter _declareParameter( - String name, DartType type, Expression initializer, + String name, DartType? type, Expression? initializer, {bool isReceiver: false}) { - Type staticType; + Type? staticType; if (type != null) { staticType = _typesBuilder.fromStaticType(type, !isReceiver); } @@ -916,7 +915,7 @@ class SummaryCollector extends RecursiveResultVisitor { } else if (initializer is BasicLiteral || initializer is SymbolLiteral || initializer is TypeLiteral) { - param.defaultValue = _visit(initializer); + param.defaultValue = _visit(initializer) as Type; } else { throw 'Unexpected parameter $name default value ${initializer.runtimeType} $initializer'; } @@ -930,8 +929,7 @@ class SummaryCollector extends RecursiveResultVisitor { } void _declareVariable(VariableDeclaration decl, TypeExpr initialValue) { - final int varIndex = _variablesInfo.varIndex[decl]; - assert(varIndex != null); + final int varIndex = _variablesInfo.varIndex[decl]!; assert(_variablesInfo.varDeclarations[varIndex] == decl); assert(_variableValues[varIndex] == null); if (_variablesInfo.isCaptured(decl)) { @@ -944,8 +942,8 @@ class SummaryCollector extends RecursiveResultVisitor { } void _writeVariable(VariableDeclaration variable, TypeExpr value) { - final int varIndex = _variablesInfo.varIndex[variable]; - final Join join = _variableCells[varIndex]; + final int varIndex = _variablesInfo.varIndex[variable]!; + final Join? join = _variableCells[varIndex]; if (join != null) { join.values.add(value); } else { @@ -953,11 +951,12 @@ class SummaryCollector extends RecursiveResultVisitor { } } - List _cloneVariableValues(List values) => - new List.from(values); + List _cloneVariableValues(List values) => + new List.from(values); - List _makeEmptyVariableValues() { - final values = new List.filled(_variablesInfo.numVariables, null); + List _makeEmptyVariableValues() { + final values = + new List.filled(_variablesInfo.numVariables, null); for (int i = 0; i < values.length; ++i) { if (_variableCells[i] != null) { values[i] = _variableValues[i]; @@ -978,11 +977,11 @@ class SummaryCollector extends RecursiveResultVisitor { return join; } - void _mergeVariableValues(List dst, List src) { + void _mergeVariableValues(List dst, List src) { assert(dst.length == src.length); for (int i = 0; i < dst.length; ++i) { - final TypeExpr dstValue = dst[i]; - final TypeExpr srcValue = src[i]; + final TypeExpr? dstValue = dst[i]; + final TypeExpr? srcValue = src[i]; if (identical(dstValue, srcValue)) { continue; } @@ -997,21 +996,21 @@ class SummaryCollector extends RecursiveResultVisitor { } else if (srcValue is Join && srcValue.values.contains(dstValue)) { dst[i] = srcValue; } else { - final Join join = _makeJoin(i, dst[i]); - join.values.add(src[i]); + final Join join = _makeJoin(i, dstValue); + join.values.add(srcValue); dst[i] = join; } } } - void _copyVariableValues(List dst, List src) { + void _copyVariableValues(List dst, List src) { assert(dst.length == src.length); for (int i = 0; i < dst.length; ++i) { dst[i] = src[i]; } } - bool _isIdenticalState(List state1, List state2) { + bool _isIdenticalState(List state1, List state2) { assert(state1.length == state2.length); for (int i = 0; i < state1.length; ++i) { if (!identical(state1[i], state2[i])) { @@ -1021,14 +1020,14 @@ class SummaryCollector extends RecursiveResultVisitor { return true; } - List _insertJoinsForModifiedVariables(TreeNode node, bool isTry) { - final List joins = - new List.filled(_variablesInfo.numVariables, null); + List _insertJoinsForModifiedVariables(ast.Statement node, bool isTry) { + final List joins = + new List.filled(_variablesInfo.numVariables, null); for (var i in _variablesInfo.getModifiedVariables(node)) { if (_variableCells[i] != null) { assert(_variableCells[i] == _variableValues[i]); } else { - final join = _makeJoin(i, _variableValues[i]); + final join = _makeJoin(i, _variableValues[i]!); joins[i] = join; _variableValues[i] = join; if (isTry) { @@ -1044,7 +1043,7 @@ class SummaryCollector extends RecursiveResultVisitor { /// Stops accumulating values in [joins] by removing them from /// _variableCells. - void _restoreVariableCellsAfterTry(List joins) { + void _restoreVariableCellsAfterTry(List joins) { for (int i = 0; i < joins.length; ++i) { if (joins[i] != null) { assert(_variableCells[i] == joins[i]); @@ -1053,14 +1052,14 @@ class SummaryCollector extends RecursiveResultVisitor { } } - void _mergeVariableValuesToJoins(List values, List joins) { + void _mergeVariableValuesToJoins(List values, List joins) { for (int i = 0; i < joins.length; ++i) { final join = joins[i]; final value = values[i]; if (join != null && !identical(join, value) && !identical(join.values.first, value)) { - join.values.add(value); + join.values.add(value!); } } } @@ -1079,16 +1078,17 @@ class SummaryCollector extends RecursiveResultVisitor { // TODO(alexmarkov): Avoid declaring variables with static types. void _declareVariableWithStaticType(VariableDeclaration decl) { - if (decl.initializer != null) { - _visit(decl.initializer); + final initializer = decl.initializer; + if (initializer != null) { + _visit(initializer); } _declareVariable(decl, _typesBuilder.fromStaticType(decl.type, true)); } Call _makeCall(TreeNode node, Selector selector, Args args, {bool isInstanceCreation = false}) { - Type staticResultType = null; - Member target; + Type? staticResultType = null; + Member? target; if (selector is DirectSelector) { target = selector.member; } else if (selector is InterfaceSelector) { @@ -1101,9 +1101,7 @@ class SummaryCollector extends RecursiveResultVisitor { } Call call = new Call(selector, args, staticResultType, isInstanceCreation); _summary.add(call); - if (node != null) { - callSites[node] = call; - } + callSites[node] = call; return call; } @@ -1189,53 +1187,43 @@ class SummaryCollector extends RecursiveResultVisitor { } DartType _staticDartType(Expression node) => - node.getStaticType(_staticTypeContext); + node.getStaticType(_staticTypeContext!); Type _staticType(Expression node) => _typesBuilder.fromStaticType(_staticDartType(node), true); - ConcreteType _cachedBoolType; - ConcreteType get _boolType => _cachedBoolType ??= + late final ConcreteType _boolType = _entryPointsListener.addAllocatedClass(_environment.coreTypes.boolClass); - ConcreteType _cachedBoolTrue; - ConcreteType get _boolTrue => _cachedBoolTrue ??= - new ConcreteType(_boolType.cls, null, BoolConstant(true)); + late final ConcreteType _boolTrue = + ConcreteType(_boolType.cls, null, BoolConstant(true)); - ConcreteType _cachedBoolFalse; - ConcreteType get _boolFalse => _cachedBoolFalse ??= - new ConcreteType(_boolType.cls, null, BoolConstant(false)); + late final ConcreteType _boolFalse = + ConcreteType(_boolType.cls, null, BoolConstant(false)); - Type _cachedDoubleType; - Type get _doubleType => _cachedDoubleType ??= new ConeType( - _typesBuilder.getTFClass(_environment.coreTypes.doubleClass)); + late final Type _doubleType = + ConeType(_typesBuilder.getTFClass(_environment.coreTypes.doubleClass)); - Type _cachedIntType; - Type get _intType => _cachedIntType ??= - new ConeType(_typesBuilder.getTFClass(_environment.coreTypes.intClass)); + late final Type _intType = + ConeType(_typesBuilder.getTFClass(_environment.coreTypes.intClass)); - Type _cachedStringType; - Type get _stringType => _cachedStringType ??= new ConeType( - _typesBuilder.getTFClass(_environment.coreTypes.stringClass)); + late final Type _stringType = + ConeType(_typesBuilder.getTFClass(_environment.coreTypes.stringClass)); - Type _cachedSymbolType; - Type get _symbolType => _cachedSymbolType ??= new ConeType( - _typesBuilder.getTFClass(_environment.coreTypes.symbolClass)); + late final Type _symbolType = + ConeType(_typesBuilder.getTFClass(_environment.coreTypes.symbolClass)); - Type _cachedTypeType; - Type get _typeType => _cachedTypeType ??= - new ConeType(_typesBuilder.getTFClass(_environment.coreTypes.typeClass)); + late final Type _typeType = + ConeType(_typesBuilder.getTFClass(_environment.coreTypes.typeClass)); - Type _cachedNullType; - Type get _nullType => - _cachedNullType ??= new Type.nullable(const EmptyType()); + late final Type _nullType = Type.nullable(const EmptyType()); - Class get _superclass => _staticTypeContext.thisType.classNode.superclass; + Class get _superclass => _staticTypeContext!.thisType!.classNode.superclass!; Type _boolLiteralType(bool value) => value ? _boolTrue : _boolFalse; - Type _intLiteralType(int value, Constant constant) { - final Class concreteClass = + Type _intLiteralType(int value, Constant? constant) { + final Class? concreteClass = target.concreteIntLiteralClass(_environment.coreTypes, value); if (concreteClass != null) { constant ??= IntConstant(value); @@ -1247,8 +1235,8 @@ class SummaryCollector extends RecursiveResultVisitor { return _intType; } - Type _doubleLiteralType(double value, Constant constant) { - final Class concreteClass = + Type _doubleLiteralType(double value, Constant? constant) { + final Class? concreteClass = target.concreteDoubleLiteralClass(_environment.coreTypes, value); if (concreteClass != null) { constant ??= DoubleConstant(value); @@ -1260,8 +1248,8 @@ class SummaryCollector extends RecursiveResultVisitor { return _doubleType; } - Type _stringLiteralType(String value, Constant constant) { - final Class concreteClass = + Type _stringLiteralType(String value, Constant? constant) { + final Class? concreteClass = target.concreteStringLiteralClass(_environment.coreTypes, value); if (concreteClass != null) { constant ??= StringConstant(value); @@ -1284,7 +1272,7 @@ class SummaryCollector extends RecursiveResultVisitor { node.positionalParameters.forEach(_declareVariableWithStaticType); node.namedParameters.forEach(_declareVariableWithStaticType); - _visit(node.body); + _visitWithoutResult(node.body!); _variableValues = savedVariableValues; _returnValue = savedReturn; @@ -1307,8 +1295,7 @@ class SummaryCollector extends RecursiveResultVisitor { for (Class c in _hierarchy.computeSubtypesInformation().getSubtypesOf(cls)) { if (!c.isAbstract) { - final candidate = _hierarchy.getDispatchTarget(c, _equalsName); - assert(candidate != null); + final candidate = _hierarchy.getDispatchTarget(c, _equalsName)!; assert(!candidate.isAbstract); if (candidate != _environment.coreTypes.objectEquals) { _cachedHasOverriddenEquals[cls] = true; @@ -1328,12 +1315,12 @@ class SummaryCollector extends RecursiveResultVisitor { // On exit _variableValues is null, so caller should explicitly pick // either trueState or falseState. void _visitCondition( - Expression node, List trueState, List falseState) { + Expression node, List trueState, List falseState) { assert(_isIdenticalState(_variableValues, trueState)); assert(_isIdenticalState(_variableValues, falseState)); if (node is Not) { _visitCondition(node.operand, falseState, trueState); - _variableValues = null; + _variableValues = const []; // Should not be used. return; } else if (node is LogicalExpression) { final isOR = (node.operatorEnum == LogicalExpressionOperator.OR); @@ -1351,7 +1338,7 @@ class SummaryCollector extends RecursiveResultVisitor { _visitCondition(node.right, trueState, falseStateAfterRHS); _mergeVariableValues(falseState, falseStateAfterRHS); } - _variableValues = null; + _variableValues = const []; // Should not be used. return; } else if (node is VariableGet || (node is AsExpression && node.operand is VariableGet)) { @@ -1359,12 +1346,12 @@ class SummaryCollector extends RecursiveResultVisitor { _addUse(_visit(node)); final variableGet = (node is AsExpression ? node.operand : node) as VariableGet; - final int varIndex = _variablesInfo.varIndex[variableGet.variable]; + final int varIndex = _variablesInfo.varIndex[variableGet.variable]!; if (_variableCells[varIndex] == null) { trueState[varIndex] = _boolTrue; falseState[varIndex] = _boolFalse; } - _variableValues = null; + _variableValues = const []; // Should not be used. return; } else if (node is EqualsCall && node.left is VariableGet) { final lhs = node.left as VariableGet; @@ -1379,11 +1366,11 @@ class SummaryCollector extends RecursiveResultVisitor { !_hasOverriddenEquals(lhs.variable.type))) { // 'x == c', where x is a variable and c is a constant. _addUse(_visit(node)); - final int varIndex = _variablesInfo.varIndex[lhs.variable]; + final int varIndex = _variablesInfo.varIndex[lhs.variable]!; if (_variableCells[varIndex] == null) { trueState[varIndex] = _visit(rhs); } - _variableValues = null; + _variableValues = const []; // Should not be used. return; } } else if (node is EqualsNull && node.expression is VariableGet) { @@ -1393,12 +1380,12 @@ class SummaryCollector extends RecursiveResultVisitor { _makeCall(node, DirectSelector(_environment.coreTypes.objectEquals), Args([expr, _nullType])); final narrowedNotNull = _makeNarrowNotNull(node, expr); - final int varIndex = _variablesInfo.varIndex[lhs.variable]; + final int varIndex = _variablesInfo.varIndex[lhs.variable]!; if (_variableCells[varIndex] == null) { trueState[varIndex] = _nullType; falseState[varIndex] = narrowedNotNull; } - _variableValues = null; + _variableValues = const []; // Should not be used. return; } else if (node is IsExpression && node.operand is VariableGet) { // Handle 'x is T', where x is a variable. @@ -1406,17 +1393,17 @@ class SummaryCollector extends RecursiveResultVisitor { final TypeCheck typeCheck = _typeCheck(_visit(operand), node.type, node, SubtypeTestKind.IsTest); isTests[node] = typeCheck; - final int varIndex = _variablesInfo.varIndex[operand.variable]; + final int varIndex = _variablesInfo.varIndex[operand.variable]!; if (_variableCells[varIndex] == null) { trueState[varIndex] = typeCheck; } - _variableValues = null; + _variableValues = const []; // Should not be used. return; } _addUse(_visit(node)); _copyVariableValues(trueState, _variableValues); _copyVariableValues(falseState, _variableValues); - _variableValues = null; + _variableValues = const []; // Should not be used. } void _updateReceiverAfterCall( @@ -1425,7 +1412,7 @@ class SummaryCollector extends RecursiveResultVisitor { if (receiverNode is VariableGet) { final nullSelectors = isSetter ? _nullSetters : _nullMethodsAndGetters; if (!nullSelectors.contains(selector)) { - final int varIndex = _variablesInfo.varIndex[receiverNode.variable]; + final int varIndex = _variablesInfo.varIndex[receiverNode.variable]!; if (_variableCells[varIndex] == null) { _variableValues[varIndex] = _makeNarrow(receiverValue, const AnyType()); @@ -1434,9 +1421,8 @@ class SummaryCollector extends RecursiveResultVisitor { } } - Procedure _cachedUnsafeCast; - Procedure get unsafeCast => _cachedUnsafeCast ??= _environment.coreTypes.index - .getTopLevelMember('dart:_internal', 'unsafeCast'); + late final Procedure unsafeCast = _environment.coreTypes.index + .getTopLevelProcedure('dart:_internal', 'unsafeCast'); @override defaultTreeNode(TreeNode node) => @@ -1446,10 +1432,10 @@ class SummaryCollector extends RecursiveResultVisitor { TypeExpr visitAsExpression(AsExpression node) { final operandNode = node.operand; final TypeExpr operand = _visit(operandNode); - final TypeExpr result = _typeCheck(operand, node.type, node); + final TypeCheck result = _typeCheck(operand, node.type, node); explicitCasts[node] = result; if (operandNode is VariableGet) { - final int varIndex = _variablesInfo.varIndex[operandNode.variable]; + final int varIndex = _variablesInfo.varIndex[operandNode.variable]!; if (_variableCells[varIndex] == null) { _variableValues[varIndex] = result; } @@ -1462,7 +1448,7 @@ class SummaryCollector extends RecursiveResultVisitor { final operandNode = node.operand; final TypeExpr result = _makeNarrowNotNull(node, _visit(operandNode)); if (operandNode is VariableGet) { - final int varIndex = _variablesInfo.varIndex[operandNode.variable]; + final int varIndex = _variablesInfo.varIndex[operandNode.variable]!; if (_variableCells[varIndex] == null) { _variableValues[varIndex] = result; } @@ -1549,20 +1535,20 @@ class SummaryCollector extends RecursiveResultVisitor { @override TypeExpr visitLet(Let node) { - _declareVariable(node.variable, _visit(node.variable.initializer)); + _declareVariable(node.variable, _visit(node.variable.initializer!)); return _visit(node.body); } @override TypeExpr visitBlockExpression(BlockExpression node) { - _visit(node.body); + _visitWithoutResult(node.body); return _visit(node.value); } @override TypeExpr visitListLiteral(ListLiteral node) { node.expressions.forEach(_visit); - Class concreteClass = + Class? concreteClass = target.concreteListLiteralClass(_environment.coreTypes); if (concreteClass != null) { return _translator.instantiateConcreteType( @@ -1588,7 +1574,7 @@ class SummaryCollector extends RecursiveResultVisitor { _visit(entry.key); _visit(entry.value); } - Class concreteClass = + Class? concreteClass = target.concreteMapLiteralClass(_environment.coreTypes); if (concreteClass != null) { return _translator.instantiateConcreteType( @@ -1690,7 +1676,7 @@ class SummaryCollector extends RecursiveResultVisitor { } TypeExpr _handlePropertyGet( - TreeNode node, Expression receiverNode, Member target, Name selector) { + TreeNode node, Expression receiverNode, Member? target, Name selector) { var receiver = _visit(receiverNode); var args = new Args([receiver]); TypeExpr result; @@ -1779,8 +1765,7 @@ class SummaryCollector extends RecursiveResultVisitor { @override TypeExpr visitSuperPropertyGet(SuperPropertyGet node) { assert(kPartialMixinResolution); - assert(_receiver != null, "Should have receiver. Node: $node"); - final args = new Args([_receiver]); + final args = new Args([_receiver!]); // Re-resolve target due to partial mixin resolution. final target = _hierarchy.getDispatchTarget(_superclass, node.name); if (target == null) { @@ -1794,9 +1779,8 @@ class SummaryCollector extends RecursiveResultVisitor { @override TypeExpr visitSuperPropertySet(SuperPropertySet node) { assert(kPartialMixinResolution); - assert(_receiver != null, "Should have receiver. Node: $node"); final value = _visit(node.value); - final args = new Args([_receiver, value]); + final args = new Args([_receiver!, value]); // Re-resolve target due to partial mixin resolution. final target = _hierarchy.getDispatchTarget(_superclass, node.name, setter: true); @@ -1882,8 +1866,7 @@ class SummaryCollector extends RecursiveResultVisitor { @override TypeExpr visitThisExpression(ThisExpression node) { - assert(_receiver != null, "Should have receiver. Node: $node"); - return _receiver; + return _receiver!; } @override @@ -1900,7 +1883,7 @@ class SummaryCollector extends RecursiveResultVisitor { @override TypeExpr visitVariableGet(VariableGet node) { - final v = _variableValues[_variablesInfo.varIndex[node.variable]]; + final v = _variableValues[_variablesInfo.varIndex[node.variable]!]; if (v == null) { throw 'Unable to find variable ${node.variable} at ${node.location}'; } @@ -1925,56 +1908,60 @@ class SummaryCollector extends RecursiveResultVisitor { } @override - TypeExpr visitAssertStatement(AssertStatement node) { + TypeExpr? visitAssertStatement(AssertStatement node) { if (!kRemoveAsserts) { _addUse(_visit(node.condition)); - if (node.message != null) { - _visit(node.message); + final message = node.message; + if (message != null) { + _visit(message); } } return null; } @override - TypeExpr visitBlock(Block node) { - node.statements.forEach(_visit); + TypeExpr? visitBlock(Block node) { + node.statements.forEach(_visitWithoutResult); return null; } @override - TypeExpr visitAssertBlock(AssertBlock node) { + TypeExpr? visitAssertBlock(AssertBlock node) { if (!kRemoveAsserts) { - node.statements.forEach(_visit); + node.statements.forEach(_visitWithoutResult); } return null; } @override - TypeExpr visitBreakStatement(BreakStatement node) { - _variableValuesAfterLabeledStatements ??= - >{}; - final state = _variableValuesAfterLabeledStatements[node.target]; + TypeExpr? visitBreakStatement(BreakStatement node) { + var afterLabels = _variableValuesAfterLabeledStatements; + if (afterLabels == null) { + _variableValuesAfterLabeledStatements = + afterLabels = >{}; + } + final state = afterLabels[node.target]; if (state != null) { _mergeVariableValues(state, _variableValues); } else { - _variableValuesAfterLabeledStatements[node.target] = _variableValues; + afterLabels[node.target] = _variableValues; } _variableValues = _makeEmptyVariableValues(); return null; } @override - TypeExpr visitContinueSwitchStatement(ContinueSwitchStatement node) { + TypeExpr? visitContinueSwitchStatement(ContinueSwitchStatement node) { _mergeVariableValuesToJoins( - _variableValues, _joinsAtSwitchCases[node.target]); + _variableValues, _joinsAtSwitchCases![node.target]!); _variableValues = _makeEmptyVariableValues(); return null; } @override - TypeExpr visitDoStatement(DoStatement node) { - final List joins = _insertJoinsForModifiedVariables(node, false); - _visit(node.body); + TypeExpr? visitDoStatement(DoStatement node) { + final List joins = _insertJoinsForModifiedVariables(node, false); + _visitWithoutResult(node.body); final trueState = _cloneVariableValues(_variableValues); final falseState = _cloneVariableValues(_variableValues); _visitCondition(node.condition, trueState, falseState); @@ -1988,39 +1975,39 @@ class SummaryCollector extends RecursiveResultVisitor { } @override - TypeExpr visitEmptyStatement(EmptyStatement node) => null; + TypeExpr? visitEmptyStatement(EmptyStatement node) => null; @override - TypeExpr visitExpressionStatement(ExpressionStatement node) { + TypeExpr? visitExpressionStatement(ExpressionStatement node) { _visit(node.expression); return null; } @override - TypeExpr visitForInStatement(ForInStatement node) { + TypeExpr? visitForInStatement(ForInStatement node) { _visit(node.iterable); // TODO(alexmarkov): try to infer more precise type from 'iterable' _declareVariableWithStaticType(node.variable); - final List joins = _insertJoinsForModifiedVariables(node, false); + final List joins = _insertJoinsForModifiedVariables(node, false); final stateAfterLoop = _cloneVariableValues(_variableValues); - _visit(node.body); + _visitWithoutResult(node.body); _mergeVariableValuesToJoins(_variableValues, joins); _variableValues = stateAfterLoop; return null; } @override - TypeExpr visitForStatement(ForStatement node) { + TypeExpr? visitForStatement(ForStatement node) { node.variables.forEach(visitVariableDeclaration); - final List joins = _insertJoinsForModifiedVariables(node, false); + final List joins = _insertJoinsForModifiedVariables(node, false); final trueState = _cloneVariableValues(_variableValues); final falseState = _cloneVariableValues(_variableValues); if (node.condition != null) { - _visitCondition(node.condition, trueState, falseState); + _visitCondition(node.condition!, trueState, falseState); } _variableValues = trueState; - _visit(node.body); + _visitWithoutResult(node.body); node.updates.forEach(_visit); _mergeVariableValuesToJoins(_variableValues, joins); // Kernel represents 'break;' as a BreakStatement referring to a @@ -2032,7 +2019,7 @@ class SummaryCollector extends RecursiveResultVisitor { } @override - TypeExpr visitFunctionDeclaration(FunctionDeclaration node) { + TypeExpr? visitFunctionDeclaration(FunctionDeclaration node) { // TODO(alexmarkov): support function types. node.variable.annotations.forEach(_visit); _declareVariableWithStaticType(node.variable); @@ -2041,18 +2028,18 @@ class SummaryCollector extends RecursiveResultVisitor { } @override - TypeExpr visitIfStatement(IfStatement node) { + TypeExpr? visitIfStatement(IfStatement node) { final trueState = _cloneVariableValues(_variableValues); final falseState = _cloneVariableValues(_variableValues); _visitCondition(node.condition, trueState, falseState); _variableValues = trueState; - _visit(node.then); + _visitWithoutResult(node.then); final stateAfter = _variableValues; _variableValues = falseState; if (node.otherwise != null) { - _visit(node.otherwise); + _visitWithoutResult(node.otherwise!); } _mergeVariableValues(stateAfter, _variableValues); @@ -2061,8 +2048,8 @@ class SummaryCollector extends RecursiveResultVisitor { } @override - TypeExpr visitLabeledStatement(LabeledStatement node) { - _visit(node.body); + TypeExpr? visitLabeledStatement(LabeledStatement node) { + _visitWithoutResult(node.body); final state = _variableValuesAfterLabeledStatements?.remove(node); if (state != null) { _mergeVariableValues(_variableValues, state); @@ -2071,34 +2058,35 @@ class SummaryCollector extends RecursiveResultVisitor { } @override - TypeExpr visitReturnStatement(ReturnStatement node) { - TypeExpr ret = - (node.expression != null) ? _visit(node.expression) : _nullType; - if (_returnValue != null) { - _returnValue.values.add(ret); - } + TypeExpr? visitReturnStatement(ReturnStatement node) { + final expression = node.expression; + TypeExpr ret = (expression != null) ? _visit(expression) : _nullType; + _returnValue?.values.add(ret); _variableValues = _makeEmptyVariableValues(); return null; } @override - TypeExpr visitSwitchStatement(SwitchStatement node) { + TypeExpr? visitSwitchStatement(SwitchStatement node) { _visit(node.expression); // Insert joins at each case in case there are 'continue' statements. final stateOnEntry = _variableValues; - final variableValuesAtCaseEntry = >{}; - _joinsAtSwitchCases ??= >{}; + final variableValuesAtCaseEntry = >{}; + Map>? joinsAtSwitchCases = _joinsAtSwitchCases; + if (joinsAtSwitchCases == null) { + _joinsAtSwitchCases = joinsAtSwitchCases = >{}; + } for (var switchCase in node.cases) { _variableValues = _cloneVariableValues(stateOnEntry); - _joinsAtSwitchCases[switchCase] = + joinsAtSwitchCases[switchCase] = _insertJoinsForModifiedVariables(node, false); variableValuesAtCaseEntry[switchCase] = _variableValues; } bool hasDefault = false; for (var switchCase in node.cases) { - _variableValues = variableValuesAtCaseEntry[switchCase]; + _variableValues = variableValuesAtCaseEntry[switchCase]!; switchCase.expressions.forEach(_visit); - _visit(switchCase.body); + _visitWithoutResult(switchCase.body); hasDefault = hasDefault || switchCase.isDefault; } if (!hasDefault) { @@ -2108,21 +2096,21 @@ class SummaryCollector extends RecursiveResultVisitor { } @override - TypeExpr visitTryCatch(TryCatch node) { + TypeExpr? visitTryCatch(TryCatch node) { final joins = _insertJoinsForModifiedVariables(node, true); final stateAfterTry = _cloneVariableValues(_variableValues); - _visit(node.body); + _visitWithoutResult(node.body); _restoreVariableCellsAfterTry(joins); - List stateAfterCatch; + List? stateAfterCatch; for (var catchClause in node.catches) { _variableValues = _cloneVariableValues(stateAfterTry); if (catchClause.exception != null) { - _declareVariableWithStaticType(catchClause.exception); + _declareVariableWithStaticType(catchClause.exception!); } if (catchClause.stackTrace != null) { - _declareVariableWithStaticType(catchClause.stackTrace); + _declareVariableWithStaticType(catchClause.stackTrace!); } - _visit(catchClause.body); + _visitWithoutResult(catchClause.body); if (stateAfterCatch == null) { stateAfterCatch = _variableValues; } else { @@ -2130,38 +2118,39 @@ class SummaryCollector extends RecursiveResultVisitor { } } _variableValues = stateAfterTry; - _mergeVariableValues(_variableValues, stateAfterCatch); + _mergeVariableValues(_variableValues, stateAfterCatch!); return null; } @override - TypeExpr visitTryFinally(TryFinally node) { + TypeExpr? visitTryFinally(TryFinally node) { final joins = _insertJoinsForModifiedVariables(node, true); final stateAfterTry = _cloneVariableValues(_variableValues); - _visit(node.body); + _visitWithoutResult(node.body); _restoreVariableCellsAfterTry(joins); _variableValues = stateAfterTry; - _visit(node.finalizer); + _visitWithoutResult(node.finalizer); return null; } @override - TypeExpr visitVariableDeclaration(VariableDeclaration node) { + TypeExpr? visitVariableDeclaration(VariableDeclaration node) { node.annotations.forEach(_visit); + final initializer = node.initializer; final TypeExpr initialValue = - node.initializer == null ? _nullType : _visit(node.initializer); + initializer == null ? _nullType : _visit(initializer); _declareVariable(node, initialValue); return null; } @override - TypeExpr visitWhileStatement(WhileStatement node) { - final List joins = _insertJoinsForModifiedVariables(node, false); + TypeExpr? visitWhileStatement(WhileStatement node) { + final List joins = _insertJoinsForModifiedVariables(node, false); final trueState = _cloneVariableValues(_variableValues); final falseState = _cloneVariableValues(_variableValues); _visitCondition(node.condition, trueState, falseState); _variableValues = trueState; - _visit(node.body); + _visitWithoutResult(node.body); _mergeVariableValuesToJoins(_variableValues, joins); // Kernel represents 'break;' as a BreakStatement referring to a // LabeledStatement. We are therefore guaranteed to always have the @@ -2172,15 +2161,15 @@ class SummaryCollector extends RecursiveResultVisitor { } @override - TypeExpr visitYieldStatement(YieldStatement node) { + TypeExpr? visitYieldStatement(YieldStatement node) { _visit(node.expression); return null; } @override - TypeExpr visitFieldInitializer(FieldInitializer node) { + TypeExpr? visitFieldInitializer(FieldInitializer node) { final value = _visit(node.value); - final args = new Args([_receiver, value]); + final args = new Args([_receiver!, value]); _makeCall( node, new DirectSelector(node.field, @@ -2190,17 +2179,17 @@ class SummaryCollector extends RecursiveResultVisitor { } @override - TypeExpr visitRedirectingInitializer(RedirectingInitializer node) { + TypeExpr? visitRedirectingInitializer(RedirectingInitializer node) { final args = _visitArguments(_receiver, node.arguments); _makeCall(node, new DirectSelector(node.target), args); return null; } @override - TypeExpr visitSuperInitializer(SuperInitializer node) { + TypeExpr? visitSuperInitializer(SuperInitializer node) { final args = _visitArguments(_receiver, node.arguments); - Constructor target = null; + Constructor? target = null; if (kPartialMixinResolution) { // Re-resolve target due to partial mixin resolution. for (var replacement in _superclass.constructors) { @@ -2212,27 +2201,26 @@ class SummaryCollector extends RecursiveResultVisitor { } else { target = node.target; } - assert(target != null); - _makeCall(node, new DirectSelector(target), args); + _makeCall(node, new DirectSelector(target!), args); return null; } @override - TypeExpr visitLocalInitializer(LocalInitializer node) { + TypeExpr? visitLocalInitializer(LocalInitializer node) { visitVariableDeclaration(node.variable); return null; } @override - TypeExpr visitAssertInitializer(AssertInitializer node) { + TypeExpr? visitAssertInitializer(AssertInitializer node) { if (!kRemoveAsserts) { - _visit(node.statement); + _visitWithoutResult(node.statement); } return null; } @override - TypeExpr visitInvalidInitializer(InvalidInitializer node) { + TypeExpr? visitInvalidInitializer(InvalidInitializer node) { return null; } @@ -2244,21 +2232,21 @@ class SummaryCollector extends RecursiveResultVisitor { class RuntimeTypeTranslatorImpl extends DartTypeVisitor implements RuntimeTypeTranslator { - final Summary summary; - final Map functionTypeVariables; + final CoreTypes coreTypes; + final Summary? summary; + final Map? functionTypeVariables; final Map typesCache = {}; - final TypeExpr receiver; + final TypeExpr? receiver; final GenericInterfacesInfo genericInterfacesInfo; - final SummaryCollector summaryCollector; - RuntimeTypeTranslatorImpl(this.summaryCollector, this.summary, this.receiver, + RuntimeTypeTranslatorImpl(this.coreTypes, this.summary, this.receiver, this.functionTypeVariables, this.genericInterfacesInfo) {} // Create a type translator which can be used only for types with no free type // variables. - RuntimeTypeTranslatorImpl.forClosedTypes(this.genericInterfacesInfo) - : summaryCollector = null, - summary = null, + RuntimeTypeTranslatorImpl.forClosedTypes( + this.coreTypes, this.genericInterfacesInfo) + : summary = null, functionTypeVariables = null, receiver = null {} @@ -2271,8 +2259,7 @@ class RuntimeTypeTranslatorImpl extends DartTypeVisitor final substitution = Substitution.fromPairs(klass.typeParameters, typeArgs); final flattenedTypeArgs = genericInterfacesInfo.flattenedTypeArgumentsFor(klass); - final flattenedTypeExprs = - new List.filled(flattenedTypeArgs.length, null); + final flattenedTypeExprs = []; bool createConcreteType = true; bool allUnknown = true; @@ -2281,7 +2268,7 @@ class RuntimeTypeTranslatorImpl extends DartTypeVisitor translate(substitution.substituteType(flattenedTypeArgs[i])); if (typeExpr is! UnknownType) allUnknown = false; if (typeExpr is Statement) createConcreteType = false; - flattenedTypeExprs[i] = typeExpr; + flattenedTypeExprs.add(typeExpr); } if (allUnknown) return type; @@ -2291,7 +2278,7 @@ class RuntimeTypeTranslatorImpl extends DartTypeVisitor type.cls, new List.from(flattenedTypeExprs)); } else { final instantiate = new CreateConcreteType(type.cls, flattenedTypeExprs); - summary.add(instantiate); + summary!.add(instantiate); return instantiate; } } @@ -2341,8 +2328,7 @@ class RuntimeTypeTranslatorImpl extends DartTypeVisitor type.classNode.typeParameters, type.typeArguments); final flattenedTypeArgs = genericInterfacesInfo.flattenedTypeArgumentsFor(type.classNode); - final flattenedTypeExprs = - new List.filled(flattenedTypeArgs.length, null); + final flattenedTypeExprs = []; bool createRuntimeType = true; for (var i = 0; i < flattenedTypeArgs.length; ++i) { @@ -2350,7 +2336,7 @@ class RuntimeTypeTranslatorImpl extends DartTypeVisitor translate(substitution.substituteType(flattenedTypeArgs[i])); if (typeExpr == const UnknownType()) return const UnknownType(); if (typeExpr is! RuntimeType) createRuntimeType = false; - flattenedTypeExprs[i] = typeExpr; + flattenedTypeExprs.add(typeExpr); } if (createRuntimeType) { @@ -2360,7 +2346,7 @@ class RuntimeTypeTranslatorImpl extends DartTypeVisitor } else { final instantiate = new CreateRuntimeType( type.classNode, type.nullability, flattenedTypeExprs); - summary.add(instantiate); + summary!.add(instantiate); return instantiate; } } @@ -2375,32 +2361,32 @@ class RuntimeTypeTranslatorImpl extends DartTypeVisitor [typeArg]); } else { final instantiate = new CreateRuntimeType( - summaryCollector._environment.coreTypes.deprecatedFutureOrClass, + coreTypes.deprecatedFutureOrClass, type.nullability, [typeArg]); - summary.add(instantiate); + summary!.add(instantiate); return instantiate; } } @override visitTypeParameterType(TypeParameterType type) { + final functionTypeVariables = this.functionTypeVariables; if (functionTypeVariables != null) { final result = functionTypeVariables[type.parameter]; if (result != null) return result; } if (type.parameter.parent is! Class) return const UnknownType(); final interfaceClass = type.parameter.parent as Class; - assert(receiver != null); // Undetermined nullability is equivalent to nonNullable when // instantiating type parameter, so convert it right away. Nullability nullability = type.nullability; if (nullability == Nullability.undetermined) { nullability = Nullability.nonNullable; } - final extract = new Extract(receiver, interfaceClass, + final extract = new Extract(receiver!, interfaceClass, interfaceClass.typeParameters.indexOf(type.parameter), nullability); - summary.add(extract); + summary!.add(extract); return extract; } } @@ -2420,7 +2406,7 @@ class ConstantAllocationCollector extends ConstantVisitor { Type _getStaticType(Constant constant) => summaryCollector._typesBuilder.fromStaticType( - constant.getType(summaryCollector._staticTypeContext), false); + constant.getType(summaryCollector._staticTypeContext!), false); @override defaultConstant(Constant constant) { @@ -2467,7 +2453,7 @@ class ConstantAllocationCollector extends ConstantVisitor { for (final Constant entry in constant.entries) { typeFor(entry); } - final Class concreteClass = summaryCollector.target + final Class? concreteClass = summaryCollector.target .concreteConstListLiteralClass(summaryCollector._environment.coreTypes); if (concreteClass != null) { return new ConcreteType( diff --git a/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart b/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart index f1901e70649..00807484de2 100644 --- a/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart +++ b/pkg/vm/lib/transformations/type_flow/table_selector_assigner.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.9 - import 'package:kernel/ast.dart'; import 'utils.dart' show UnionFind; @@ -18,7 +16,7 @@ class TableSelectorAssigner { final Map> _methodOrSetterMemberIds = {}; final UnionFind _unionFind = UnionFind(); - List _selectorIdForMemberId; + late List _selectorIdForMemberId; TableSelectorAssigner(Component component) { for (Library library in component.libraries) { @@ -44,20 +42,21 @@ class TableSelectorAssigner { } } - Map _memberIdsForClass(Class cls, {bool getter}) { + Map _memberIdsForClass(Class? cls, {required bool getter}) { if (cls == null) return {}; final cache = getter ? _getterMemberIds : _methodOrSetterMemberIds; // Already computed for this class? - Map memberIds = cache[cls]; - if (memberIds != null) return memberIds; + final cachedMemberIds = cache[cls]; + if (cachedMemberIds != null) return cachedMemberIds; // Merge maps from supertypes. - memberIds = Map.from(_memberIdsForClass(cls.superclass, getter: getter)); + final memberIds = + Map.from(_memberIdsForClass(cls.superclass, getter: getter)); for (Supertype impl in cls.implementedTypes) { _memberIdsForClass(impl.classNode, getter: getter).forEach((name, id) { - final int firstId = memberIds[name]; + final int? firstId = memberIds[name]; if (firstId == null) { memberIds[name] = id; } else if (firstId != id) { @@ -99,9 +98,9 @@ class TableSelectorAssigner { return cache[cls] = memberIds; } - int _selectorIdForMember(Member member, {bool getter}) { + int _selectorIdForMember(Member member, {required bool getter}) { final map = getter ? _getterMemberIds : _methodOrSetterMemberIds; - int memberId = map[member.enclosingClass][member.name]; + int? memberId = map[member.enclosingClass!]![member.name]; if (memberId == null) { assert(member is Procedure && ((identical(map, _getterMemberIds) && @@ -115,7 +114,7 @@ class TableSelectorAssigner { return ProcedureAttributesMetadata.kInvalidSelectorId; } memberId = _unionFind.find(memberId); - int selectorId = _selectorIdForMemberId[memberId]; + int? selectorId = _selectorIdForMemberId[memberId]; if (selectorId == null) { _selectorIdForMemberId[memberId] = selectorId = metadata.addSelector(); } diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart index feb185da6fd..82bebeccb45 100644 --- a/pkg/vm/lib/transformations/type_flow/transformer.dart +++ b/pkg/vm/lib/transformations/type_flow/transformer.dart @@ -2,10 +2,7 @@ // 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.9 - /// Transformations based on type flow analysis. -library vm.transformations.type_flow.transformer; import 'dart:core' hide Type; @@ -14,7 +11,8 @@ import 'package:kernel/ast.dart' hide Statement, StatementVisitor; import 'package:kernel/ast.dart' as ast show Statement; import 'package:kernel/clone.dart' show CloneVisitorNotMembers; import 'package:kernel/core_types.dart' show CoreTypes; -import 'package:kernel/class_hierarchy.dart' show ClassHierarchy; +import 'package:kernel/class_hierarchy.dart' + show ClassHierarchy, ClosedWorldClassHierarchy; import 'package:kernel/library_index.dart' show LibraryIndex; import 'package:kernel/type_environment.dart'; @@ -43,16 +41,18 @@ const bool kDumpClassHierarchy = /// Assumes strong mode and closed world. Component transformComponent( Target target, CoreTypes coreTypes, Component component, - {PragmaAnnotationParser matcher, + {PragmaAnnotationParser? matcher, bool treeShakeSignatures: true, bool treeShakeWriteOnlyFields: true, bool treeShakeProtobufs: false}) { void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {} final hierarchy = new ClassHierarchy(component, coreTypes, - onAmbiguousSupertypes: ignoreAmbiguousSupertypes); + onAmbiguousSupertypes: ignoreAmbiguousSupertypes) + as ClosedWorldClassHierarchy; final types = new TypeEnvironment(coreTypes, hierarchy); final libraryIndex = new LibraryIndex.all(component); - final genericInterfacesInfo = new GenericInterfacesInfoImpl(hierarchy); + final genericInterfacesInfo = + new GenericInterfacesInfoImpl(coreTypes, hierarchy); final protobufHandler = treeShakeProtobufs ? ProtobufHandler.forComponent(component, coreTypes) : null; @@ -73,7 +73,7 @@ Component transformComponent( protobufHandler, matcher); - Procedure main = component.mainMethod; + Procedure? main = component.mainMethod; // `main` can be null, roots can also come from @pragma("vm:entry-point"). if (main != null) { @@ -149,7 +149,7 @@ class MoveFieldInitializers { if (!f.isStatic && !f.isLate && f.initializer != null && - mayHaveSideEffects(f.initializer)) + mayHaveSideEffects(f.initializer!)) f ]; if (fields.isEmpty) return; @@ -173,7 +173,7 @@ class MoveFieldInitializers { }; final List newInitializers = []; for (Field f in fields) { - Expression initExpr = f.initializer; + Expression initExpr = f.initializer!; if (!isFirst) { initExpr = CloneVisitorNotMembers().clone(initExpr); } @@ -204,7 +204,7 @@ class MoveFieldInitializers { class CleanupAnnotations extends RecursiveVisitor { final Class externalNameClass; final Class pragmaClass; - final ProtobufHandler protobufHandler; + final ProtobufHandler? protobufHandler; CleanupAnnotations( CoreTypes coreTypes, LibraryIndex index, this.protobufHandler) @@ -238,7 +238,7 @@ class CleanupAnnotations extends RecursiveVisitor { return (cls == externalNameClass) || (cls == pragmaClass) || (protobufHandler != null && - protobufHandler.usesAnnotationClass(cls)); + protobufHandler!.usesAnnotationClass(cls)); } } return false; @@ -255,11 +255,11 @@ class TFADevirtualization extends Devirtualization { : super(_typeFlowAnalysis.environment.coreTypes, component, hierarchy); @override - DirectCallMetadata getDirectCall(TreeNode node, Member interfaceTarget, + DirectCallMetadata? getDirectCall(TreeNode node, Member? interfaceTarget, {bool setter = false}) { final callSite = _typeFlowAnalysis.callSite(node); if (callSite != null) { - final Member singleTarget = fieldMorpher + final Member? singleTarget = fieldMorpher .getMorphedMember(callSite.monomorphicTarget, isSetter: setter); if (singleTarget != null) { return new DirectCallMetadata( @@ -283,12 +283,13 @@ class AnnotateKernel extends RecursiveVisitor { final UnboxingInfoMetadataRepository _unboxingInfoMetadata; final UnboxingInfoManager _unboxingInfo; final Class _intClass; - Constant _nullConstant; + late final Constant _nullConstant = NullConstant(); AnnotateKernel(Component component, this._typeFlowAnalysis, this.fieldMorpher, this._tableSelectorAssigner, this._unboxingInfo) : _directCallMetadataRepository = - component.metadata[DirectCallMetadataRepository.repositoryTag], + component.metadata[DirectCallMetadataRepository.repositoryTag] + as DirectCallMetadataRepository, _inferredTypeMetadata = new InferredTypeMetadataRepository(), _unreachableNodeMetadata = new UnreachableNodeMetadataRepository(), _procedureAttributesMetadata = @@ -308,12 +309,10 @@ class AnnotateKernel extends RecursiveVisitor { return _directCallMetadataRepository.mapping.containsKey(node); } - InferredType _convertType(Type type, + InferredType? _convertType(Type type, {bool skipCheck: false, bool receiverNotInt: false}) { - assert(type != null); - - Class concreteClass; - Constant constantValue; + Class? concreteClass; + Constant? constantValue; bool isInt = false; final nullable = type is NullableType; @@ -324,7 +323,7 @@ class AnnotateKernel extends RecursiveVisitor { if (nullable && type == const EmptyType()) { concreteClass = _typeFlowAnalysis.environment.coreTypes.deprecatedNullClass; - constantValue = _nullConstant ??= new NullConstant(); + constantValue = _nullConstant; } else { concreteClass = type.getConcreteClass(_typeFlowAnalysis.hierarchyCache); @@ -337,9 +336,9 @@ class AnnotateKernel extends RecursiveVisitor { } } - List typeArgs; + List? typeArgs; if (type is ConcreteType && type.typeArgs != null) { - typeArgs = type.typeArgs + typeArgs = type.typeArgs! .take(type.numImmediateTypeArgs) .map((t) => t is UnknownType ? null : (t as RuntimeType).representedType) @@ -374,7 +373,7 @@ class AnnotateKernel extends RecursiveVisitor { _unreachableNodeMetadata.mapping[node] = const UnreachableNode(); } - void _annotateCallSite(TreeNode node, Member interfaceTarget) { + void _annotateCallSite(TreeNode node, Member? interfaceTarget) { final callSite = _typeFlowAnalysis.callSite(node); if (callSite == null) return; if (!callSite.isReachable) { @@ -405,7 +404,7 @@ class AnnotateKernel extends RecursiveVisitor { if (interfaceTarget == null || _typeFlowAnalysis.hierarchyCache.hierarchy.isSubtypeOf( _typeFlowAnalysis.hierarchyCache.coreTypes.intClass, - interfaceTarget.enclosingClass)) { + interfaceTarget.enclosingClass!)) { markReceiverNotInt = true; } } @@ -446,35 +445,33 @@ class AnnotateKernel extends RecursiveVisitor { void _annotateMember(Member member) { if (_typeFlowAnalysis.isMemberUsed(member)) { if (member is Field) { - _setInferredType(member, _typeFlowAnalysis.fieldType(member)); + _setInferredType(member, _typeFlowAnalysis.fieldType(member)!); } else { - Args argTypes = _typeFlowAnalysis.argumentTypes(member); + Args argTypes = _typeFlowAnalysis.argumentTypes(member)!; final uncheckedParameters = _typeFlowAnalysis.uncheckedParameters(member); - assert(argTypes != null); final int firstParamIndex = numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0); - final positionalParams = member.function.positionalParameters; + final positionalParams = member.function!.positionalParameters; assert(argTypes.positionalCount == firstParamIndex + positionalParams.length); for (int i = 0; i < positionalParams.length; i++) { _setInferredType( positionalParams[i], argTypes.values[firstParamIndex + i], - skipCheck: uncheckedParameters.contains(positionalParams[i])); + skipCheck: uncheckedParameters!.contains(positionalParams[i])); } // TODO(dartbug.com/32292): make sure parameters are sorted in kernel // AST and iterate parameters in parallel, without lookup. final names = argTypes.names; for (int i = 0; i < names.length; i++) { - final param = findNamedParameter(member.function, names[i]); - assert(param != null); + final param = findNamedParameter(member.function!, names[i])!; _setInferredType(param, argTypes.values[firstParamIndex + positionalParams.length + i], - skipCheck: uncheckedParameters.contains(param)); + skipCheck: uncheckedParameters!.contains(param)); } // TODO(alexmarkov): figure out how to pass receiver type. @@ -521,7 +518,7 @@ class AnnotateKernel extends RecursiveVisitor { // interface target, and table dispatch calls need selector IDs for all // interface targets. if (member.isInstanceMember) { - final original = fieldMorpher.getOriginalMember(member); + final original = fieldMorpher.getOriginalMember(member)!; final attrs = new ProcedureAttributesMetadata( methodOrSetterCalledDynamically: _typeFlowAnalysis.isCalledDynamically(original), @@ -689,11 +686,11 @@ class TreeShaker { final Set _usedMembers = new Set(); final Set _usedExtensions = new Set(); final Set _usedTypedefs = new Set(); - FieldMorpher fieldMorpher; - _TreeShakerTypeVisitor typeVisitor; - _TreeShakerConstantVisitor constantVisitor; - _TreeShakerPass1 _pass1; - _TreeShakerPass2 _pass2; + late final FieldMorpher fieldMorpher; + late final _TreeShakerTypeVisitor typeVisitor; + late final _TreeShakerConstantVisitor constantVisitor; + late final _TreeShakerPass1 _pass1; + late final _TreeShakerPass2 _pass2; TreeShaker(Component component, this.typeFlowAnalysis, {this.treeShakeWriteOnlyFields: true}) { @@ -734,7 +731,7 @@ class TreeShaker { (!f.isStatic && f.initializer != null && isFieldInitializerReachable(f) && - mayHaveSideEffects(f.initializer)) || + mayHaveSideEffects(f.initializer!)) || (f.isLate && f.isFinal)) || isMemberReferencedFromNativeCode(f) || _isInstanceFieldOfAllocatedEnum(f); @@ -745,8 +742,8 @@ class TreeShaker { bool _isInstanceFieldOfAllocatedEnum(Field node) => !node.isStatic && node.enclosingClass != null && - node.enclosingClass.isEnum && - isClassAllocated(node.enclosingClass); + node.enclosingClass!.isEnum && + isClassAllocated(node.enclosingClass!); void addClassUsedInType(Class c) { if (_classesUsedInType.add(c)) { @@ -777,7 +774,7 @@ class TreeShaker { _usedClasses.add(enclosingClass); } - FunctionNode func = null; + FunctionNode? func = null; if (m is Field) { m.type.accept(typeVisitor); } else if (m is Procedure) { @@ -786,19 +783,19 @@ class TreeShaker { m.stubTarget = fieldMorpher.adjustInstanceCallTarget( m.concreteForwardingStubTarget, isSetter: m.isSetter); - addUsedMember(m.concreteForwardingStubTarget); + addUsedMember(m.concreteForwardingStubTarget!); } if (m.abstractForwardingStubTarget != null) { m.stubTarget = fieldMorpher.adjustInstanceCallTarget( m.abstractForwardingStubTarget, isSetter: m.isSetter); - addUsedMember(m.abstractForwardingStubTarget); + addUsedMember(m.abstractForwardingStubTarget!); } if (m.memberSignatureOrigin != null) { m.stubTarget = fieldMorpher.adjustInstanceCallTarget( m.memberSignatureOrigin, isSetter: m.isSetter); - addUsedMember(m.memberSignatureOrigin); + addUsedMember(m.memberSignatureOrigin!); } } else if (m is Constructor) { func = m.function; @@ -821,8 +818,7 @@ class TreeShaker { final extension = m.enclosingLibrary.extensions.firstWhere((extension) { return extension.members .any((descriptor) => descriptor.member.asMember == m); - }, orElse: () => null); - assert(extension != null); + }); // Ensure we retain the [Extension] itself (though members might be // shaken) @@ -844,7 +840,7 @@ class TreeShaker { if (_usedExtensions.add(node)) { node.annotations = const []; _pass1.transformTypeParameterList(node.typeParameters, node); - node.onType?.accept(typeVisitor); + node.onType.accept(typeVisitor); } } @@ -898,7 +894,7 @@ class FieldMorpher { isAbstract: true, fileUri: field.fileUri); } accessor.fileOffset = field.fileOffset; - field.enclosingClass.addProcedure(accessor); + field.enclosingClass!.addProcedure(accessor); _removedFields[accessor] = field; shaker.addUsedMember(accessor); return accessor; @@ -908,7 +904,7 @@ class FieldMorpher { /// If necessary, creates a getter or setter as a replacement if target is a /// field which is going to be removed by the tree shaker. /// This method is used during tree shaker pass 1. - Member adjustInstanceCallTarget(Member target, {bool isSetter = false}) { + Member? adjustInstanceCallTarget(Member? target, {bool isSetter = false}) { if (target is Field && !shaker.retainField(target)) { final targets = isSetter ? _settersForRemovedFields : _gettersForRemovedFields; @@ -923,9 +919,9 @@ class FieldMorpher { /// Return a member which replaced [target] in instance calls. /// This method can be used after tree shaking to discover replacement. - Member getMorphedMember(Member target, {bool isSetter = false}) { - if (target == null) { - return null; + Member? getMorphedMember(Member? target, {bool isSetter = false}) { + if (target is! Field) { + return target; } final targets = isSetter ? _settersForRemovedFields : _gettersForRemovedFields; @@ -934,7 +930,7 @@ class FieldMorpher { /// Return original member which was replaced by [target] in instance calls. /// This method can be used after tree shaking. - Member getOriginalMember(Member target) { + Member? getOriginalMember(Member? target) { if (target == null) { return null; } @@ -994,16 +990,15 @@ class _TreeShakerPass1 extends RemovingTransformer { final TreeShaker shaker; final FieldMorpher fieldMorpher; final TypeEnvironment environment; - Procedure _unsafeCast; - StaticTypeContext _staticTypeContext; - Member _currentMember; + StaticTypeContext? _staticTypeContext; + Member? _currentMember; StaticTypeContext get staticTypeContext => _staticTypeContext ??= StaticTypeContext(currentMember, environment); - Member get currentMember => _currentMember; - set currentMember(Member m) { + Member get currentMember => _currentMember!; + set currentMember(Member? m) { _currentMember = m; _staticTypeContext = null; } @@ -1022,7 +1017,7 @@ class _TreeShakerPass1 extends RemovingTransformer { } List _flattenArguments(Arguments arguments, - {Expression receiver}) { + {Expression? receiver}) { final args = []; if (receiver != null) { args.add(receiver); @@ -1035,9 +1030,9 @@ class _TreeShakerPass1 extends RemovingTransformer { bool _isThrowExpression(Expression expr) { for (;;) { if (expr is Let) { - expr = (expr as Let).body; + expr = expr.body; } else if (expr is BlockExpression) { - expr = (expr as BlockExpression).value; + expr = expr.value; } else { break; } @@ -1068,7 +1063,7 @@ class _TreeShakerPass1 extends RemovingTransformer { return BlockExpression(Block(statements), value); } - TreeNode _makeUnreachableCall(List args) { + Expression _makeUnreachableCall(List args) { Expression node; final int last = args.indexWhere(_isThrowExpression); if (last >= 0) { @@ -1090,12 +1085,12 @@ class _TreeShakerPass1 extends RemovingTransformer { new VariableDeclaration(null, initializer: _makeUnreachableCall(args))); } - NarrowNotNull _getNullTest(TreeNode node) => + NarrowNotNull? _getNullTest(TreeNode node) => shaker.typeFlowAnalysis.nullTest(node); - TreeNode _visitAssertNode(TreeNode node, TreeNode removalSentinel) { + TreeNode _visitAssertNode(TreeNode node, TreeNode? removalSentinel) { if (kRemoveAsserts) { - return removalSentinel; + return removalSentinel!; } else { node.transformOrRemoveChildren(this); return node; @@ -1103,31 +1098,31 @@ class _TreeShakerPass1 extends RemovingTransformer { } @override - DartType visitDartType(DartType node, DartType removalSentinel) { + DartType visitDartType(DartType node, DartType? removalSentinel) { node.accept(shaker.typeVisitor); return node; } @override - Supertype visitSupertype(Supertype node, Supertype removalSentinel) { + Supertype visitSupertype(Supertype node, Supertype? removalSentinel) { node.accept(shaker.typeVisitor); return node; } @override - TreeNode visitTypedef(Typedef node, TreeNode removalSentinel) { + TreeNode visitTypedef(Typedef node, TreeNode? removalSentinel) { return node; // Do not go deeper. } @override - Extension visitExtension(Extension node, TreeNode removalSentinel) { + TreeNode visitExtension(Extension node, TreeNode? removalSentinel) { // The extension can be considered a weak node, we'll only retain it if // normal code references any of it's members. return node; } @override - TreeNode visitClass(Class node, TreeNode removalSentinel) { + TreeNode visitClass(Class node, TreeNode? removalSentinel) { if (shaker.isClassAllocated(node) || shaker.isClassReferencedFromNativeCode(node)) { shaker.addClassUsedInType(node); @@ -1140,7 +1135,7 @@ class _TreeShakerPass1 extends RemovingTransformer { } @override - TreeNode defaultMember(Member node, TreeNode removalSentinel) { + TreeNode defaultMember(Member node, TreeNode? removalSentinel) { currentMember = node; if (shaker.isMemberBodyReachable(node)) { if (kPrintTrace) { @@ -1160,7 +1155,7 @@ class _TreeShakerPass1 extends RemovingTransformer { } @override - TreeNode visitField(Field node, TreeNode removalSentinel) { + TreeNode visitField(Field node, TreeNode? removalSentinel) { currentMember = node; if (shaker.retainField(node)) { if (kPrintTrace) { @@ -1185,21 +1180,21 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitInstanceInvocation( - InstanceInvocation node, TreeNode removalSentinel) { + InstanceInvocation node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall( _flattenArguments(node.arguments, receiver: node.receiver)); } - node.interfaceTarget = - fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget); + node.interfaceTarget = fieldMorpher + .adjustInstanceCallTarget(node.interfaceTarget) as Procedure; shaker.addUsedMember(node.interfaceTarget); return node; } @override TreeNode visitDynamicInvocation( - DynamicInvocation node, TreeNode removalSentinel) { + DynamicInvocation node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall( @@ -1210,7 +1205,7 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitLocalFunctionInvocation( - LocalFunctionInvocation node, TreeNode removalSentinel) { + LocalFunctionInvocation node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall(_flattenArguments(node.arguments)); @@ -1220,7 +1215,7 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitFunctionInvocation( - FunctionInvocation node, TreeNode removalSentinel) { + FunctionInvocation node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall( @@ -1230,24 +1225,24 @@ class _TreeShakerPass1 extends RemovingTransformer { } @override - TreeNode visitEqualsCall(EqualsCall node, TreeNode removalSentinel) { + TreeNode visitEqualsCall(EqualsCall node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall([node.left, node.right]); } - node.interfaceTarget = - fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget); + node.interfaceTarget = fieldMorpher + .adjustInstanceCallTarget(node.interfaceTarget) as Procedure; shaker.addUsedMember(node.interfaceTarget); return node; } @override - TreeNode visitEqualsNull(EqualsNull node, TreeNode removalSentinel) { + TreeNode visitEqualsNull(EqualsNull node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall([node.expression]); } - final nullTest = _getNullTest(node); + final nullTest = _getNullTest(node)!; if (nullTest.isAlwaysNull || nullTest.isAlwaysNotNull) { return _evaluateArguments([node.expression], BoolLiteral(nullTest.isAlwaysNull)..fileOffset = node.fileOffset); @@ -1256,13 +1251,13 @@ class _TreeShakerPass1 extends RemovingTransformer { } @override - TreeNode visitInstanceGet(InstanceGet node, TreeNode removalSentinel) { + TreeNode visitInstanceGet(InstanceGet node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall([node.receiver]); } else { node.interfaceTarget = - fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget); + fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget)!; shaker.addUsedMember(node.interfaceTarget); return node; } @@ -1270,20 +1265,20 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitInstanceTearOff( - InstanceTearOff node, TreeNode removalSentinel) { + InstanceTearOff node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall([node.receiver]); } else { - node.interfaceTarget = - fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget); + node.interfaceTarget = fieldMorpher + .adjustInstanceCallTarget(node.interfaceTarget) as Procedure; shaker.addUsedMember(node.interfaceTarget); return node; } } @override - TreeNode visitDynamicGet(DynamicGet node, TreeNode removalSentinel) { + TreeNode visitDynamicGet(DynamicGet node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall([node.receiver]); @@ -1294,7 +1289,7 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitFunctionTearOff( - FunctionTearOff node, TreeNode removalSentinel) { + FunctionTearOff node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall([node.receiver]); @@ -1304,20 +1299,20 @@ class _TreeShakerPass1 extends RemovingTransformer { } @override - TreeNode visitInstanceSet(InstanceSet node, TreeNode removalSentinel) { + TreeNode visitInstanceSet(InstanceSet node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall([node.receiver, node.value]); } else { node.interfaceTarget = fieldMorpher - .adjustInstanceCallTarget(node.interfaceTarget, isSetter: true); + .adjustInstanceCallTarget(node.interfaceTarget, isSetter: true)!; shaker.addUsedMember(node.interfaceTarget); return node; } } @override - TreeNode visitDynamicSet(DynamicSet node, TreeNode removalSentinel) { + TreeNode visitDynamicSet(DynamicSet node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall([node.receiver, node.value]); @@ -1328,15 +1323,15 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitSuperMethodInvocation( - SuperMethodInvocation node, TreeNode removalSentinel) { + SuperMethodInvocation node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall(_flattenArguments(node.arguments)); } else { - node.interfaceTarget = - fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget); + node.interfaceTarget = fieldMorpher + .adjustInstanceCallTarget(node.interfaceTarget) as Procedure?; if (node.interfaceTarget != null) { - shaker.addUsedMember(node.interfaceTarget); + shaker.addUsedMember(node.interfaceTarget!); } return node; } @@ -1344,7 +1339,7 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitSuperPropertyGet( - SuperPropertyGet node, TreeNode removalSentinel) { + SuperPropertyGet node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall([]); @@ -1352,7 +1347,7 @@ class _TreeShakerPass1 extends RemovingTransformer { node.interfaceTarget = fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget); if (node.interfaceTarget != null) { - shaker.addUsedMember(node.interfaceTarget); + shaker.addUsedMember(node.interfaceTarget!); } return node; } @@ -1360,7 +1355,7 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitSuperPropertySet( - SuperPropertySet node, TreeNode removalSentinel) { + SuperPropertySet node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall([node.value]); @@ -1368,7 +1363,7 @@ class _TreeShakerPass1 extends RemovingTransformer { node.interfaceTarget = fieldMorpher .adjustInstanceCallTarget(node.interfaceTarget, isSetter: true); if (node.interfaceTarget != null) { - shaker.addUsedMember(node.interfaceTarget); + shaker.addUsedMember(node.interfaceTarget!); } return node; } @@ -1376,7 +1371,7 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitStaticInvocation( - StaticInvocation node, TreeNode removalSentinel) { + StaticInvocation node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall(_flattenArguments(node.arguments)); @@ -1390,7 +1385,7 @@ class _TreeShakerPass1 extends RemovingTransformer { } @override - TreeNode visitStaticGet(StaticGet node, TreeNode removalSentinel) { + TreeNode visitStaticGet(StaticGet node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall([]); @@ -1405,13 +1400,13 @@ class _TreeShakerPass1 extends RemovingTransformer { } @override - Constant visitConstant(Constant node, Constant removalSentinel) { + Constant visitConstant(Constant node, Constant? removalSentinel) { shaker.constantVisitor.analyzeConstant(node); return node; } @override - TreeNode visitStaticSet(StaticSet node, TreeNode removalSentinel) { + TreeNode visitStaticSet(StaticSet node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall([node.value]); @@ -1428,7 +1423,7 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitConstructorInvocation( - ConstructorInvocation node, TreeNode removalSentinel) { + ConstructorInvocation node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableCall(_flattenArguments(node.arguments)); @@ -1444,7 +1439,7 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitRedirectingInitializer( - RedirectingInitializer node, TreeNode removalSentinel) { + RedirectingInitializer node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableInitializer(_flattenArguments(node.arguments)); @@ -1457,7 +1452,7 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitSuperInitializer( - SuperInitializer node, TreeNode removalSentinel) { + SuperInitializer node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableInitializer(_flattenArguments(node.arguments)); @@ -1469,7 +1464,7 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitFieldInitializer( - FieldInitializer node, TreeNode removalSentinel) { + FieldInitializer node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); if (_isUnreachable(node)) { return _makeUnreachableInitializer([node.value]); @@ -1482,7 +1477,7 @@ class _TreeShakerPass1 extends RemovingTransformer { return LocalInitializer( VariableDeclaration(null, initializer: node.value)); } else { - return removalSentinel; + return removalSentinel!; } } return node; @@ -1491,18 +1486,18 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitAssertStatement( - AssertStatement node, TreeNode removalSentinel) { + AssertStatement node, TreeNode? removalSentinel) { return _visitAssertNode(node, removalSentinel); } @override - TreeNode visitAssertBlock(AssertBlock node, TreeNode removalSentinel) { + TreeNode visitAssertBlock(AssertBlock node, TreeNode? removalSentinel) { return _visitAssertNode(node, removalSentinel); } @override TreeNode visitAssertInitializer( - AssertInitializer node, TreeNode removalSentinel) { + AssertInitializer node, TreeNode? removalSentinel) { return _visitAssertNode(node, removalSentinel); } @@ -1520,21 +1515,21 @@ class _TreeShakerPass1 extends RemovingTransformer { // Returns Block corresponding to the given extended bool literal, // or null if the expression is a simple bool literal. - Block _getExtendedBoolLiteralBlock(Expression expr) => + Block? _getExtendedBoolLiteralBlock(Expression expr) => (expr is BoolLiteral) ? null : (expr as BlockExpression).body; @override - TreeNode visitIfStatement(IfStatement node, TreeNode removalSentinel) { + TreeNode visitIfStatement(IfStatement node, TreeNode? removalSentinel) { final condition = transform(node.condition); if (_isExtendedBoolLiteral(condition)) { final bool conditionValue = _getExtendedBoolLiteralValue(condition); - final Block conditionBlock = _getExtendedBoolLiteralBlock(condition); - ast.Statement body; + final Block? conditionBlock = _getExtendedBoolLiteralBlock(condition); + ast.Statement? body; if (conditionValue) { body = transform(node.then); } else { if (node.otherwise != null) { - body = transformOrRemoveStatement(node.otherwise); + body = transformOrRemoveStatement(node.otherwise!); } } if (conditionBlock != null) { @@ -1549,7 +1544,7 @@ class _TreeShakerPass1 extends RemovingTransformer { node.condition = condition..parent = node; node.then = transform(node.then)..parent = node; if (node.otherwise != null) { - node.otherwise = transformOrRemoveStatement(node.otherwise); + node.otherwise = transformOrRemoveStatement(node.otherwise!); node.otherwise?.parent = node; } return node; @@ -1557,7 +1552,7 @@ class _TreeShakerPass1 extends RemovingTransformer { @override visitConditionalExpression( - ConditionalExpression node, TreeNode removalSentinel) { + ConditionalExpression node, TreeNode? removalSentinel) { final condition = transform(node.condition); if (_isExtendedBoolLiteral(condition)) { final bool value = _getExtendedBoolLiteralValue(condition); @@ -1578,7 +1573,7 @@ class _TreeShakerPass1 extends RemovingTransformer { } @override - TreeNode visitNot(Not node, TreeNode removalSentinel) { + TreeNode visitNot(Not node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); final operand = node.operand; if (_isExtendedBoolLiteral(operand)) { @@ -1595,7 +1590,7 @@ class _TreeShakerPass1 extends RemovingTransformer { @override TreeNode visitLogicalExpression( - LogicalExpression node, TreeNode removalSentinel) { + LogicalExpression node, TreeNode? removalSentinel) { final left = transform(node.left); final operatorEnum = node.operatorEnum; if (_isExtendedBoolLiteral(left)) { @@ -1621,8 +1616,8 @@ class _TreeShakerPass1 extends RemovingTransformer { } @override - TreeNode visitIsExpression(IsExpression node, TreeNode removalSentinel) { - TypeCheck check = shaker.typeFlowAnalysis.isTest(node); + TreeNode visitIsExpression(IsExpression node, TreeNode? removalSentinel) { + TypeCheck? check = shaker.typeFlowAnalysis.isTest(node); if (check != null && (check.alwaysFail || check.alwaysPass)) { final operand = transform(node.operand); final result = BoolLiteral(!check.alwaysFail) @@ -1634,9 +1629,9 @@ class _TreeShakerPass1 extends RemovingTransformer { } @override - TreeNode visitAsExpression(AsExpression node, TreeNode removalSentinel) { + TreeNode visitAsExpression(AsExpression node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); - TypeCheck check = shaker.typeFlowAnalysis.explicitCast(node); + TypeCheck? check = shaker.typeFlowAnalysis.explicitCast(node); if (check != null && check.alwaysPass) { return StaticInvocation( unsafeCast, Arguments([node.operand], types: [node.type])) @@ -1646,9 +1641,9 @@ class _TreeShakerPass1 extends RemovingTransformer { } @override - TreeNode visitNullCheck(NullCheck node, TreeNode removalSentinel) { + TreeNode visitNullCheck(NullCheck node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); - final nullTest = _getNullTest(node); + final nullTest = _getNullTest(node)!; if (nullTest.isAlwaysNotNull) { return StaticInvocation( unsafeCast, @@ -1659,12 +1654,9 @@ class _TreeShakerPass1 extends RemovingTransformer { return node; } - Procedure get unsafeCast { - _unsafeCast ??= shaker.typeFlowAnalysis.environment.coreTypes.index - .getTopLevelMember('dart:_internal', 'unsafeCast'); - assert(_unsafeCast != null); - return _unsafeCast; - } + late final Procedure unsafeCast = shaker + .typeFlowAnalysis.environment.coreTypes.index + .getTopLevelProcedure('dart:_internal', 'unsafeCast'); } /// The second pass of [TreeShaker]. It is called after set of used @@ -1680,7 +1672,7 @@ class _TreeShakerPass2 extends RemovingTransformer { void transformComponent(Component component) { component.transformOrRemoveChildren(this); for (Source source in component.uriToSource.values) { - source?.constantCoverageConstructors?.removeWhere((Reference reference) { + source.constantCoverageConstructors?.removeWhere((Reference reference) { Member node = reference.asMember; return !shaker.isMemberUsed(node); }); @@ -1688,7 +1680,7 @@ class _TreeShakerPass2 extends RemovingTransformer { } @override - TreeNode visitLibrary(Library node, TreeNode removalSentinel) { + TreeNode visitLibrary(Library node, TreeNode? removalSentinel) { node.transformOrRemoveChildren(this); // The transformer API does not iterate over `Library.additionalExports`, // so we manually delete the references to shaken nodes. @@ -1708,12 +1700,12 @@ class _TreeShakerPass2 extends RemovingTransformer { } @override - Typedef visitTypedef(Typedef node, TreeNode removalSentinel) { - return shaker.isTypedefUsed(node) ? node : removalSentinel; + TreeNode visitTypedef(Typedef node, TreeNode? removalSentinel) { + return shaker.isTypedefUsed(node) ? node : removalSentinel!; } @override - Class visitClass(Class node, TreeNode removalSentinel) { + TreeNode visitClass(Class node, TreeNode? removalSentinel) { if (!shaker.isClassUsed(node)) { debugPrint('Dropped class ${node.name}'); // Ensure that kernel file writer will not be able to @@ -1724,7 +1716,7 @@ class _TreeShakerPass2 extends RemovingTransformer { "been repurposed for ${node.reference.node}."); node.reference.canonicalName?.unbind(); Statistics.classesDropped++; - return removalSentinel; // Remove the class. + return removalSentinel!; // Remove the class. } if (!shaker.isClassUsedInType(node)) { @@ -1755,7 +1747,7 @@ class _TreeShakerPass2 extends RemovingTransformer { } @override - Member defaultMember(Member node, TreeNode removalSentinel) { + TreeNode defaultMember(Member node, TreeNode? removalSentinel) { if (!shaker.isMemberUsed(node)) { // Ensure that kernel file writer will not be able to // write a dangling reference to the deleted member. @@ -1767,10 +1759,10 @@ class _TreeShakerPass2 extends RemovingTransformer { node.getterReference.canonicalName?.unbind(); if (node.hasSetter) { assert( - node.setterReference.node == node, + node.setterReference!.node == node, "Trying to remove canonical name from reference on $node which " - "has been repurposed for ${node.setterReference.node}."); - node.setterReference.canonicalName?.unbind(); + "has been repurposed for ${node.setterReference!.node}."); + node.setterReference!.canonicalName?.unbind(); } } else { assert( @@ -1780,13 +1772,13 @@ class _TreeShakerPass2 extends RemovingTransformer { node.reference.canonicalName?.unbind(); } Statistics.membersDropped++; - return removalSentinel; + return removalSentinel!; } if (!shaker.isMemberBodyReachable(node)) { if (node is Procedure) { // Remove body of unused member. - if (!node.isStatic && node.enclosingClass.isAbstract) { + if (!node.isStatic && node.enclosingClass!.isAbstract) { node.isAbstract = true; node.function.body = null; } else { @@ -1829,7 +1821,7 @@ class _TreeShakerPass2 extends RemovingTransformer { } @override - Extension visitExtension(Extension node, TreeNode removalSentinel) { + TreeNode visitExtension(Extension node, TreeNode? removalSentinel) { if (shaker.isExtensionUsed(node)) { int writeIndex = 0; for (int i = 0; i < node.members.length; ++i) { @@ -1840,7 +1832,7 @@ class _TreeShakerPass2 extends RemovingTransformer { // member was already removed or it will be removed later. final Reference memberReference = descriptor.member; final bool isBound = memberReference.node != null; - if (isBound && shaker.isMemberUsed(memberReference.node)) { + if (isBound && shaker.isMemberUsed(memberReference.asMember)) { node.members[writeIndex++] = descriptor; } } @@ -1850,7 +1842,7 @@ class _TreeShakerPass2 extends RemovingTransformer { assert(node.members.length > 0); return node; } - return removalSentinel; + return removalSentinel!; } void _makeUnreachableBody(FunctionNode function) { @@ -1871,7 +1863,7 @@ class _TreeShakerPass2 extends RemovingTransformer { } @override - TreeNode defaultTreeNode(TreeNode node, TreeNode removalSentinel) { + TreeNode defaultTreeNode(TreeNode node, TreeNode? removalSentinel) { return node; // Do not traverse into other nodes. } } diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart index 588512cae2c..3ed7b9bf78e 100644 --- a/pkg/vm/lib/transformations/type_flow/types.dart +++ b/pkg/vm/lib/transformations/type_flow/types.dart @@ -2,10 +2,7 @@ // 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.9 - /// Declares the type system used by global type flow analysis. -library vm.transformations.type_flow.types; import 'dart:core' hide Type; @@ -138,10 +135,7 @@ abstract class TypeHierarchy extends TypesBuilder /// values can flow through the program. Type specializeTypeCone(TFClass base, {bool allowWideCone = false}); - Type _cachedIntType; - Type get intType { - return _cachedIntType ??= fromStaticType(coreTypes.intLegacyRawType, true); - } + late final Type intType = fromStaticType(coreTypes.intLegacyRawType, true); } /// Base class for type expressions. @@ -151,7 +145,7 @@ abstract class TypeExpr { /// Returns computed type of this type expression. /// [types] is the list of types computed for the statements in the summary. - Type getComputedType(List types); + Type getComputedType(List types); } /// Kind of a subtype test: subtype/cast/'as' test or instance check/'is' test. @@ -174,7 +168,7 @@ abstract class Type extends TypeExpr { /// Create a type representing arbitrary nullable object (`dynamic`). factory Type.nullableAny() => new NullableType(const AnyType()); - Class getConcreteClass(TypeHierarchy typeHierarchy) => null; + Class? getConcreteClass(TypeHierarchy typeHierarchy) => null; bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) => false; @@ -185,7 +179,7 @@ abstract class Type extends TypeExpr { RuntimeType runtimeType, SubtypeTestKind kind); @override - Type getComputedType(List types) => this; + Type getComputedType(List types) => this; /// Order of precedence for evaluation of union/intersection. int get order; @@ -260,7 +254,6 @@ class NullableType extends Type { final Type baseType; NullableType(this.baseType) { - assert(baseType != null); assert(baseType is! NullableType); } @@ -387,7 +380,9 @@ class AnyType extends Type { class SetType extends Type { /// List of concrete types, sorted by classId. final List types; - int _hashCode; + + @override + late final int hashCode = _computeHashCode(); /// Creates a new SetType using list of concrete types sorted by classId. SetType(this.types) { @@ -395,9 +390,6 @@ class SetType extends Type { assert(isSorted(types)); } - @override - int get hashCode => _hashCode ??= _computeHashCode(); - int _computeHashCode() { int hash = 1237; for (var t in types) { @@ -470,8 +462,8 @@ class SetType extends Type { return types; } - static List _intersectLists( - List types1, List types2) { + static List _intersectLists(List types1, + List types2, TypeHierarchy typeHierarchy) { int i1 = 0; int i2 = 0; List types = []; @@ -491,9 +483,9 @@ class SetType extends Type { t2.constant == null) { types.add(t1); } else { - final intersect = t1.intersection(t2, null); + final intersect = t1.intersection(t2, typeHierarchy); if (intersect is! EmptyType) { - types.add(intersect); + types.add(intersect as ConcreteType); } } ++i1; @@ -558,7 +550,8 @@ class SetType extends Type { return other.intersection(this, typeHierarchy); } if (other is SetType) { - List list = _intersectLists(types, other.types); + List list = + _intersectLists(types, other.types, typeHierarchy); final size = list.length; if (size == 0) { return const EmptyType(); @@ -594,7 +587,7 @@ class ConeType extends Type { ConeType(this.cls); @override - Class getConcreteClass(TypeHierarchy typeHierarchy) => typeHierarchy + Class? getConcreteClass(TypeHierarchy typeHierarchy) => typeHierarchy .specializeTypeCone(cls, allowWideCone: true) .getConcreteClass(typeHierarchy); @@ -696,7 +689,7 @@ class WideConeType extends ConeType { WideConeType(TFClass cls) : super(cls); @override - Class getConcreteClass(TypeHierarchy typeHierarchy) => null; + Class? getConcreteClass(TypeHierarchy typeHierarchy) => null; @override int get hashCode => (cls.id + 41) & kHashMask; @@ -783,7 +776,9 @@ class WideConeType extends ConeType { /// or `null` object). class ConcreteType extends Type implements Comparable { final TFClass cls; - int _hashCode; + + @override + late final int hashCode = _computeHashCode(); // May be null if there are no type arguments constraints. The type arguments // should represent type sets, i.e. `UnknownType` or `RuntimeType`. The type @@ -796,19 +791,19 @@ class ConcreteType extends Type implements Comparable { // 'numImmediateTypeArgs' is the length of the prefix of 'typeArgs' which // holds the type arguments to the class itself. final int numImmediateTypeArgs; - final List typeArgs; + final List? typeArgs; // May be null if constant value is not inferred. - final Constant constant; + final Constant? constant; - ConcreteType(this.cls, [List typeArgs_, this.constant]) + ConcreteType(this.cls, [List? typeArgs_, this.constant]) : typeArgs = typeArgs_, numImmediateTypeArgs = typeArgs_ != null ? cls.classNode.typeParameters.length : 0 { // TODO(alexmarkov): support closures assert(!cls.classNode.isAbstract); assert(typeArgs == null || cls.classNode.typeParameters.isNotEmpty); - assert(typeArgs == null || typeArgs.any((t) => t is RuntimeType)); + assert(typeArgs == null || typeArgs!.any((t) => t is RuntimeType)); } ConcreteType get raw => cls.concreteType; @@ -839,7 +834,7 @@ class ConcreteType extends Type implements Comparable { if (rhs.typeArguments.isEmpty) return true; - List usableTypeArgs = typeArgs; + List? usableTypeArgs = typeArgs; if (usableTypeArgs == null) { if (cls.classNode.typeParameters.isEmpty) { usableTypeArgs = @@ -862,7 +857,7 @@ class ConcreteType extends Type implements Comparable { } assert(ta is RuntimeType); if (!ta.isSubtypeOfRuntimeType( - typeHierarchy, runtimeType.typeArgs[i], SubtypeTestKind.Subtype)) { + typeHierarchy, runtimeType.typeArgs![i], SubtypeTestKind.Subtype)) { return false; } } @@ -877,29 +872,26 @@ class ConcreteType extends Type implements Comparable { } else { final interfaceOffset = typeHierarchy.genericInterfaceOffsetFor( cls.classNode, typeHierarchy.coreTypes.futureClass); - typeArg = typeArgs[interfaceOffset]; + typeArg = typeArgs![interfaceOffset]; } final RuntimeType lhs = typeArg is RuntimeType ? typeArg : RuntimeType(DynamicType(), null); return lhs.isSubtypeOfRuntimeType( - typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype); + typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype); } else { return isSubtypeOfRuntimeType( - typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype); + typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype); } } return false; } - @override - int get hashCode => _hashCode ??= _computeHashCode(); - int _computeHashCode() { int hash = cls.hashCode ^ 0x1234 & kHashMask; // We only need to hash the first type arguments vector, since the type // arguments of the implemented interfaces are implied by it. for (int i = 0; i < numImmediateTypeArgs; ++i) { - hash = (((hash * 31) & kHashMask) + typeArgs[i].hashCode) & kHashMask; + hash = (((hash * 31) & kHashMask) + typeArgs![i].hashCode) & kHashMask; } hash = ((hash * 31) & kHashMask) + constant.hashCode; return hash; @@ -915,7 +907,7 @@ class ConcreteType extends Type implements Comparable { } if (this.typeArgs != null) { for (int i = 0; i < numImmediateTypeArgs; ++i) { - if (this.typeArgs[i] != other.typeArgs[i]) { + if (this.typeArgs![i] != other.typeArgs![i]) { return false; } } @@ -942,10 +934,10 @@ class ConcreteType extends Type implements Comparable { final StringBuffer buf = new StringBuffer(); buf.write("_T (${cls}"); if (typeArgs != null) { - buf.write("<${typeArgs.take(numImmediateTypeArgs).join(', ')}>"); + buf.write("<${typeArgs!.take(numImmediateTypeArgs).join(', ')}>"); } if (constant != null) { - buf.write(", ${nodeToText(constant)}"); + buf.write(", ${nodeToText(constant!)}"); } buf.write(")"); return buf.toString(); @@ -997,17 +989,21 @@ class ConcreteType extends Type implements Comparable { return this; } - List mergedTypeArgs; - if (typeArgs == null) { - mergedTypeArgs = other.typeArgs; - } else if (other.typeArgs == null) { - mergedTypeArgs = typeArgs; + List? mergedTypeArgs; + final thisTypeArgs = this.typeArgs; + final otherTypeArgs = other.typeArgs; + if (thisTypeArgs == null) { + mergedTypeArgs = otherTypeArgs; + } else if (otherTypeArgs == null) { + mergedTypeArgs = thisTypeArgs; } else { - mergedTypeArgs = new List.filled(typeArgs.length, null); + assert(thisTypeArgs.length == otherTypeArgs.length); + mergedTypeArgs = + new List.filled(thisTypeArgs.length, const EmptyType()); bool hasRuntimeType = false; - for (int i = 0; i < typeArgs.length; ++i) { + for (int i = 0; i < thisTypeArgs.length; ++i) { final merged = - typeArgs[i].intersection(other.typeArgs[i], typeHierarchy); + thisTypeArgs[i].intersection(otherTypeArgs[i], typeHierarchy); if (merged is EmptyType) { return const EmptyType(); } else if (merged is RuntimeType) { @@ -1020,7 +1016,7 @@ class ConcreteType extends Type implements Comparable { } } - Constant mergedConstant; + Constant? mergedConstant; if (constant == null) { mergedConstant = other.constant; } else if (other.constant == null || constant == other.constant) { @@ -1062,7 +1058,7 @@ class RuntimeType extends Type { final DartType _type; // Doesn't contain type args. final int numImmediateTypeArgs; - final List typeArgs; + final List? typeArgs; RuntimeType(DartType type, this.typeArgs) : _type = type, @@ -1070,14 +1066,12 @@ class RuntimeType extends Type { ? type.classNode.typeParameters.length : (type is FutureOrType ? 1 : 0) { if (_type is InterfaceType && numImmediateTypeArgs > 0) { - assert(typeArgs != null); - assert(typeArgs.length >= numImmediateTypeArgs); + assert(typeArgs!.length >= numImmediateTypeArgs); assert((_type as InterfaceType) .typeArguments .every((t) => t == const DynamicType())); } else if (_type is FutureOrType) { - assert(typeArgs != null); - assert(typeArgs.length >= numImmediateTypeArgs); + assert(typeArgs!.length >= numImmediateTypeArgs); DartType typeArgument = (_type as FutureOrType).typeArgument; assert(typeArgument == const DynamicType()); } else { @@ -1098,25 +1092,27 @@ class RuntimeType extends Type { final type = _type; if (type is InterfaceType && typeArgs != null) { final klass = type.classNode; - final typeArguments = typeArgs + final typeArguments = typeArgs! .take(klass.typeParameters.length) .map((pt) => pt.representedType) .toList(); return new InterfaceType(klass, type.nullability, typeArguments); } else if (type is FutureOrType) { - return new FutureOrType(typeArgs[0].representedType, type.nullability); + return new FutureOrType(typeArgs![0].representedType, type.nullability); } else { return type; } } @override - int get hashCode { + late final int hashCode = _computeHashCode(); + + int _computeHashCode() { int hash = _type.hashCode ^ 0x1234 & kHashMask; // Only hash by the type arguments of the class. The type arguments of // supertypes are are implied by them. for (int i = 0; i < numImmediateTypeArgs; ++i) { - hash = (((hash * 31) & kHashMask) + typeArgs[i].hashCode) & kHashMask; + hash = (((hash * 31) & kHashMask) + typeArgs![i].hashCode) & kHashMask; } return hash; } @@ -1127,7 +1123,7 @@ class RuntimeType extends Type { if (other is RuntimeType) { if (other._type != _type) return false; assert(numImmediateTypeArgs == other.numImmediateTypeArgs); - return typeArgs == null || listEquals(typeArgs, other.typeArgs); + return typeArgs == null || listEquals(typeArgs!, other.typeArgs!); } return false; } @@ -1139,7 +1135,7 @@ class RuntimeType extends Type { : "${nodeToText(_type)}"; final typeArgsStrs = (numImmediateTypeArgs == 0) ? "" - : "<${typeArgs.take(numImmediateTypeArgs).map((t) => "$t").join(", ")}>"; + : "<${typeArgs!.take(numImmediateTypeArgs).map((t) => "$t").join(", ")}>"; final nullability = _type.nullability.suffix; return "$head$typeArgsStrs$nullability"; } @@ -1200,15 +1196,15 @@ class RuntimeType extends Type { if (_type is InterfaceType) { Class thisClass = (_type as InterfaceType).classNode; if (thisClass == typeHierarchy.coreTypes.futureClass) { - return typeArgs[0].isSubtypeOfRuntimeType( - typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype); + return typeArgs![0].isSubtypeOfRuntimeType( + typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype); } else { return isSubtypeOfRuntimeType( - typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype); + typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype); } } else if (_type is FutureOrType) { - return typeArgs[0].isSubtypeOfRuntimeType( - typeHierarchy, runtimeType.typeArgs[0], SubtypeTestKind.Subtype); + return typeArgs![0].isSubtypeOfRuntimeType( + typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype); } } @@ -1236,7 +1232,7 @@ class RuntimeType extends Type { return true; } - List usableTypeArgs = typeArgs; + List? usableTypeArgs = typeArgs; if (usableTypeArgs == null) { assert(thisClass.typeParameters.isEmpty); usableTypeArgs = @@ -1248,7 +1244,7 @@ class RuntimeType extends Type { runtimeType.numImmediateTypeArgs); for (int i = 0; i < runtimeType.numImmediateTypeArgs; ++i) { if (!usableTypeArgs[interfaceOffset + i].isSubtypeOfRuntimeType( - typeHierarchy, runtimeType.typeArgs[i], SubtypeTestKind.Subtype)) { + typeHierarchy, runtimeType.typeArgs![i], SubtypeTestKind.Subtype)) { return false; } } diff --git a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart index 723e673a330..682cf582227 100644 --- a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart +++ b/pkg/vm/lib/transformations/type_flow/unboxing_info.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.9 - import 'package:kernel/ast.dart'; import 'package:kernel/core_types.dart'; import 'package:kernel/external_name.dart' show getExternalName; @@ -30,12 +28,12 @@ class UnboxingInfoManager { _coreTypes = typeFlowAnalysis.environment.coreTypes, _nativeCodeOracle = typeFlowAnalysis.nativeCodeOracle; - UnboxingInfoMetadata getUnboxingInfoOfMember(Member member) { - final UnboxingInfoMetadata info = _memberInfo[member]; + UnboxingInfoMetadata? getUnboxingInfoOfMember(Member member) { + final UnboxingInfoMetadata? info = _memberInfo[member]; if (member is Procedure && member.isGetter) { // Remove placeholder parameter info slot for setters that the getter is // grouped with. - return UnboxingInfoMetadata(0)..returnInfo = info.returnInfo; + return UnboxingInfoMetadata(0)..returnInfo = info!.returnInfo; } return info; } @@ -81,8 +79,8 @@ class UnboxingInfoManager { ? (member.hasSetter ? 1 : 0) : member is Procedure && member.isGetter ? 1 - : member.function.requiredParameterCount; - UnboxingInfoMetadata info; + : member.function!.requiredParameterCount; + UnboxingInfoMetadata? info; if (member.isInstanceMember) { int selectorId = member is Field || member is Procedure && member.isGetter @@ -121,20 +119,18 @@ class UnboxingInfoManager { void _updateUnboxingInfoOfMember( Member member, TypeFlowAnalysis typeFlowAnalysis) { if (typeFlowAnalysis.isMemberUsed(member)) { - final UnboxingInfoMetadata unboxingInfo = _memberInfo[member]; + final UnboxingInfoMetadata unboxingInfo = _memberInfo[member]!; if (_cannotUnbox(member)) { unboxingInfo.unboxedArgsInfo.length = 0; unboxingInfo.returnInfo = UnboxingInfoMetadata.kBoxed; return; } if (member is Procedure || member is Constructor) { - final Args argTypes = typeFlowAnalysis.argumentTypes(member); - assert(argTypes != null); - + final Args argTypes = typeFlowAnalysis.argumentTypes(member)!; final int firstParamIndex = numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0); - final positionalParams = member.function.positionalParameters; + final positionalParams = member.function!.positionalParameters; assert(argTypes.positionalCount == firstParamIndex + positionalParams.length); diff --git a/pkg/vm/lib/transformations/type_flow/utils.dart b/pkg/vm/lib/transformations/type_flow/utils.dart index b04e69ece45..c85dfc7f971 100644 --- a/pkg/vm/lib/transformations/type_flow/utils.dart +++ b/pkg/vm/lib/transformations/type_flow/utils.dart @@ -2,12 +2,11 @@ // 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.9 - /// Declares miscellaneous utility functions and constants for type flow /// analysis. library vm.transformations.type_flow.utils; +import 'package:collection/collection.dart' show IterableExtension; import 'package:kernel/ast.dart'; import 'package:kernel/src/printer.dart'; @@ -123,9 +122,8 @@ bool isSorted(List list) { return true; } -VariableDeclaration findNamedParameter(FunctionNode function, String name) { - return function.namedParameters - .firstWhere((p) => p.name == name, orElse: () => null); +VariableDeclaration? findNamedParameter(FunctionNode function, String name) { + return function.namedParameters.firstWhereOrNull((p) => p.name == name); } class Histogram { @@ -143,7 +141,7 @@ class Histogram { print( '-------------------------------------------------------------------'); List keys = values.keys.toList(); - keys.sort((k1, k2) => values[k1].compareTo(values[k2])); + keys.sort((k1, k2) => values[k1]!.compareTo(values[k2]!)); final cut = keys.length < n ? 0 : keys.length - n; for (int i = keys.length - 1; i >= cut; --i) { final k = keys[i]; @@ -376,7 +374,7 @@ const nullabilitySuffix = { }; extension NullabilitySuffix on Nullability { - String get suffix => nullabilitySuffix[this]; + String get suffix => nullabilitySuffix[this]!; } bool mayHaveSideEffects(Expression node) { diff --git a/pkg/vm/pubspec.yaml b/pkg/vm/pubspec.yaml index f57cf3893a0..0e78a099b10 100644 --- a/pkg/vm/pubspec.yaml +++ b/pkg/vm/pubspec.yaml @@ -18,6 +18,7 @@ dependencies: meta: path: ../meta package_config: any + collection: ^1.15.0 dev_dependencies: expect: diff --git a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart index f9ea8d7678d..2e253440810 100644 --- a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart +++ b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart @@ -60,7 +60,7 @@ class FakeEntryPointsListener implements EntryPointsListener { void recordMemberCalledViaThis(Member target) {} @override - void recordTearOff(Procedure target) {} + void recordTearOff(Member target) {} } class PrintSummaries extends RecursiveVisitor { @@ -78,7 +78,7 @@ class PrintSummaries extends RecursiveVisitor { typesBuilder, new NativeCodeOracle( null, new ConstantPragmaAnnotationParser(coreTypes)), - new GenericInterfacesInfoImpl(hierarchy), + new GenericInterfacesInfoImpl(coreTypes, hierarchy), /*_protobufHandler=*/ null); }