Track RTI dependency through instantiations
Closes #33093
Change-Id: Ia7d9cd1235cd4fe60858f37533689f5eeb600540
Reviewed-on: https://dart-review.googlesource.com/59400
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 208d40f..a0c99af 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -7,6 +7,7 @@
import '../common_elements.dart';
import '../elements/entities.dart';
import '../elements/types.dart' show DartType, InterfaceType;
+import '../universe/feature.dart';
import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
import '../universe/world_impact.dart'
show WorldImpact, WorldImpactBuilderImpl, WorldImpactVisitor;
@@ -29,7 +30,10 @@
bool get usesInterceptor => false;
- Iterable<AsyncMarker> get asyncMarkers => <AsyncMarker>[];
+ Iterable<AsyncMarker> get asyncMarkers => const <AsyncMarker>[];
+
+ Iterable<GenericInstantiation> get genericInstantiations =>
+ const <GenericInstantiation>[];
}
class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
@@ -38,6 +42,7 @@
List<Set<ClassEntity>> _specializedGetInterceptors;
bool _usesInterceptor = false;
EnumSet<AsyncMarker> _asyncMarkers;
+ Set<GenericInstantiation> _genericInstantiations;
_CodegenImpact();
@@ -49,9 +54,7 @@
void registerTypeVariableBoundsSubtypeCheck(
DartType subtype, DartType supertype) {
- if (_typeVariableBoundsSubtypeChecks == null) {
- _typeVariableBoundsSubtypeChecks = new Setlet<Pair<DartType, DartType>>();
- }
+ _typeVariableBoundsSubtypeChecks ??= new Setlet<Pair<DartType, DartType>>();
_typeVariableBoundsSubtypeChecks
.add(new Pair<DartType, DartType>(subtype, supertype));
}
@@ -63,9 +66,7 @@
}
void registerConstSymbol(String name) {
- if (_constSymbols == null) {
- _constSymbols = new Setlet<String>();
- }
+ _constSymbols ??= new Setlet<String>();
_constSymbols.add(name);
}
@@ -74,9 +75,7 @@
}
void registerSpecializedGetInterceptor(Set<ClassEntity> classes) {
- if (_specializedGetInterceptors == null) {
- _specializedGetInterceptors = <Set<ClassEntity>>[];
- }
+ _specializedGetInterceptors ??= <Set<ClassEntity>>[];
_specializedGetInterceptors.add(classes);
}
@@ -93,9 +92,7 @@
bool get usesInterceptor => _usesInterceptor;
void registerAsyncMarker(AsyncMarker asyncMarker) {
- if (_asyncMarkers == null) {
- _asyncMarkers = new EnumSet<AsyncMarker>();
- }
+ _asyncMarkers ??= new EnumSet<AsyncMarker>();
_asyncMarkers.add(asyncMarker);
}
@@ -104,6 +101,16 @@
? _asyncMarkers.iterable(AsyncMarker.values)
: const <AsyncMarker>[];
}
+
+ void registerGenericInstantiation(GenericInstantiation instantiation) {
+ _genericInstantiations ??= new Set<GenericInstantiation>();
+ _genericInstantiations.add(instantiation);
+ }
+
+ @override
+ Iterable<GenericInstantiation> get genericInstantiations {
+ return _genericInstantiations ?? const <GenericInstantiation>[];
+ }
}
// TODO(johnniwinther): Split this class into interface and implementation.
@@ -169,6 +176,10 @@
void registerAsyncMarker(AsyncMarker asyncMarker) {
worldImpact.registerAsyncMarker(asyncMarker);
}
+
+ void registerGenericInstantiation(GenericInstantiation instantiation) {
+ worldImpact.registerGenericInstantiation(instantiation);
+ }
}
/// [WorkItem] used exclusively by the [CodegenEnqueuer].
diff --git a/pkg/compiler/lib/src/common/resolution.dart b/pkg/compiler/lib/src/common/resolution.dart
index b0eb1ac..cf2ed2c 100644
--- a/pkg/compiler/lib/src/common/resolution.dart
+++ b/pkg/compiler/lib/src/common/resolution.dart
@@ -21,4 +21,7 @@
Iterable<ClassEntity> get seenClasses => const <ClassEntity>[];
Iterable<dynamic> get nativeData => const <dynamic>[];
+
+ Iterable<GenericInstantiation> get genericInstantiations =>
+ const <GenericInstantiation>[];
}
diff --git a/pkg/compiler/lib/src/js_backend/backend_usage.dart b/pkg/compiler/lib/src/js_backend/backend_usage.dart
index 8af1da3..7e2065e 100644
--- a/pkg/compiler/lib/src/js_backend/backend_usage.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_usage.dart
@@ -43,9 +43,6 @@
/// `true` if `noSuchMethod` is used.
bool get isNoSuchMethodUsed;
-
- /// `true` if generic instantiation is used.
- bool get isGenericInstantiationUsed;
}
abstract class BackendUsageBuilder {
@@ -83,9 +80,6 @@
/// `true` if `noSuchMethod` is used.
bool isNoSuchMethodUsed;
- /// `true` if generic instantiation is used.
- bool isGenericInstantiationUsed;
-
BackendUsage close();
}
@@ -122,9 +116,6 @@
/// `true` if `noSuchMethod` is used.
bool isNoSuchMethodUsed = false;
- /// `true` if generic instantiation is used.
- bool isGenericInstantiationUsed = false;
-
BackendUsageBuilderImpl(this._commonElements);
@override
@@ -280,8 +271,7 @@
isRuntimeTypeUsed: isRuntimeTypeUsed,
isFunctionApplyUsed: isFunctionApplyUsed,
isMirrorsUsed: isMirrorsUsed,
- isNoSuchMethodUsed: isNoSuchMethodUsed,
- isGenericInstantiationUsed: isGenericInstantiationUsed);
+ isNoSuchMethodUsed: isNoSuchMethodUsed);
}
}
@@ -317,9 +307,6 @@
/// `true` if `noSuchMethod` is used.
final bool isNoSuchMethodUsed;
- /// `true` if generic instantiation is used.
- final bool isGenericInstantiationUsed;
-
BackendUsageImpl(
{Set<FunctionEntity> globalFunctionDependencies,
Set<ClassEntity> globalClassDependencies,
@@ -332,8 +319,7 @@
this.isRuntimeTypeUsed,
this.isFunctionApplyUsed,
this.isMirrorsUsed,
- this.isNoSuchMethodUsed,
- this.isGenericInstantiationUsed})
+ this.isNoSuchMethodUsed})
: this._globalFunctionDependencies = globalFunctionDependencies,
this._globalClassDependencies = globalClassDependencies,
this._helperFunctionsUsed = helperFunctionsUsed,
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index 70e8d1a..8d6506d 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -104,10 +104,6 @@
new TypeUse.instantiation(_commonElements.nullType));
registerImpact(_impacts.nullLiteral);
break;
- case Feature.GENERIC_INSTANTIATION:
- registerImpact(_impacts.genericInstantiation);
- _backendUsageBuilder.isGenericInstantiationUsed = true;
- break;
case Feature.LAZY_FIELD:
registerImpact(_impacts.lazyField);
break;
@@ -292,6 +288,14 @@
_classHierarchyBuilder.registerClass(classEntity);
}
+ if (worldImpact.genericInstantiations.isNotEmpty) {
+ registerImpact(_impacts.genericInstantiation);
+ for (GenericInstantiation instantiation
+ in worldImpact.genericInstantiations) {
+ _rtiNeedBuilder.registerGenericInstantiation(instantiation);
+ }
+ }
+
return transformed;
}
@@ -460,6 +464,10 @@
}
}
+ for (GenericInstantiation instantiation in impact.genericInstantiations) {
+ _rtiChecksBuilder.registerGenericInstantiation(instantiation);
+ }
+
// TODO(johnniwinther): Remove eager registration.
return transformed;
}
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index d637cb1..332926b 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -13,6 +13,7 @@
import '../js/js.dart' show js;
import '../js_emitter/js_emitter.dart' show Emitter;
import '../options.dart';
+import '../universe/feature.dart';
import '../universe/selector.dart';
import '../universe/world_builder.dart';
import '../world.dart' show JClosedWorld, KClosedWorld;
@@ -95,6 +96,13 @@
/// Returns `true` if a dynamic call of [selector] needs to pass type
/// arguments.
bool selectorNeedsTypeArguments(Selector selector);
+
+ /// Returns `true` if a generic instantiation on an expression of type
+ /// [functionType] with the given [typeArgumentCount] needs to pass type
+ /// arguments.
+ // TODO(johnniwinther): Use [functionType].
+ bool instantiationNeedsTypeArguments(
+ DartType functionType, int typeArgumentCount);
}
class TrivialRuntimeTypesNeed implements RuntimeTypesNeed {
@@ -117,6 +125,12 @@
@override
bool selectorNeedsTypeArguments(Selector selector) => true;
+
+ @override
+ bool instantiationNeedsTypeArguments(
+ DartType functionType, int typeArgumentCount) {
+ return true;
+ }
}
/// Interface for computing classes and methods that need runtime types.
@@ -131,6 +145,9 @@
/// literal.
void registerLocalFunctionUsingTypeVariableLiteral(Local localFunction);
+ /// Registers that a generic [instantiation] is used.
+ void registerGenericInstantiation(GenericInstantiation instantiation);
+
/// Computes the [RuntimeTypesNeed] for the data registered with this builder.
RuntimeTypesNeed computeRuntimeTypesNeed(
ResolutionWorldBuilder resolutionWorldBuilder,
@@ -151,6 +168,9 @@
void registerLocalFunctionUsingTypeVariableLiteral(Local localFunction) {}
@override
+ void registerGenericInstantiation(GenericInstantiation instantiation) {}
+
+ @override
RuntimeTypesNeed computeRuntimeTypesNeed(
ResolutionWorldBuilder resolutionWorldBuilder,
KClosedWorld closedWorld,
@@ -194,6 +214,9 @@
void registerTypeVariableBoundsSubtypeCheck(
DartType typeArgument, DartType bound);
+ /// Registers that a generic [instantiation] is used.
+ void registerGenericInstantiation(GenericInstantiation instantiation);
+
/// Computes the [RuntimeTypesChecks] for the data in this builder.
RuntimeTypesChecks computeRequiredChecks(
CodegenWorldBuilder codegenWorldBuilder, CompilerOptions options);
@@ -215,6 +238,9 @@
DartType typeArgument, DartType bound) {}
@override
+ void registerGenericInstantiation(GenericInstantiation instantiation) {}
+
+ @override
RuntimeTypesChecks computeRequiredChecks(
CodegenWorldBuilder codegenWorldBuilder, CompilerOptions options) {
rtiChecksBuilderClosed = true;
@@ -700,6 +726,7 @@
final Set<Local> localFunctionsNeedingSignature;
final Set<Local> localFunctionsNeedingTypeArguments;
final Set<Selector> selectorsNeedingTypeArguments;
+ final Set<int> instantiationsNeedingTypeArguments;
RuntimeTypesNeedImpl(
this._elementEnvironment,
@@ -709,7 +736,8 @@
this.methodsNeedingTypeArguments,
this.localFunctionsNeedingSignature,
this.localFunctionsNeedingTypeArguments,
- this.selectorsNeedingTypeArguments);
+ this.selectorsNeedingTypeArguments,
+ this.instantiationsNeedingTypeArguments);
bool checkClass(covariant ClassEntity cls) => true;
@@ -749,6 +777,12 @@
if (_backendUsage.isRuntimeTypeUsed) return true;
return selectorsNeedingTypeArguments.contains(selector);
}
+
+ @override
+ bool instantiationNeedsTypeArguments(
+ DartType functionType, int typeArgumentCount) {
+ return instantiationsNeedingTypeArguments.contains(typeArgumentCount);
+ }
}
class TypeVariableTests {
@@ -756,6 +790,7 @@
Map<ClassEntity, ClassNode> _classes = <ClassEntity, ClassNode>{};
Map<Entity, MethodNode> _methods = <Entity, MethodNode>{};
Map<Selector, Set<Entity>> _appliedSelectorMap;
+ Map<GenericInstantiation, Set<Entity>> _instantiationMap;
/// All explicit is-tests.
final Set<DartType> explicitIsChecks;
@@ -763,11 +798,17 @@
/// All implicit is-tests.
final Set<DartType> implicitIsChecks = new Set<DartType>();
- TypeVariableTests(ElementEnvironment elementEnvironment,
- CommonElements commonElements, DartTypes types, WorldBuilder worldBuilder,
+ TypeVariableTests(
+ ElementEnvironment elementEnvironment,
+ CommonElements commonElements,
+ DartTypes types,
+ WorldBuilder worldBuilder,
+ Set<GenericInstantiation> genericInstantiations,
{bool forRtiNeeds: true})
: explicitIsChecks = new Set<DartType>.from(worldBuilder.isChecks) {
- _setupDependencies(elementEnvironment, commonElements, worldBuilder);
+ _setupDependencies(
+ elementEnvironment, commonElements, worldBuilder, genericInstantiations,
+ forRtiNeeds: forRtiNeeds);
_propagateTests(commonElements, elementEnvironment, worldBuilder);
if (forRtiNeeds) {
_propagateLiterals(elementEnvironment, worldBuilder);
@@ -867,6 +908,13 @@
_appliedSelectorMap.forEach(f);
}
+ /// Calls [f] for each generic instantiation that applies to generic
+ /// closurized [targets].
+ void forEachGenericInstantiation(
+ void f(GenericInstantiation instantiation, Set<Entity> targets)) {
+ _instantiationMap?.forEach(f);
+ }
+
ClassNode _getClassNode(ClassEntity cls) {
return _classes.putIfAbsent(cls, () {
ClassNode node = new ClassNode(cls);
@@ -905,8 +953,12 @@
});
}
- void _setupDependencies(ElementEnvironment elementEnvironment,
- CommonElements commonElements, WorldBuilder worldBuilder) {
+ void _setupDependencies(
+ ElementEnvironment elementEnvironment,
+ CommonElements commonElements,
+ WorldBuilder worldBuilder,
+ Set<GenericInstantiation> genericInstantiations,
+ {bool forRtiNeeds: true}) {
/// Register that if `node.entity` needs type arguments then so do entities
/// whose type variables occur in [type].
///
@@ -1018,6 +1070,31 @@
worldBuilder.closurizedStatics.forEach(processEntity);
worldBuilder.userNoSuchMethods.forEach(processEntity);
});
+
+ for (GenericInstantiation instantiation in genericInstantiations) {
+ void processEntity(Entity entity) {
+ MethodNode node =
+ _getMethodNode(elementEnvironment, worldBuilder, entity);
+ if (node.parameterStructure.typeParameters ==
+ instantiation.typeArguments.length) {
+ if (forRtiNeeds) {
+ _instantiationMap ??= <GenericInstantiation, Set<Entity>>{};
+ _instantiationMap
+ .putIfAbsent(instantiation, () => new Set<Entity>())
+ .add(entity);
+ }
+ for (DartType type in instantiation.typeArguments) {
+ // Register that if `node.entity` needs type arguments then so do
+ // the entities that declare type variables occurring in [type].
+ registerDependencies(node, type);
+ }
+ }
+ }
+
+ worldBuilder.closurizedMembers.forEach(processEntity);
+ worldBuilder.closurizedStatics.forEach(processEntity);
+ worldBuilder.genericLocalFunctions.forEach(processEntity);
+ }
}
void _propagateTests(CommonElements commonElements,
@@ -1339,6 +1416,12 @@
Map<Selector, Set<Entity>> selectorsNeedingTypeArgumentsForTesting;
+ Map<GenericInstantiation, Set<Entity>>
+ instantiationsNeedingTypeArgumentsForTesting;
+
+ final Set<GenericInstantiation> _genericInstantiations =
+ new Set<GenericInstantiation>();
+
TypeVariableTests typeVariableTestsForTesting;
RuntimeTypesNeedBuilderImpl(this._elementEnvironment, DartTypes types)
@@ -1360,6 +1443,11 @@
}
@override
+ void registerGenericInstantiation(GenericInstantiation instantiation) {
+ _genericInstantiations.add(instantiation);
+ }
+
+ @override
RuntimeTypesNeed computeRuntimeTypesNeed(
ResolutionWorldBuilder resolutionWorldBuilder,
KClosedWorld closedWorld,
@@ -1368,7 +1456,8 @@
closedWorld.elementEnvironment,
closedWorld.commonElements,
closedWorld.dartTypes,
- resolutionWorldBuilder);
+ resolutionWorldBuilder,
+ _genericInstantiations);
Set<ClassEntity> classesNeedingTypeArguments = new Set<ClassEntity>();
Set<FunctionEntity> methodsNeedingSignature = new Set<FunctionEntity>();
Set<FunctionEntity> methodsNeedingTypeArguments = new Set<FunctionEntity>();
@@ -1440,8 +1529,9 @@
if (potentialSubtypeOf == null ||
closedWorld.dartTypes.isPotentialSubtype(
functionType, potentialSubtypeOf,
- assumeInstantiations:
- closedWorld.backendUsage.isGenericInstantiationUsed)) {
+ // TODO(johnniwinther): Use register generic instantiations
+ // instead.
+ assumeInstantiations: _genericInstantiations.isNotEmpty)) {
functionType.forEachTypeVariable((TypeVariableType typeVariable) {
Entity typeDeclaration = typeVariable.element.typeDeclaration;
if (!processedEntities.contains(typeDeclaration)) {
@@ -1571,6 +1661,28 @@
}
}
});
+ Set<int> instantiationsNeedingTypeArguments = new Set<int>();
+ typeVariableTests.forEachGenericInstantiation(
+ (GenericInstantiation instantiation, Set<Entity> targets) {
+ for (Entity target in targets) {
+ if (methodsNeedingTypeArguments.contains(target) ||
+ localFunctionsNeedingTypeArguments.contains(target)) {
+ // TODO(johnniwinther): Use the static type of the instantiated
+ // expression.
+ instantiationsNeedingTypeArguments
+ .add(instantiation.typeArguments.length);
+ if (cacheRtiDataForTesting) {
+ instantiationsNeedingTypeArgumentsForTesting ??=
+ <GenericInstantiation, Set<Entity>>{};
+ instantiationsNeedingTypeArgumentsForTesting
+ .putIfAbsent(instantiation, () => new Set<Entity>())
+ .add(target);
+ } else {
+ return;
+ }
+ }
+ }
+ });
if (cacheRtiDataForTesting) {
typeVariableTestsForTesting = typeVariableTests;
@@ -1594,9 +1706,11 @@
localFunctionsNeedingTypeArguments.forEach((e) => print(' $e'));
print('------------------------------------------------------------------');
print('selectorsNeedingTypeArguments:');
- selectorsNeedingTypeArguments.forEach((e) => print(' $e'));*/
+ selectorsNeedingTypeArguments.forEach((e) => print(' $e'));
+ print('instantiationsNeedingTypeArguments: '
+ '$instantiationsNeedingTypeArguments');*/
- return _createRuntimeTypesNeed(
+ return new RuntimeTypesNeedImpl(
_elementEnvironment,
closedWorld.backendUsage,
classesNeedingTypeArguments,
@@ -1604,27 +1718,8 @@
methodsNeedingTypeArguments,
localFunctionsNeedingSignature,
localFunctionsNeedingTypeArguments,
- selectorsNeedingTypeArguments);
- }
-
- RuntimeTypesNeed _createRuntimeTypesNeed(
- ElementEnvironment elementEnvironment,
- BackendUsage backendUsage,
- Set<ClassEntity> classesNeedingTypeArguments,
- Set<FunctionEntity> methodsNeedingSignature,
- Set<FunctionEntity> methodsNeedingTypeArguments,
- Set<Local> localFunctionsNeedingSignature,
- Set<Local> localFunctionsNeedingTypeArguments,
- Set<Selector> selectorsNeedingTypeArguments) {
- return new RuntimeTypesNeedImpl(
- _elementEnvironment,
- backendUsage,
- classesNeedingTypeArguments,
- methodsNeedingSignature,
- methodsNeedingTypeArguments,
- localFunctionsNeedingSignature,
- localFunctionsNeedingTypeArguments,
- selectorsNeedingTypeArguments);
+ selectorsNeedingTypeArguments,
+ instantiationsNeedingTypeArguments);
}
}
@@ -1672,6 +1767,9 @@
Map<ClassEntity, ClassUse> classUseMapForTesting;
+ final Set<GenericInstantiation> _genericInstantiations =
+ new Set<GenericInstantiation>();
+
@override
void registerTypeVariableBoundsSubtypeCheck(
DartType typeArgument, DartType bound) {
@@ -1679,10 +1777,19 @@
checkedBounds.add(bound);
}
+ @override
+ void registerGenericInstantiation(GenericInstantiation instantiation) {
+ _genericInstantiations.add(instantiation);
+ }
+
RuntimeTypesChecks computeRequiredChecks(
CodegenWorldBuilder codegenWorldBuilder, CompilerOptions options) {
TypeVariableTests typeVariableTests = new TypeVariableTests(
- _elementEnvironment, _commonElements, _types, codegenWorldBuilder,
+ _elementEnvironment,
+ _commonElements,
+ _types,
+ codegenWorldBuilder,
+ _genericInstantiations,
forRtiNeeds: false);
Set<DartType> explicitIsChecks = typeVariableTests.explicitIsChecks;
Set<DartType> implicitIsChecks = typeVariableTests.implicitIsChecks;
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index b1c32aa..e6cd967 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -199,6 +199,13 @@
return true;
}
break;
+ case VariableUseKind.instantiationTypeArgument:
+ // TODO(johnniwinther): Use the static type of the expression.
+ if (rtiNeed.instantiationNeedsTypeArguments(
+ null, usage.instantiation.typeArguments.length)) {
+ return true;
+ }
+ break;
}
}
return false;
@@ -428,6 +435,9 @@
/// A type variable in a field type.
fieldType,
+
+ /// A type argument of an generic instantiation.
+ instantiationTypeArgument,
}
class VariableUse {
@@ -436,21 +446,25 @@
final ir.TreeNode /*ir.FunctionDeclaration|ir.FunctionExpression*/
localFunction;
final ir.MethodInvocation invocation;
+ final ir.Instantiation instantiation;
const VariableUse._simple(this.kind)
: this.member = null,
this.localFunction = null,
- this.invocation = null;
+ this.invocation = null,
+ this.instantiation = null;
VariableUse.memberParameter(this.member)
: this.kind = VariableUseKind.memberParameter,
this.localFunction = null,
- this.invocation = null;
+ this.invocation = null,
+ this.instantiation = null;
VariableUse.localParameter(this.localFunction)
: this.kind = VariableUseKind.localParameter,
this.member = null,
- this.invocation = null {
+ this.invocation = null,
+ this.instantiation = null {
assert(localFunction is ir.FunctionDeclaration ||
localFunction is ir.FunctionExpression);
}
@@ -458,12 +472,14 @@
VariableUse.memberReturnType(this.member)
: this.kind = VariableUseKind.memberReturnType,
this.localFunction = null,
- this.invocation = null;
+ this.invocation = null,
+ this.instantiation = null;
VariableUse.localReturnType(this.localFunction)
: this.kind = VariableUseKind.localReturnType,
this.member = null,
- this.invocation = null {
+ this.invocation = null,
+ this.instantiation = null {
assert(localFunction is ir.FunctionDeclaration ||
localFunction is ir.FunctionExpression);
}
@@ -471,25 +487,35 @@
VariableUse.constructorTypeArgument(this.member)
: this.kind = VariableUseKind.constructorTypeArgument,
this.localFunction = null,
- this.invocation = null;
+ this.invocation = null,
+ this.instantiation = null;
VariableUse.staticTypeArgument(this.member)
: this.kind = VariableUseKind.staticTypeArgument,
this.localFunction = null,
- this.invocation = null;
+ this.invocation = null,
+ this.instantiation = null;
VariableUse.instanceTypeArgument(this.invocation)
: this.kind = VariableUseKind.instanceTypeArgument,
this.member = null,
- this.localFunction = null;
+ this.localFunction = null,
+ this.instantiation = null;
VariableUse.localTypeArgument(this.localFunction, this.invocation)
: this.kind = VariableUseKind.localTypeArgument,
- this.member = null {
+ this.member = null,
+ this.instantiation = null {
assert(localFunction is ir.FunctionDeclaration ||
localFunction is ir.FunctionExpression);
}
+ VariableUse.instantiationTypeArgument(this.instantiation)
+ : this.kind = VariableUseKind.instantiationTypeArgument,
+ this.member = null,
+ this.localFunction = null,
+ this.invocation = null;
+
static const VariableUse explicit =
const VariableUse._simple(VariableUseKind.explicit);
@@ -512,7 +538,8 @@
kind.hashCode * 11 +
member.hashCode * 13 +
localFunction.hashCode * 17 +
- invocation.hashCode * 19;
+ invocation.hashCode * 19 +
+ instantiation.hashCode * 23;
bool operator ==(other) {
if (identical(this, other)) return true;
@@ -520,11 +547,13 @@
return kind == other.kind &&
member == other.member &&
localFunction == other.localFunction &&
- invocation == other.invocation;
+ invocation == other.invocation &&
+ instantiation == other.instantiation;
}
String toString() => 'VariableUse(kind=$kind,member=$member,'
- 'localFunction=$localFunction,invocation=$invocation)';
+ 'localFunction=$localFunction,invocation=$invocation,'
+ 'instantiation=$instantiation)';
}
class KernelScopeInfo {
@@ -1150,4 +1179,7 @@
bool localFunctionNeedsSignature(ir.Node node);
bool selectorNeedsTypeArguments(Selector selector);
+
+ bool instantiationNeedsTypeArguments(
+ DartType functionType, int typeArgumentCount);
}
diff --git a/pkg/compiler/lib/src/js_model/closure_visitors.dart b/pkg/compiler/lib/src/js_model/closure_visitors.dart
index 5868aea..9c1dfbb 100644
--- a/pkg/compiler/lib/src/js_model/closure_visitors.dart
+++ b/pkg/compiler/lib/src/js_model/closure_visitors.dart
@@ -631,7 +631,8 @@
@override
visitInstantiation(ir.Instantiation node) {
- visitChildrenInContext(node, VariableUse.explicit);
+ visitChildrenInContext(
+ node, new VariableUse.instantiationTypeArgument(node));
}
/// Returns true if the node is a field, or a constructor (factory or
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index d8a72c6..e1779e6 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -416,7 +416,6 @@
map.toBackendFunctionSet(backendUsage.helperFunctionsUsed);
Set<ClassEntity> helperClassesUsed =
map.toBackendClassSet(backendUsage.helperClassesUsed);
-
return new BackendUsageImpl(
globalFunctionDependencies: globalFunctionDependencies,
globalClassDependencies: globalClassDependencies,
@@ -572,7 +571,8 @@
methodsNeedingTypeArguments,
null,
null,
- selectorsNeedingTypeArguments);
+ selectorsNeedingTypeArguments,
+ rtiNeed.instantiationsNeedingTypeArguments);
}
/// Construct a closure class and set up the necessary class inference
@@ -829,12 +829,28 @@
class TrivialClosureRtiNeed implements ClosureRtiNeed {
const TrivialClosureRtiNeed();
+ @override
bool localFunctionNeedsSignature(ir.Node node) => true;
+
+ @override
bool classNeedsTypeArguments(ClassEntity cls) => true;
+
+ @override
bool methodNeedsTypeArguments(FunctionEntity method) => true;
+
+ @override
bool localFunctionNeedsTypeArguments(ir.Node node) => true;
+
+ @override
bool selectorNeedsTypeArguments(Selector selector) => true;
+
+ @override
bool methodNeedsSignature(MemberEntity method) => true;
+
+ @override
+ bool instantiationNeedsTypeArguments(
+ DartType functionType, int typeArgumentCount) =>
+ true;
}
class JsClosureRtiNeed implements ClosureRtiNeed {
@@ -849,6 +865,7 @@
this.localFunctionsNodesNeedingTypeArguments,
this.localFunctionsNodesNeedingSignature);
+ @override
bool localFunctionNeedsSignature(ir.Node node) {
assert(node is ir.FunctionDeclaration || node is ir.FunctionExpression);
return backendUsage.isRuntimeTypeUsed
@@ -856,12 +873,15 @@
: localFunctionsNodesNeedingSignature.contains(node);
}
+ @override
bool classNeedsTypeArguments(ClassEntity cls) =>
rtiNeed.classNeedsTypeArguments(cls);
+ @override
bool methodNeedsTypeArguments(FunctionEntity method) =>
rtiNeed.methodNeedsTypeArguments(method);
+ @override
bool localFunctionNeedsTypeArguments(ir.Node node) {
assert(node is ir.FunctionDeclaration || node is ir.FunctionExpression);
return backendUsage.isRuntimeTypeUsed
@@ -869,9 +889,16 @@
: localFunctionsNodesNeedingTypeArguments.contains(node);
}
+ @override
bool selectorNeedsTypeArguments(Selector selector) =>
rtiNeed.selectorNeedsTypeArguments(selector);
+ @override
bool methodNeedsSignature(MemberEntity method) =>
rtiNeed.methodNeedsSignature(method);
+
+ @override
+ bool instantiationNeedsTypeArguments(
+ DartType functionType, int typeArgumentCount) =>
+ rtiNeed.instantiationNeedsTypeArguments(functionType, typeArgumentCount);
}
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index 2d713f1..ecdf526 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -22,6 +22,7 @@
Setlet<ConstantExpression> _constantLiterals;
Setlet<dynamic> _nativeData;
Setlet<ClassEntity> _seenClasses;
+ Set<GenericInstantiation> _genericInstantiations;
ResolutionWorldImpactBuilder(this.name);
@@ -30,9 +31,7 @@
void registerMapLiteral(MapLiteralUse mapLiteralUse) {
assert(mapLiteralUse != null);
- if (_mapLiterals == null) {
- _mapLiterals = new Setlet<MapLiteralUse>();
- }
+ _mapLiterals ??= new Setlet<MapLiteralUse>();
_mapLiterals.add(mapLiteralUse);
}
@@ -43,9 +42,7 @@
void registerListLiteral(ListLiteralUse listLiteralUse) {
assert(listLiteralUse != null);
- if (_listLiterals == null) {
- _listLiterals = new Setlet<ListLiteralUse>();
- }
+ _listLiterals ??= new Setlet<ListLiteralUse>();
_listLiterals.add(listLiteralUse);
}
@@ -55,9 +52,7 @@
}
void registerConstSymbolName(String name) {
- if (_constSymbolNames == null) {
- _constSymbolNames = new Setlet<String>();
- }
+ _constSymbolNames ??= new Setlet<String>();
_constSymbolNames.add(name);
}
@@ -67,9 +62,7 @@
}
void registerFeature(Feature feature) {
- if (_features == null) {
- _features = new EnumSet<Feature>();
- }
+ _features ??= new EnumSet<Feature>();
_features.add(feature);
}
@@ -81,9 +74,7 @@
}
void registerConstantLiteral(ConstantExpression constant) {
- if (_constantLiterals == null) {
- _constantLiterals = new Setlet<ConstantExpression>();
- }
+ _constantLiterals ??= new Setlet<ConstantExpression>();
_constantLiterals.add(constant);
}
@@ -95,9 +86,7 @@
void registerNativeData(dynamic nativeData) {
assert(nativeData != null);
- if (_nativeData == null) {
- _nativeData = new Setlet<dynamic>();
- }
+ _nativeData ??= new Setlet<dynamic>();
_nativeData.add(nativeData);
}
@@ -107,9 +96,7 @@
}
void registerSeenClass(ClassEntity seenClass) {
- if (_seenClasses == null) {
- _seenClasses = new Setlet<ClassEntity>();
- }
+ _seenClasses ??= new Setlet<ClassEntity>();
_seenClasses.add(seenClass);
}
@@ -118,6 +105,16 @@
return _seenClasses ?? const <ClassEntity>[];
}
+ void registerInstantiation(GenericInstantiation instantiation) {
+ _genericInstantiations ??= new Set<GenericInstantiation>();
+ _genericInstantiations.add(instantiation);
+ }
+
+ @override
+ Iterable<GenericInstantiation> get genericInstantiations {
+ return _genericInstantiations ?? const <GenericInstantiation>[];
+ }
+
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('_ResolutionWorldImpact($name)');
@@ -155,6 +152,12 @@
sb.write('\n $data');
}
}
+ if (_genericInstantiations != null) {
+ sb.write('\n instantiations:');
+ for (var data in _genericInstantiations) {
+ sb.write('\n $data');
+ }
+ }
return sb.toString();
}
}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 079f4c0..aa5f212 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -35,6 +35,7 @@
import '../types/abstract_value_domain.dart';
import '../types/types.dart';
import '../universe/call_structure.dart';
+import '../universe/feature.dart';
import '../universe/selector.dart';
import '../universe/side_effects.dart' show SideEffects;
import '../universe/target_checks.dart' show TargetChecks;
@@ -4234,9 +4235,20 @@
var arguments = <HInstruction>[];
node.expression.accept(this);
arguments.add(pop());
- for (ir.DartType type in node.typeArguments) {
- HInstruction instruction = typeBuilder.analyzeTypeArgument(
- _elementMap.getDartType(type), sourceElement);
+ // TODO(johnniwinther): Use the static type of the expression.
+ bool typeArgumentsNeeded = rtiNeed.instantiationNeedsTypeArguments(
+ null, node.typeArguments.length);
+ List<DartType> typeArguments = node.typeArguments
+ .map((type) => typeArgumentsNeeded
+ ? _elementMap.getDartType(type)
+ : _commonElements.dynamicType)
+ .toList();
+ registry.registerGenericInstantiation(
+ new GenericInstantiation(null, typeArguments));
+ // TODO(johnniwinther): Can we avoid creating the instantiation object?
+ for (DartType type in typeArguments) {
+ HInstruction instruction =
+ typeBuilder.analyzeTypeArgument(type, sourceElement);
arguments.add(instruction);
}
int typeArgumentCount = node.typeArguments.length;
diff --git a/pkg/compiler/lib/src/ssa/kernel_impact.dart b/pkg/compiler/lib/src/ssa/kernel_impact.dart
index 2352143..0c3846e 100644
--- a/pkg/compiler/lib/src/ssa/kernel_impact.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_impact.dart
@@ -680,7 +680,9 @@
@override
void visitInstantiation(ir.Instantiation node) {
// TODO(johnniwinther): Track which arities are used in instantiation.
- impactBuilder.registerFeature(Feature.GENERIC_INSTANTIATION);
+ impactBuilder.registerInstantiation(new GenericInstantiation(
+ elementMap.getStaticType(node.expression),
+ node.typeArguments.map(elementMap.getDartType).toList()));
node.visitChildren(this);
}
diff --git a/pkg/compiler/lib/src/universe/feature.dart b/pkg/compiler/lib/src/universe/feature.dart
index d63fa34..3d4f018 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -8,7 +8,8 @@
/// compilation pipeline, for example during resolution.
library compiler.universe.feature;
-import '../elements/types.dart' show InterfaceType;
+import '../elements/types.dart' show DartType, InterfaceType;
+import '../util/util.dart';
/// A language feature that may be seen in the program.
// TODO(johnniwinther): Should mirror usage be part of this?
@@ -43,9 +44,6 @@
/// A field without an initializer.
FIELD_WITHOUT_INITIALIZER,
- /// A generic instantiation (application of type parameters).
- GENERIC_INSTANTIATION,
-
/// A field whose initialization is not a constant.
LAZY_FIELD,
@@ -149,3 +147,33 @@
return 'ListLiteralUse($type,isConstant:$isConstant,isEmpty:$isEmpty)';
}
}
+
+/// A generic instantiation of an expression of type [functionType] with the
+/// given [typeArguments].
+class GenericInstantiation {
+ /// The static type of the instantiated expression.
+ final DartType functionType;
+
+ /// The type arguments of the instantiation.
+ final List<DartType> typeArguments;
+
+ GenericInstantiation(this.functionType, this.typeArguments);
+
+ /// Short textual representation use for testing.
+ String get shortText => '<${typeArguments.join(',')}>';
+
+ int get hashCode =>
+ Hashing.listHash(typeArguments, Hashing.objectHash(functionType));
+
+ bool operator ==(other) {
+ if (identical(this, other)) return true;
+ if (other is! GenericInstantiation) return false;
+ return functionType == other.functionType &&
+ equalElements(typeArguments, other.typeArguments);
+ }
+
+ String toString() {
+ return 'GenericInstantiation(functionType:$functionType,'
+ 'typeArguments:$typeArguments)';
+ }
+}
diff --git a/pkg/compiler/lib/src/universe/world_impact.dart b/pkg/compiler/lib/src/universe/world_impact.dart
index 3620b85..af5eaae 100644
--- a/pkg/compiler/lib/src/universe/world_impact.dart
+++ b/pkg/compiler/lib/src/universe/world_impact.dart
@@ -99,9 +99,7 @@
void registerDynamicUse(DynamicUse dynamicUse) {
assert(dynamicUse != null);
- if (_dynamicUses == null) {
- _dynamicUses = new Setlet<DynamicUse>();
- }
+ _dynamicUses ??= new Setlet<DynamicUse>();
_dynamicUses.add(dynamicUse);
}
@@ -111,9 +109,7 @@
void registerTypeUse(TypeUse typeUse) {
assert(typeUse != null);
- if (_typeUses == null) {
- _typeUses = new Setlet<TypeUse>();
- }
+ _typeUses ??= new Setlet<TypeUse>();
_typeUses.add(typeUse);
}
@@ -123,9 +119,7 @@
void registerStaticUse(StaticUse staticUse) {
assert(staticUse != null);
- if (_staticUses == null) {
- _staticUses = new Setlet<StaticUse>();
- }
+ _staticUses ??= new Setlet<StaticUse>();
_staticUses.add(staticUse);
}
@@ -135,9 +129,7 @@
void registerConstantUse(ConstantUse constantUse) {
assert(constantUse != null);
- if (_constantUses == null) {
- _constantUses = new Setlet<ConstantUse>();
- }
+ _constantUses ??= new Setlet<ConstantUse>();
_constantUses.add(constantUse);
}
diff --git a/tests/compiler/dart2js/closure/closure_test.dart b/tests/compiler/dart2js/closure/closure_test.dart
index dfc8631..819890e 100644
--- a/tests/compiler/dart2js/closure/closure_test.dart
+++ b/tests/compiler/dart2js/closure/closure_test.dart
@@ -25,7 +25,7 @@
asyncTest(() async {
Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
await checkTests(dataDir, computeKernelClosureData,
- skipForKernel: skipForKernel, args: args);
+ skipForKernel: skipForKernel, args: args, testOmit: true);
});
}
diff --git a/tests/compiler/dart2js/closure/data/generic_strong.dart b/tests/compiler/dart2js/closure/data/generic_strong.dart
index 1fbe9ca..8823cb6 100644
--- a/tests/compiler/dart2js/closure/data/generic_strong.dart
+++ b/tests/compiler/dart2js/closure/data/generic_strong.dart
@@ -55,8 +55,14 @@
return /*fields=[S,U],free=[S,U],hasThis*/ () => '$S$U';
}
- var local2 = /*fields=[S,this],free=[S,this],hasThis*/ (o) {
- return /*fields=[S,this],free=[S,this],hasThis*/ () => new Map<T, S>();
+ var local2 =
+ /*strong.fields=[S,this],free=[S,this],hasThis*/
+ /*omit.hasThis*/
+ (o) {
+ return
+ /*strong.fields=[S,this],free=[S,this],hasThis*/
+ /*omit.hasThis*/
+ () => new Map<T, S>();
};
return local2(local<double>());
}
diff --git a/tests/compiler/dart2js/closure/data/instantiation1.dart b/tests/compiler/dart2js/closure/data/instantiation1.dart
new file mode 100644
index 0000000..9e86e11
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/instantiation1.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+int f<T>(T a) => null;
+
+typedef int F<R>(R a);
+
+/*element: B.:hasThis*/
+class B<S> {
+ /*element: B.method:hasThis*/
+ method() {
+ return
+ /*kernel.hasThis*/
+ /*strong.fields=[this],free=[this],hasThis*/
+ /*omit.hasThis*/
+ () {
+ F<S> c = f;
+ return c;
+ };
+ }
+}
+
+main() {
+ new B().method();
+}
diff --git a/tests/compiler/dart2js/closure/data/instantiation2.dart b/tests/compiler/dart2js/closure/data/instantiation2.dart
new file mode 100644
index 0000000..4fd81d1
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/instantiation2.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+bool f<T>(T a) => a is T;
+
+typedef bool F<R>(R a);
+
+/*element: B.:hasThis*/
+class B<S> {
+ /*element: B.method:hasThis*/
+ method() {
+ return
+ /*kernel.hasThis*/
+ /*!kernel.fields=[this],free=[this],hasThis*/
+ () {
+ F<S> c = f;
+ return c;
+ };
+ }
+}
+
+main() {
+ new B().method();
+}
diff --git a/tests/compiler/dart2js/closure/data/instantiation3.dart b/tests/compiler/dart2js/closure/data/instantiation3.dart
new file mode 100644
index 0000000..aeeee92
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/instantiation3.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+int f<T>(T a) => null;
+
+typedef int F<R>(R a);
+
+method<S>() {
+ return
+ /*strong.fields=[S],free=[S]*/
+ /*omit.*/
+ () {
+ F<S> c = f;
+ return c;
+ };
+}
+
+main() {
+ method();
+}
diff --git a/tests/compiler/dart2js/closure/data/instantiation4.dart b/tests/compiler/dart2js/closure/data/instantiation4.dart
new file mode 100644
index 0000000..957eca0
--- /dev/null
+++ b/tests/compiler/dart2js/closure/data/instantiation4.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+bool f<T>(T a) => a is T;
+
+typedef bool F<R>(R a);
+
+method<S>() {
+ return
+ /*strong.fields=[S],free=[S]*/
+ /*omit.fields=[S],free=[S]*/
+ () {
+ F<S> c = f;
+ return c;
+ };
+}
+
+main() {
+ method();
+}
diff --git a/tests/compiler/dart2js/closure/data/instantiation_strong.dart b/tests/compiler/dart2js/closure/data/instantiation_strong.dart
index 10b70e9..8f95b60 100644
--- a/tests/compiler/dart2js/closure/data/instantiation_strong.dart
+++ b/tests/compiler/dart2js/closure/data/instantiation_strong.dart
@@ -5,7 +5,8 @@
T id<T>(T t) => t;
method<S>(S s) {
- /*fields=[S],free=[S]*/
+ /*strong.fields=[S],free=[S]*/
+ /*omit.*/
S Function(S) getId() => id;
return getId();
}
diff --git a/tests/compiler/dart2js/closure/data/list_literal_untested_strong_trust.dart b/tests/compiler/dart2js/closure/data/list_literal_untested_strong_trust.dart
index 55e709a..52788fc 100644
--- a/tests/compiler/dart2js/closure/data/list_literal_untested_strong_trust.dart
+++ b/tests/compiler/dart2js/closure/data/list_literal_untested_strong_trust.dart
@@ -6,7 +6,9 @@
@NoInline()
method<T>() {
- /**/ dynamic local() => <T>[];
+ /*!strong.*/
+ /*strong.fields=[T],free=[T]*/
+ dynamic local() => <T>[];
return local;
}
diff --git a/tests/compiler/dart2js/closure/data/list_literal_untested_trust.dart b/tests/compiler/dart2js/closure/data/list_literal_untested_trust.dart
index 92b057e..89fe422 100644
--- a/tests/compiler/dart2js/closure/data/list_literal_untested_trust.dart
+++ b/tests/compiler/dart2js/closure/data/list_literal_untested_trust.dart
@@ -9,7 +9,9 @@
/*element: A.method:hasThis*/
@NoInline()
method() {
- /*hasThis*/ dynamic local() => <T>[];
+ /*!strong.hasThis*/
+ /*strong.fields=[this],free=[this],hasThis*/
+ dynamic local() => <T>[];
return local;
}
}
diff --git a/tests/compiler/dart2js/closure/data/map_literal_untested_strong_trust.dart b/tests/compiler/dart2js/closure/data/map_literal_untested_strong_trust.dart
index 8793b90..6cfb9e9 100644
--- a/tests/compiler/dart2js/closure/data/map_literal_untested_strong_trust.dart
+++ b/tests/compiler/dart2js/closure/data/map_literal_untested_strong_trust.dart
@@ -6,7 +6,9 @@
@NoInline()
method<T>() {
- /**/ dynamic local() => <T, int>{};
+ /*!strong.*/
+ /*strong.fields=[T],free=[T]*/
+ dynamic local() => <T, int>{};
return local;
}
diff --git a/tests/compiler/dart2js/closure/data/map_literal_untested_trust.dart b/tests/compiler/dart2js/closure/data/map_literal_untested_trust.dart
index 958da83..146de88 100644
--- a/tests/compiler/dart2js/closure/data/map_literal_untested_trust.dart
+++ b/tests/compiler/dart2js/closure/data/map_literal_untested_trust.dart
@@ -9,7 +9,9 @@
/*element: A.method:hasThis*/
@NoInline()
method() {
- /*hasThis*/ dynamic local() => <T, int>{};
+ /*!strong.hasThis*/
+ /*strong.fields=[this],free=[this],hasThis*/
+ dynamic local() => <T, int>{};
return local;
}
}
diff --git a/tests/compiler/dart2js/closure/data/test_type.dart b/tests/compiler/dart2js/closure/data/test_type.dart
index aaadba2..1cd8aef 100644
--- a/tests/compiler/dart2js/closure/data/test_type.dart
+++ b/tests/compiler/dart2js/closure/data/test_type.dart
@@ -38,7 +38,7 @@
class Class3<T> {
/*element: Class3.method3:hasThis*/
method3(dynamic o) {
- /*kernel.fields=[o],free=[o],hasThis*/
+ /*!strong.fields=[o],free=[o],hasThis*/
/*strong.fields=[o,this],free=[o,this],hasThis*/
T local() => o;
return local;
diff --git a/tests/compiler/dart2js/closure/data/test_type_strong.dart b/tests/compiler/dart2js/closure/data/test_type_strong.dart
index 93dcec0..cb8f88d 100644
--- a/tests/compiler/dart2js/closure/data/test_type_strong.dart
+++ b/tests/compiler/dart2js/closure/data/test_type_strong.dart
@@ -30,7 +30,8 @@
/*element: method3:*/
method3<T>(dynamic o) {
- /*fields=[T,o],free=[T,o]*/
+ /*strong.fields=[T,o],free=[T,o]*/
+ /*omit.fields=[o],free=[o]*/
T local() => o;
return local;
}
diff --git a/tests/compiler/dart2js/closure/data/test_type_strong_trust.dart b/tests/compiler/dart2js/closure/data/test_type_strong_trust.dart
deleted file mode 100644
index abb909b..0000000
--- a/tests/compiler/dart2js/closure/data/test_type_strong_trust.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
-// 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.
-
-////////////////////////////////////////////////////////////////////////////////
-/// Explicit is-test is required even with --omit-implicit-checks.
-////////////////////////////////////////////////////////////////////////////////
-
-/*element: method1:*/
-method1<T>(dynamic o) {
- /*fields=[T,o],free=[T,o]*/
- dynamic local() => o is T;
- return local;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// Explicit as-cast is required even with --omit-implicit-checks.
-////////////////////////////////////////////////////////////////////////////////
-
-/*element: method2:*/
-method2<T>(dynamic o) {
- /*fields=[T,o],free=[T,o]*/
- dynamic local() => o as T;
- return local;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// Implicit as-cast is not required with --omit-implicit-checks.
-////////////////////////////////////////////////////////////////////////////////
-
-/*element: method3:*/
-method3<T>(dynamic o) {
- /*fields=[o],free=[o]*/
- T local() => o;
- return local;
-}
-
-main() {
- method1<int>(0).call();
- method2<int>(0).call();
- method3<int>(0).call();
-}
diff --git a/tests/compiler/dart2js/closure/data/test_type_trust.dart b/tests/compiler/dart2js/closure/data/test_type_trust.dart
deleted file mode 100644
index 7ed8dc1..0000000
--- a/tests/compiler/dart2js/closure/data/test_type_trust.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
-// 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.
-
-////////////////////////////////////////////////////////////////////////////////
-/// Explicit is-test is required even with --omit-implicit-checks.
-////////////////////////////////////////////////////////////////////////////////
-
-/*element: Class1.:hasThis*/
-class Class1<T> {
- /*element: Class1.method1:hasThis*/
- method1(dynamic o) {
- /*fields=[o,this],free=[o,this],hasThis*/
- dynamic local() => o is T;
- return local;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// Explicit as-cast is required even with --omit-implicit-checks.
-////////////////////////////////////////////////////////////////////////////////
-
-/*element: Class2.:hasThis*/
-class Class2<T> {
- /*element: Class2.method2:hasThis*/
- method2(dynamic o) {
- /*fields=[o,this],free=[o,this],hasThis*/
- dynamic local() => o as T;
- return local;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// Implicit as-cast is not required with --omit-implicit-checks.
-////////////////////////////////////////////////////////////////////////////////
-
-/*element: Class3.:hasThis*/
-class Class3<T> {
- /*element: Class3.method3:hasThis*/
- method3(dynamic o) {
- /*fields=[o],free=[o],hasThis*/
- T local() => o;
- return local;
- }
-}
-
-main() {
- new Class1<int>().method1(0).call();
- new Class2<int>().method2(0).call();
- new Class3<int>().method3(0).call();
-}
diff --git a/tests/compiler/dart2js/closure/data/type_annotations.dart b/tests/compiler/dart2js/closure/data/type_annotations.dart
index 112565e..a891048 100644
--- a/tests/compiler/dart2js/closure/data/type_annotations.dart
+++ b/tests/compiler/dart2js/closure/data/type_annotations.dart
@@ -48,7 +48,7 @@
class Class2<T> {
/*element: Class2.method2:hasThis*/
method2() {
- /*kernel.hasThis*/
+ /*!strong.hasThis*/
/*strong.fields=[this],free=[this],hasThis*/
dynamic local(T t) => t;
return local;
@@ -63,7 +63,7 @@
class Class3<T> {
/*element: Class3.method3:hasThis*/
method3(dynamic o) {
- /*kernel.fields=[o],free=[o],hasThis*/
+ /*!strong.fields=[o],free=[o],hasThis*/
/*strong.fields=[o,this],free=[o,this],hasThis*/
T local() => o;
return local;
@@ -106,7 +106,7 @@
class Class6<T> {
/*element: Class6.method6:hasThis*/
method6() {
- /*kernel.hasThis*/
+ /*!strong.hasThis*/
/*strong.fields=[this],free=[this],hasThis*/
dynamic local(T t) {
/*fields=[t],free=[t],hasThis*/
@@ -126,7 +126,7 @@
class Class7<T> {
/*element: Class7.method7:hasThis*/
method7(dynamic o) {
- /*kernel.fields=[o],free=[o],hasThis*/
+ /*!strong.fields=[o],free=[o],hasThis*/
/*strong.fields=[o,this],free=[o,this],hasThis*/
T local() {
/*fields=[o],free=[o],hasThis*/
diff --git a/tests/compiler/dart2js/closure/data/type_annotations_strong.dart b/tests/compiler/dart2js/closure/data/type_annotations_strong.dart
index 3b4c2a6..878e3bd 100644
--- a/tests/compiler/dart2js/closure/data/type_annotations_strong.dart
+++ b/tests/compiler/dart2js/closure/data/type_annotations_strong.dart
@@ -21,7 +21,8 @@
////////////////////////////////////////////////////////////////////////////////
method2<T>() {
- /*fields=[T],free=[T]*/
+ /*strong.fields=[T],free=[T]*/
+ /*omit.*/
dynamic local(T t) => t;
return local;
}
@@ -31,7 +32,8 @@
////////////////////////////////////////////////////////////////////////////////
method3<T>(dynamic o) {
- /*fields=[T,o],free=[T,o]*/
+ /*strong.fields=[T,o],free=[T,o]*/
+ /*omit.fields=[o],free=[o]*/
T local() => o;
return local;
}
@@ -61,7 +63,8 @@
////////////////////////////////////////////////////////////////////////////////
method6<T>() {
- /*fields=[T],free=[T]*/
+ /*strong.fields=[T],free=[T]*/
+ /*omit.*/
dynamic local(T t) {
/*fields=[t],free=[t]*/
dynamic inner() => t;
@@ -76,7 +79,8 @@
////////////////////////////////////////////////////////////////////////////////
method7<T>(dynamic o) {
- /*fields=[T,o],free=[T,o]*/
+ /*strong.fields=[T,o],free=[T,o]*/
+ /*omit.fields=[o],free=[o]*/
T local() {
/*fields=[o],free=[o]*/
dynamic inner() => o;
diff --git a/tests/compiler/dart2js/closure/data/type_annotations_strong_trust.dart b/tests/compiler/dart2js/closure/data/type_annotations_strong_trust.dart
deleted file mode 100644
index 1ec0bf1..0000000
--- a/tests/compiler/dart2js/closure/data/type_annotations_strong_trust.dart
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
-// 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.
-
-////////////////////////////////////////////////////////////////////////////////
-/// A sound assignment to a local variable doesn't capture the type variable.
-////////////////////////////////////////////////////////////////////////////////
-
-method1<T>(T o) {
- /*fields=[o],free=[o]*/
- dynamic local() {
- T t = o;
- return t;
- }
-
- return local;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// A local function parameter type is with --omit-type-checks.
-////////////////////////////////////////////////////////////////////////////////
-
-method2<T>() {
- /**/
- dynamic local(T t) => t;
- return local;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// A local function return type is not captured with --omit-type-checks.
-////////////////////////////////////////////////////////////////////////////////
-
-method3<T>(dynamic o) {
- /*fields=[o],free=[o]*/
- T local() => o;
- return local;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// A member parameter type is not captured.
-////////////////////////////////////////////////////////////////////////////////
-
-method4<T>(T o) {
- /*fields=[o],free=[o]*/
- dynamic local() => o;
- return local;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// A member return type is not captured.
-////////////////////////////////////////////////////////////////////////////////
-
-T method5<T>(dynamic o) {
- /*fields=[o],free=[o]*/
- dynamic local() => o;
- return local();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// A local function parameter type is not captured by an inner local function.
-////////////////////////////////////////////////////////////////////////////////
-
-method6<T>() {
- /**/
- dynamic local(T t) {
- /*fields=[t],free=[t]*/
- dynamic inner() => t;
- return inner;
- }
-
- return local;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// A local function return type is not captured by an inner local function.
-////////////////////////////////////////////////////////////////////////////////
-
-method7<T>(dynamic o) {
- /*fields=[o],free=[o]*/
- T local() {
- /*fields=[o],free=[o]*/
- dynamic inner() => o;
- return inner();
- }
-
- return local;
-}
-
-main() {
- method1<int>(0).call();
- method2<int>().call(0);
- method3<int>(0).call();
- method4<int>(0).call();
- method5<int>(0);
- method6<int>().call(0).call();
- method7<int>(0).call().call();
-}
diff --git a/tests/compiler/dart2js/closure/data/type_annotations_trust.dart b/tests/compiler/dart2js/closure/data/type_annotations_trust.dart
deleted file mode 100644
index ff0ee55..0000000
--- a/tests/compiler/dart2js/closure/data/type_annotations_trust.dart
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
-// 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.
-
-////////////////////////////////////////////////////////////////////////////////
-/// A sound assignment to a local variable doesn't capture the type variable.
-////////////////////////////////////////////////////////////////////////////////
-
-/*element: Class1.:hasThis*/
-class Class1<T> {
- /*element: Class1.method1:hasThis*/
- method1(T o) {
- /*fields=[o],free=[o],hasThis*/
- dynamic local() {
- T t = o;
- return t;
- }
-
- return local;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// A local function parameter type is with --omit-type-checks.
-////////////////////////////////////////////////////////////////////////////////
-
-/*element: Class2.:hasThis*/
-class Class2<T> {
- /*element: Class2.method2:hasThis*/
- method2() {
- /*hasThis*/
- dynamic local(T t) => t;
- return local;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// A local function return type is not captured with --omit-type-checks.
-////////////////////////////////////////////////////////////////////////////////
-
-/*element: Class3.:hasThis*/
-class Class3<T> {
- /*element: Class3.method3:hasThis*/
- method3(dynamic o) {
- /*fields=[o],free=[o],hasThis*/
- T local() => o;
- return local;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// A member parameter type is not captured.
-////////////////////////////////////////////////////////////////////////////////
-
-/*element: Class4.:hasThis*/
-class Class4<T> {
- /*element: Class4.method4:hasThis*/
- method4(T o) {
- /*fields=[o],free=[o],hasThis*/
- dynamic local() => o;
- return local;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// A member return type is not captured.
-////////////////////////////////////////////////////////////////////////////////
-
-/*element: Class5.:hasThis*/
-class Class5<T> {
- /*element: Class5.method5:hasThis*/
- T method5(dynamic o) {
- /*fields=[o],free=[o],hasThis*/
- dynamic local() => o;
- return local();
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// A local function parameter type is not captured by an inner local function.
-////////////////////////////////////////////////////////////////////////////////
-
-/*element: Class6.:hasThis*/
-class Class6<T> {
- /*element: Class6.method6:hasThis*/
- method6() {
- /*hasThis*/
- dynamic local(T t) {
- /*fields=[t],free=[t],hasThis*/
- dynamic inner() => t;
- return inner;
- }
-
- return local;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// A local function return type is not captured by an inner local function.
-////////////////////////////////////////////////////////////////////////////////
-
-/*element: Class7.:hasThis*/
-class Class7<T> {
- /*element: Class7.method7:hasThis*/
- method7(dynamic o) {
- /*fields=[o],free=[o],hasThis*/
- T local() {
- /*fields=[o],free=[o],hasThis*/
- dynamic inner() => o;
- return inner();
- }
-
- return local;
- }
-}
-
-main() {
- new Class1<int>().method1(0).call();
- new Class2<int>().method2().call(0);
- new Class3<int>().method3(0).call();
- new Class4<int>().method4(0).call();
- new Class5<int>().method5(0);
- new Class6<int>().method6().call(0).call();
- new Class7<int>().method7(0).call().call();
-}
diff --git a/tests/compiler/dart2js/inference/data/field_type.dart b/tests/compiler/dart2js/inference/data/field_type.dart
index 51b672d..44168f3 100644
--- a/tests/compiler/dart2js/inference/data/field_type.dart
+++ b/tests/compiler/dart2js/inference/data/field_type.dart
@@ -202,7 +202,8 @@
/*element: A9.:[exact=A9]*/
A9(/*[exact=JSBool]*/ x) {
- if (x) {} else {
+ if (x) {
+ } else {
/*update: [exact=A9]*/ f9 = "1";
}
}
@@ -727,7 +728,8 @@
/*element: A29.:[exact=A29]*/
A29(/*[exact=JSUInt31]*/ x) {
this. /*update: [exact=A29]*/ f29a = x;
- if (x /*invoke: [exact=JSUInt31]*/ == 0) {} else {
+ if (x /*invoke: [exact=JSUInt31]*/ == 0) {
+ } else {
return;
}
this. /*update: [exact=A29]*/ f29b = x;
diff --git a/tests/compiler/dart2js/inference/data/general.dart b/tests/compiler/dart2js/inference/data/general.dart
index ea317d5..1b2d806 100644
--- a/tests/compiler/dart2js/inference/data/general.dart
+++ b/tests/compiler/dart2js/inference/data/general.dart
@@ -306,7 +306,8 @@
/*element: testIsCheck26:[subclass=JSInt]*/
testIsCheck26(/*[null|subclass=Object]*/ a) {
- if (a is int) {} else {
+ if (a is int) {
+ } else {
throw 42;
}
return a;
@@ -314,7 +315,8 @@
/*element: testIsCheck27:[subclass=JSInt]*/
testIsCheck27(/*[null|subclass=Object]*/ a) {
- if (a is int) {} else {
+ if (a is int) {
+ } else {
return 42;
}
return a;
@@ -322,7 +324,8 @@
/*element: testIsCheck28:[null|subclass=Object]*/
testIsCheck28(/*[null|subclass=Object]*/ a) {
- if (a is int) {} else {}
+ if (a is int) {
+ } else {}
return a;
}
@@ -344,7 +347,8 @@
/*element: testIf2:[null|exact=JSUInt31]*/
testIf2(/*[null|subclass=Object]*/ a) {
var c = null;
- if (a) {} else {
+ if (a) {
+ } else {
c = 10;
}
return c;
diff --git a/tests/compiler/dart2js/rti/data/instantiation1.dart b/tests/compiler/dart2js/rti/data/instantiation1.dart
new file mode 100644
index 0000000..1b8e7cd
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/instantiation1.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+/*strong.element: f:deps=[B],direct,explicit=[f.T],needsArgs,needsInst=[<B.S>]*/
+/*omit.element: f:deps=[B]*/
+int f<T>(T a) => null;
+
+typedef int F<R>(R a);
+
+/*strong.class: B:explicit=[int Function(B.S)],indirect,needsArgs*/
+class B<S> {
+ F<S> c;
+
+ B() : c = f;
+}
+
+main() {
+ new B();
+}
diff --git a/tests/compiler/dart2js/rti/data/instantiation2.dart b/tests/compiler/dart2js/rti/data/instantiation2.dart
new file mode 100644
index 0000000..fd7022c
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/instantiation2.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+/*kernel.element: f:direct,explicit=[f.T]*/
+/*!kernel.element: f:deps=[B],direct,explicit=[f.T],needsArgs,needsInst=[<B.S>]*/
+bool f<T>(T a) => a is T;
+
+typedef bool F<R>(R a);
+
+/*strong.class: B:explicit=[bool Function(B.S)],indirect,needsArgs*/
+/*omit.class: B:indirect,needsArgs*/
+class B<S> {
+ F<S> c;
+
+ B() : c = f;
+}
+
+main() {
+ new B();
+}
diff --git a/tests/compiler/dart2js/rti/data/instantiation3.dart b/tests/compiler/dart2js/rti/data/instantiation3.dart
new file mode 100644
index 0000000..7d3df34
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/instantiation3.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+/*strong.element: f:deps=[B],direct,explicit=[f.T],needsArgs,needsInst=[<B.S>]*/
+/*omit.element: f:deps=[B]*/
+int f<T>(T a) => null;
+
+typedef int F<R>(R a);
+
+/*strong.class: B:direct,explicit=[int Function(B.S)],needsArgs*/
+class B<S> {
+ F<S> c;
+
+ method() {
+ return () {
+ c = f;
+ };
+ }
+}
+
+main() {
+ new B().method();
+}
diff --git a/tests/compiler/dart2js/rti/data/instantiation4.dart b/tests/compiler/dart2js/rti/data/instantiation4.dart
new file mode 100644
index 0000000..b9f1a78
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/instantiation4.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+/*kernel.element: f:direct,explicit=[f.T]*/
+/*!kernel.element: f:deps=[B],direct,explicit=[f.T],needsArgs,needsInst=[<B.S>]*/
+bool f<T>(T a) => a is T;
+
+typedef bool F<R>(R a);
+
+/*strong.class: B:direct,explicit=[bool Function(B.S)],needsArgs*/
+/*omit.class: B:indirect,needsArgs*/
+class B<S> {
+ F<S> c;
+
+ method() {
+ return () {
+ c = f;
+ };
+ }
+}
+
+main() {
+ new B().method();
+}
diff --git a/tests/compiler/dart2js/rti/data/instantiation5.dart b/tests/compiler/dart2js/rti/data/instantiation5.dart
new file mode 100644
index 0000000..c69f333
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/instantiation5.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+/*strong.element: f:deps=[method],direct,explicit=[f.T],needsArgs,needsInst=[<method.S>]*/
+/*omit.element: f:deps=[method]*/
+int f<T>(T a) => null;
+
+typedef int F<R>(R a);
+
+/*strong.element: method:indirect,needsArgs*/
+method<S>() {
+ F<S> c;
+
+ return () {
+ c = f;
+ return c;
+ };
+}
+
+main() {
+ method();
+}
diff --git a/tests/compiler/dart2js/rti/data/instantiation6.dart b/tests/compiler/dart2js/rti/data/instantiation6.dart
new file mode 100644
index 0000000..feb9e52
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/instantiation6.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+/*kernel.element: f:direct,explicit=[f.T]*/
+/*!kernel.element: f:deps=[method],direct,explicit=[f.T],needsArgs,needsInst=[<method.S>]*/
+bool f<T>(T a) => a is T;
+
+typedef bool F<R>(R a);
+
+/*!kernel.element: method:indirect,needsArgs*/
+method<S>() {
+ F<S> c;
+
+ return () {
+ c = f;
+ return c;
+ };
+}
+
+main() {
+ method();
+}
diff --git a/tests/compiler/dart2js/rti/data/instantiation7.dart b/tests/compiler/dart2js/rti/data/instantiation7.dart
new file mode 100644
index 0000000..d8af322
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/instantiation7.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+/*strong.element: f1:deps=[method],direct,explicit=[f1.T],needsArgs,needsInst=[<method.X>]*/
+/*omit.element: f1:deps=[method]*/
+int f1<T>(T a, T b, T c) => null;
+
+/*strong.element: f2:deps=[method],direct,explicit=[f2.S,f2.T],needsArgs,needsInst=[<method.X,method.Y>]*/
+/*omit.element: f2:deps=[method]*/
+int f2<T, S>(T a, S b, S c) => null;
+
+/*strong.element: f3:deps=[method],direct,explicit=[f3.S,f3.T,f3.U],needsArgs,needsInst=[<method.X,method.Y,method.Z>]*/
+/*omit.element: f3:deps=[method]*/
+int f3<T, S, U>(T a, S b, U c) => null;
+
+typedef int F1<R>(R a, R b, R c);
+typedef int F2<R, P>(R a, P b, P c);
+typedef int F3<R, P, Q>(R a, P b, Q c);
+
+/*strong.element: method:indirect,needsArgs*/
+method<X, Y, Z>() {
+ F1<X> c1;
+ F2<X, Y> c2;
+ F3<X, Y, Z> c3;
+
+ return () {
+ c1 = f1;
+ c2 = f2;
+ c3 = f3;
+ return c1 ?? c2 ?? c3;
+ };
+}
+
+main() {
+ method();
+}
diff --git a/tests/compiler/dart2js/rti/data/local_function_signatures_strong.dart b/tests/compiler/dart2js/rti/data/local_function_signatures_strong.dart
index ce07bec..8d4dd9b 100644
--- a/tests/compiler/dart2js/rti/data/local_function_signatures_strong.dart
+++ b/tests/compiler/dart2js/rti/data/local_function_signatures_strong.dart
@@ -77,7 +77,7 @@
}
method10() {
- /*strong.direct,explicit=[local.T],needsArgs,needsSignature*/
+ /*strong.direct,explicit=[local.T],needsArgs,needsInst=[<dynamic>,<num>,<num>],needsSignature*/
/*omit.needsSignature*/
num local<T>(T n) => null;
return local;
@@ -90,7 +90,7 @@
}
method12() {
- /*strong.direct,explicit=[local.T],needsArgs*/
+ /*strong.direct,explicit=[local.T],needsArgs,needsInst=[<dynamic>,<num>,<num>]*/
/*omit.*/
num local<T>(num n, T t) => null;
return local;
@@ -103,7 +103,7 @@
}
num Function(num) method14() {
- /*strong.direct,explicit=[local.T],needsArgs,needsSignature*/
+ /*strong.direct,explicit=[local.T],needsArgs,needsInst=[<dynamic>,<num>,<num>],needsSignature*/
/*omit.needsSignature*/
num local<T>(T n) => null;
return local;
diff --git a/tests/compiler/dart2js/rti/data/method_signatures_strong.dart b/tests/compiler/dart2js/rti/data/method_signatures_strong.dart
index 03650b8..afca40f5 100644
--- a/tests/compiler/dart2js/rti/data/method_signatures_strong.dart
+++ b/tests/compiler/dart2js/rti/data/method_signatures_strong.dart
@@ -16,7 +16,7 @@
}
class Class2 {
- /*strong.element: Class2.method4:direct,explicit=[method4.T],needsArgs*/
+ /*strong.element: Class2.method4:direct,explicit=[method4.T],needsArgs,needsInst=[<num>,<num>]*/
/*omit.element: Class2.method4:*/
num method4<T>(T n) => null;
}
@@ -27,19 +27,19 @@
}
class Class4 {
- /*strong.element: Class4.method6:direct,explicit=[method6.T],needsArgs*/
+ /*strong.element: Class4.method6:direct,explicit=[method6.T],needsArgs,needsInst=[<num>,<num>]*/
/*omit.element: Class4.method6:*/
num method6<T>(num n, T t) => null;
}
-/*strong.element: method7:direct,explicit=[method7.T],needsArgs*/
+/*strong.element: method7:direct,explicit=[method7.T],needsArgs,needsInst=[<num>,<num>]*/
/*omit.element: method7:*/
num method7<T>(T n) => null;
/*element: method8:*/
T method8<T>(num n) => null;
-/*strong.element: method9:direct,explicit=[method9.T],needsArgs*/
+/*strong.element: method9:direct,explicit=[method9.T],needsArgs,needsInst=[<num>,<num>]*/
/*omit.element: method9:*/
num method9<T>(num n, T t) => null;
diff --git a/tests/compiler/dart2js/rti/rti_need_test_helper.dart b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
index 7386d6a..3e809b1 100644
--- a/tests/compiler/dart2js/rti/rti_need_test_helper.dart
+++ b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
@@ -15,6 +15,7 @@
import 'package:compiler/src/kernel/element_map.dart';
import 'package:compiler/src/kernel/kernel_backend_strategy.dart';
import 'package:compiler/src/kernel/kernel_strategy.dart';
+import 'package:compiler/src/universe/feature.dart';
import 'package:compiler/src/universe/selector.dart';
import 'package:compiler/src/universe/world_builder.dart';
import 'package:kernel/ast.dart' as ir;
@@ -56,6 +57,7 @@
static const String indirectTypeArgumentTest = 'indirect';
static const String typeLiteral = 'exp';
static const String selectors = 'selectors';
+ static const String instantiationsNeedTypeArguments = 'needsInst';
}
abstract class ComputeValueMixin<T> {
@@ -162,6 +164,13 @@
features.addElement(Tags.selectors, selector);
}
});
+ rtiNeedBuilder.instantiationsNeedingTypeArgumentsForTesting?.forEach(
+ (GenericInstantiation instantiation, Set<Entity> targets) {
+ if (targets.contains(entity)) {
+ features.addElement(
+ Tags.instantiationsNeedTypeArguments, instantiation.shortText);
+ }
+ });
}
if (frontendClosure != null) {
diff --git a/tests/compiler/dart2js_extra/generic_instantiation1_test.dart b/tests/compiler/dart2js_extra/generic_instantiation1_test.dart
new file mode 100644
index 0000000..fcfb79f
--- /dev/null
+++ b/tests/compiler/dart2js_extra/generic_instantiation1_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+// dart2jsOptions=--strong
+
+int f<T>(T a) => null;
+
+typedef int F<R>(R a);
+
+class B<S> {
+ F<S> c;
+
+ B() : c = f;
+}
+
+main() {
+ new B<int>().c(0);
+}
diff --git a/tests/compiler/dart2js_extra/generic_instantiation2_test.dart b/tests/compiler/dart2js_extra/generic_instantiation2_test.dart
new file mode 100644
index 0000000..047d221
--- /dev/null
+++ b/tests/compiler/dart2js_extra/generic_instantiation2_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+// dart2jsOptions=--strong --omit-implicit-checks
+
+int f<T>(T a) => null;
+
+typedef int F<R>(R a);
+
+class B<S> {
+ F<S> c;
+
+ B() : c = f;
+}
+
+main() {
+ new B<int>().c(0);
+}
diff --git a/tests/compiler/dart2js_extra/generic_instantiation3_test.dart b/tests/compiler/dart2js_extra/generic_instantiation3_test.dart
new file mode 100644
index 0000000..3152565
--- /dev/null
+++ b/tests/compiler/dart2js_extra/generic_instantiation3_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+
+bool f<T, S>(T a, S b) => a is S;
+
+typedef bool F<P, Q>(P a, Q b);
+
+class B<X, Y> {
+ F<X, Y> c;
+
+ B() : c = f;
+}
+
+main() {
+ Expect.isTrue(new B<int, int>().c(0, 0));
+ Expect.isFalse(new B<int, String>().c(0, ''));
+}
diff --git a/tests/compiler/dart2js_extra/generic_instantiation4_test.dart b/tests/compiler/dart2js_extra/generic_instantiation4_test.dart
new file mode 100644
index 0000000..d5f8eb9
--- /dev/null
+++ b/tests/compiler/dart2js_extra/generic_instantiation4_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+// dart2jsOptions=--strong --omit-implicit-checks
+
+import 'package:expect/expect.dart';
+
+bool f<T, S>(T a, S b) => a is S;
+
+typedef bool F<P, Q>(P a, Q b);
+
+class B<X, Y> {
+ F<X, Y> c;
+
+ B() : c = f;
+}
+
+main() {
+ Expect.isTrue(new B<int, int>().c(0, 0));
+ Expect.isFalse(new B<int, String>().c(0, ''));
+}