Version 2.13.0-132.0.dev
Merge commit '3c5767ccd34d0aeaf084bbf50b0849e24c17d710' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
index a8634ca..830a57d 100644
--- a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
@@ -427,14 +427,8 @@
}
DoStatement statement = node;
var sb = _sourceBuilderAfterKeyword(statement.doKeyword);
- // I modified the code and ran the tests with both the old and new parser.
- // Apparently the old parser sometimes sticks something other than 'while'
- // into the whileKeyword field, which causes statement completion to throw
- // an exception further downstream.
- // TODO(danrubel): change `statement.whileKeyword?.lexeme == "while"`
- // to `statement.whileKeyword != null` once the fasta parser is the default.
- var hasWhileKeyword = statement.whileKeyword?.lexeme == 'while' &&
- !statement.whileKeyword.isSynthetic;
+ var hasWhileKeyword =
+ statement.whileKeyword != null && !statement.whileKeyword.isSynthetic;
var exitDelta = 0;
if (!_statementHasValidBody(statement.doKeyword, statement.body)) {
var text = utils.getNodeText(statement.body);
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index bd86522..2090cf6 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -96,8 +96,6 @@
/// where there is no `new` or `const` keyword.
bool get suggestConstructorsWithoutNew => true;
- bool get usingFastaParser => true;
-
void addTestSource(String content) {
expect(completionOffset, isNull, reason: 'Call addTestUnit exactly once');
completionOffset = content.indexOf('^');
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 5bda1ad..84b0ba8 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -528,9 +528,7 @@
Future<void> test_anonymous_function_async7() async {
addTestSource('main() {foo("bar", () as^ => null');
await computeSuggestions();
- assertSuggestKeywords([],
- pseudoKeywords:
- usingFastaParser ? ['async'] : ['async', 'async*', 'sync*']);
+ assertSuggestKeywords([], pseudoKeywords: ['async']);
}
Future<void> test_anonymous_function_async8() async {
@@ -916,17 +914,13 @@
Future<void> test_class_implements2() async {
addTestSource('class A e^ implements foo');
await computeSuggestions();
- assertSuggestKeywords(usingFastaParser
- ? [Keyword.EXTENDS]
- : [Keyword.EXTENDS, Keyword.IMPLEMENTS]);
+ assertSuggestKeywords([Keyword.EXTENDS]);
}
Future<void> test_class_implements3() async {
addTestSource('class A e^ implements foo { }');
await computeSuggestions();
- assertSuggestKeywords(usingFastaParser
- ? [Keyword.EXTENDS]
- : [Keyword.EXTENDS, Keyword.IMPLEMENTS]);
+ assertSuggestKeywords([Keyword.EXTENDS]);
}
Future<void> test_class_implements_name() async {
diff --git a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
index 504dc74..5d99721 100644
--- a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
+++ b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
@@ -1398,17 +1398,7 @@
(s) => _afterLast(s, ' '));
}
- @failingTest
Future<void> test_noCloseParenWithSemicolon() async {
- // TODO(danrubel):
- // Fasta scanner produces an error message which is converted into
- // an Analyzer error message before the fasta parser gets a chance
- // to move it along with the associated synthetic ')' to a more
- // appropriate location. This means that some statement completions,
- // which are expecting errors in a particular location, don't work.
- // Fixing this properly means modifying the scanner not to generate
- // closing ')', then updating the parser to handle that situation.
- // This is a fair amount of work and won't be tackled today.
var before = '''
main() {
var s = 'sample'.substring(3;
@@ -1427,12 +1417,6 @@
await _prepareCompletion('ing(3;', before, atEnd: true);
_assertHasChange('Insert a newline at the end of the current line', after,
(s) => _afterLast(s, ' '));
-
- // The old Analyzer parser passes this test, but will be turned off soon.
- // It is preferable to throw only if the old analyzer is being used,
- // but there does not seem to be a reliable way to determine that here.
- // TODO(danrubel): remove this once fasta parser is enabled by default.
- throw 'remove this once fasta parser is enabled by default';
}
Future<void> test_semicolonFn() async {
@@ -1507,12 +1491,6 @@
f() {}
''',
(s) => _afterLast(s, ' '));
-
- // The old Analyzer parser passes this test, but will be turned off soon.
- // It is preferable to throw only if the old analyzer is being used,
- // but there does not seem to be a reliable way to determine that here.
- // TODO(danrubel): remove this once fasta parser is enabled by default.
- throw 'remove this once fasta parser is enabled by default';
}
Future<void> test_semicolonFnExpr() async {
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 4c261da..41e58eb 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -1381,7 +1381,7 @@
@override
bool visitNeverType(NeverType type, List<FunctionTypeVariable> bindings) =>
- false;
+ handleNeverType(type);
@override
bool visitVoidType(VoidType type, List<FunctionTypeVariable> bindings) =>
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index 474f127..fee1573 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -415,11 +415,17 @@
case ConstantValueKind.SET:
case ConstantValueKind.MAP:
case ConstantValueKind.CONSTRUCTED:
- case ConstantValueKind.INSTANTIATION:
case ConstantValueKind.LIST:
transformed.registerStaticUse(StaticUse.staticInvoke(
_closedWorld.commonElements.findType, CallStructure.ONE_ARG));
break;
+ case ConstantValueKind.INSTANTIATION:
+ transformed.registerStaticUse(StaticUse.staticInvoke(
+ _closedWorld.commonElements.findType, CallStructure.ONE_ARG));
+ InstantiationConstantValue instantiation = constantUse.value;
+ _rtiChecksBuilder.registerGenericInstantiation(GenericInstantiation(
+ instantiation.function.type, instantiation.typeArguments));
+ break;
case ConstantValueKind.DEFERRED_GLOBAL:
_closedWorld.outputUnitData
.registerConstantDeferredUse(constantUse.value);
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index c24e828..e7113df 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -533,7 +533,6 @@
TypeVariableTests typeVariableTests = new TypeVariableTests(
_elementEnvironment,
_commonElements,
- _types,
codegenWorld,
_genericInstantiations,
forRtiNeeds: false);
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
index 7afc77e..9348b79 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
@@ -197,11 +197,17 @@
}
class TypeVariableTests {
- Map<ClassEntity, ClassNode> _classes = {};
- Map<Entity, MethodNode> _methods = {};
- Map<MemberEntity, CallablePropertyNode> _callableProperties = {};
+ final ElementEnvironment _elementEnvironment;
+ final CommonElements _commonElements;
+ final BuiltWorld _world;
+ final Set<GenericInstantiation> _genericInstantiations;
+ final bool forRtiNeeds;
+
+ final Map<ClassEntity, ClassNode> _classes = {};
+ final Map<Entity, MethodNode> _methods = {};
+ final Map<MemberEntity, CallablePropertyNode> _callableProperties = {};
Map<Selector, Set<Entity>> _appliedSelectorMap;
- Map<GenericInstantiation, Set<Entity>> _instantiationMap;
+ final Map<Entity, Set<GenericInstantiation>> _instantiationMap = {};
/// All explicit is-tests.
final Set<DartType> explicitIsChecks;
@@ -209,25 +215,20 @@
/// All implicit is-tests.
final Set<DartType> implicitIsChecks = new Set<DartType>();
- TypeVariableTests(
- ElementEnvironment elementEnvironment,
- CommonElements commonElements,
- DartTypes types,
- BuiltWorld world,
- Set<GenericInstantiation> genericInstantiations,
- {bool forRtiNeeds: true})
- : explicitIsChecks = new Set<DartType>.from(world.isChecks) {
- _setupDependencies(
- elementEnvironment, commonElements, world, genericInstantiations,
- forRtiNeeds: forRtiNeeds);
- _propagateTests(commonElements, elementEnvironment, world);
+ TypeVariableTests(this._elementEnvironment, this._commonElements, this._world,
+ this._genericInstantiations,
+ {this.forRtiNeeds: true})
+ : explicitIsChecks = _world.isChecks.toSet() {
+ _setupDependencies();
+ _propagateTests();
if (forRtiNeeds) {
- _propagateLiterals(elementEnvironment, world);
+ _propagateLiterals();
}
- _collectResults(commonElements, elementEnvironment, types, world,
- forRtiNeeds: forRtiNeeds);
+ _collectResults();
}
+ DartTypes get _dartTypes => _commonElements.dartTypes;
+
/// Classes whose type variables are explicitly or implicitly used in
/// is-tests.
///
@@ -323,9 +324,9 @@
/// Calls [f] for each generic instantiation that applies to generic
/// closurized [targets].
- void forEachGenericInstantiation(
- void f(GenericInstantiation instantiation, Set<Entity> targets)) {
- _instantiationMap?.forEach(f);
+ void forEachInstantiatedEntity(
+ void f(Entity target, Set<GenericInstantiation> instantiations)) {
+ _instantiationMap.forEach(f);
}
ClassNode _getClassNode(ClassEntity cls) {
@@ -366,12 +367,7 @@
_callableProperties.putIfAbsent(
property, () => CallablePropertyNode(property, type));
- void _setupDependencies(
- ElementEnvironment elementEnvironment,
- CommonElements commonElements,
- BuiltWorld world,
- Set<GenericInstantiation> genericInstantiations,
- {bool forRtiNeeds: true}) {
+ void _setupDependencies() {
/// Register that if `node.entity` needs type arguments then so do entities
/// whose type variables occur in [type].
///
@@ -387,11 +383,33 @@
node.addDependency(_getClassNode(typeDeclaration));
} else {
node.addDependency(
- _getMethodNode(elementEnvironment, world, typeDeclaration));
+ _getMethodNode(_elementEnvironment, _world, typeDeclaration));
}
});
}
+ void registerDependenciesForInstantiation(RtiNode node, DartType type) {
+ void onInterface(InterfaceType type) {
+ if (type.typeArguments.isNotEmpty) {
+ node.addDependency(_getClassNode(type.element));
+ }
+ }
+
+ void onTypeVariable(TypeVariableType type) {
+ Entity declaration = type.element.typeDeclaration;
+ if (declaration is ClassEntity) {
+ node.addDependency(_getClassNode(declaration));
+ } else {
+ node.addDependency(
+ _getMethodNode(_elementEnvironment, _world, declaration));
+ }
+ }
+
+ _DependencyVisitor(
+ onInterface: onInterface, onTypeVariable: onTypeVariable)
+ .run(type);
+ }
+
// Add the rti dependencies that are implicit in the way the backend
// generates code: when we create a new [List], we actually create a
// [JSArray] in the backend and we need to add type arguments to the calls
@@ -412,17 +430,17 @@
//
// TODO(johnniwinther): Make this dependency visible from code, possibly
// using generic methods.
- if (commonElements.jsArrayClass != null) {
- _getClassNode(commonElements.jsArrayClass)
- .addDependency(_getClassNode(commonElements.listClass));
+ if (_commonElements.jsArrayClass != null) {
+ _getClassNode(_commonElements.jsArrayClass)
+ .addDependency(_getClassNode(_commonElements.listClass));
}
- if (commonElements.setLiteralClass != null) {
- _getClassNode(commonElements.setLiteralClass)
- .addDependency(_getClassNode(commonElements.setClass));
+ if (_commonElements.setLiteralClass != null) {
+ _getClassNode(_commonElements.setLiteralClass)
+ .addDependency(_getClassNode(_commonElements.setClass));
}
- if (commonElements.mapLiteralClass != null) {
- _getClassNode(commonElements.mapLiteralClass)
- .addDependency(_getClassNode(commonElements.mapClass));
+ if (_commonElements.mapLiteralClass != null) {
+ _getClassNode(_commonElements.mapLiteralClass)
+ .addDependency(_getClassNode(_commonElements.mapClass));
}
void processCheckedType(DartType type) {
@@ -439,36 +457,36 @@
// For the implied `is Future<X>` test, register that if `Future` needs
// type arguments then so do the entities that declare type variables
// occurring in `type.typeArgument`.
- registerDependencies(_getClassNode(commonElements.futureClass),
+ registerDependencies(_getClassNode(_commonElements.futureClass),
typeWithoutNullability.typeArgument);
// Process `type.typeArgument` for the implied `is X` test.
processCheckedType(typeWithoutNullability.typeArgument);
}
}
- world.isChecks.forEach(processCheckedType);
+ _world.isChecks.forEach(processCheckedType);
- world.instantiatedTypes.forEach((InterfaceType type) {
+ _world.instantiatedTypes.forEach((InterfaceType type) {
// Register that if [cls] needs type arguments then so do the entities
// that declare type variables occurring in [type].
ClassEntity cls = type.element;
registerDependencies(_getClassNode(cls), type);
});
- world.forEachStaticTypeArgument(
+ _world.forEachStaticTypeArgument(
(Entity entity, Iterable<DartType> typeArguments) {
for (DartType type in typeArguments) {
// Register that if [entity] needs type arguments then so do the
// entities that declare type variables occurring in [type].
registerDependencies(
- _getMethodNode(elementEnvironment, world, entity), type);
+ _getMethodNode(_elementEnvironment, _world, entity), type);
}
});
- world.forEachDynamicTypeArgument(
+ _world.forEachDynamicTypeArgument(
(Selector selector, Iterable<DartType> typeArguments) {
void processCallableNode(CallableNode node) {
- if (node.selectorApplies(selector, world)) {
+ if (node.selectorApplies(selector, _world)) {
for (DartType type in typeArguments) {
// Register that if `node.entity` needs type arguments then so do
// the entities that declare type variables occurring in [type].
@@ -478,7 +496,7 @@
}
void processMethod(Entity entity) {
- MethodNode node = _getMethodNode(elementEnvironment, world, entity);
+ MethodNode node = _getMethodNode(_elementEnvironment, _world, entity);
processCallableNode(node);
}
@@ -487,47 +505,38 @@
processCallableNode(node);
}
- world.forEachGenericInstanceMethod(processMethod);
- world.genericLocalFunctions.forEach(processMethod);
- world.closurizedStatics.forEach(processMethod);
- world.userNoSuchMethods.forEach(processMethod);
- world.genericCallableProperties.forEach(processCallableProperty);
+ _world.forEachGenericInstanceMethod(processMethod);
+ _world.genericLocalFunctions.forEach(processMethod);
+ _world.closurizedStatics.forEach(processMethod);
+ _world.userNoSuchMethods.forEach(processMethod);
+ _world.genericCallableProperties.forEach(processCallableProperty);
});
- for (GenericInstantiation instantiation in genericInstantiations) {
+ for (GenericInstantiation instantiation in _genericInstantiations) {
void processEntity(Entity entity) {
- MethodNode node = _getMethodNode(elementEnvironment, world, entity);
- if (node.parameterStructure.typeParameters ==
- instantiation.typeArguments.length) {
- if (forRtiNeeds) {
- _instantiationMap ??= <GenericInstantiation, Set<Entity>>{};
- _instantiationMap
- .putIfAbsent(instantiation, () => new Set<Entity>())
- .add(entity);
- }
+ MethodNode node = _getMethodNode(_elementEnvironment, _world, entity);
+ if (node.parameterStructure ==
+ ParameterStructure.fromType(instantiation.functionType)) {
+ _instantiationMap.putIfAbsent(entity, () => {}).add(instantiation);
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);
+ registerDependenciesForInstantiation(node, type);
}
}
}
- world.closurizedMembers.forEach(processEntity);
- world.closurizedStatics.forEach(processEntity);
- world.genericLocalFunctions.forEach(processEntity);
+ _world.closurizedMembers.forEach(processEntity);
+ _world.closurizedStatics.forEach(processEntity);
+ _world.genericLocalFunctions.forEach(processEntity);
}
}
- void _propagateTests(CommonElements commonElements,
- ElementEnvironment elementEnvironment, BuiltWorld worldBuilder) {
+ void _propagateTests() {
void processTypeVariableType(TypeVariableType type, {bool direct: true}) {
TypeVariableEntity variable = type.element;
if (variable.typeDeclaration is ClassEntity) {
_getClassNode(variable.typeDeclaration).markTest(direct: direct);
} else {
- _getMethodNode(
- elementEnvironment, worldBuilder, variable.typeDeclaration)
+ _getMethodNode(_elementEnvironment, _world, variable.typeDeclaration)
.markTest(direct: direct);
}
}
@@ -535,7 +544,7 @@
void processType(DartType type, {bool direct: true}) {
var typeWithoutNullability = type.withoutNullability;
if (typeWithoutNullability is FutureOrType) {
- _getClassNode(commonElements.futureClass).markIndirectTest();
+ _getClassNode(_commonElements.futureClass).markIndirectTest();
processType(typeWithoutNullability.typeArgument, direct: false);
} else {
typeWithoutNullability.forEachTypeVariable((TypeVariableType type) {
@@ -544,17 +553,17 @@
}
}
- worldBuilder.isChecks.forEach(processType);
+ _world.isChecks.forEach(processType);
}
- void _propagateLiterals(
- ElementEnvironment elementEnvironment, BuiltWorld world) {
- world.typeVariableTypeLiterals.forEach((TypeVariableType typeVariableType) {
+ void _propagateLiterals() {
+ _world.typeVariableTypeLiterals
+ .forEach((TypeVariableType typeVariableType) {
TypeVariableEntity variable = typeVariableType.element;
if (variable.typeDeclaration is ClassEntity) {
_getClassNode(variable.typeDeclaration).markDirectLiteral();
} else {
- _getMethodNode(elementEnvironment, world, variable.typeDeclaration)
+ _getMethodNode(_elementEnvironment, _world, variable.typeDeclaration)
.markDirectLiteral();
}
});
@@ -608,34 +617,45 @@
return sb.toString();
}
- void _collectResults(CommonElements commonElements,
- ElementEnvironment elementEnvironment, DartTypes types, BuiltWorld world,
- {bool forRtiNeeds: true}) {
- /// Register the implicit is-test of [type].
- ///
- /// If [type] is of the form `FutureOr<X>`, also register the implicit
- /// is-tests of `Future<X>` and `X`.
- void addImplicitCheck(DartType type) {
- var typeWithoutNullability = type.withoutNullability;
- if (implicitIsChecks.add(typeWithoutNullability)) {
- if (typeWithoutNullability is FutureOrType) {
- addImplicitCheck(
- commonElements.futureType(typeWithoutNullability.typeArgument));
- addImplicitCheck(typeWithoutNullability.typeArgument);
- }
+ /// Register the implicit is-test of [type].
+ ///
+ /// If [type] is of the form `FutureOr<X>`, also register the implicit
+ /// is-tests of `Future<X>` and `X`.
+ void _addImplicitCheck(DartType type) {
+ var typeWithoutNullability = type.withoutNullability;
+ if (implicitIsChecks.add(typeWithoutNullability)) {
+ if (typeWithoutNullability is FutureOrType) {
+ _addImplicitCheck(
+ _commonElements.futureType(typeWithoutNullability.typeArgument));
+ _addImplicitCheck(typeWithoutNullability.typeArgument);
+ } else if (typeWithoutNullability is TypeVariableType) {
+ _addImplicitChecksViaInstantiation(typeWithoutNullability);
}
}
+ }
- void addImplicitChecks(Iterable<DartType> types) {
- types.forEach(addImplicitCheck);
- }
+ void _addImplicitChecks(Iterable<DartType> types) {
+ types.forEach(_addImplicitCheck);
+ }
- world.isChecks.forEach((DartType type) {
+ void _addImplicitChecksViaInstantiation(TypeVariableType variable) {
+ TypeVariableEntity entity = variable.element;
+ Entity declaration = entity.typeDeclaration;
+ _instantiationMap[declaration]
+ ?.forEach((GenericInstantiation instantiation) {
+ _addImplicitCheck(instantiation.typeArguments[entity.index]);
+ });
+ }
+
+ void _collectResults() {
+ _world.isChecks.forEach((DartType type) {
var typeWithoutNullability = type.withoutNullability;
if (typeWithoutNullability is FutureOrType) {
- addImplicitCheck(
- commonElements.futureType(typeWithoutNullability.typeArgument));
- addImplicitCheck(typeWithoutNullability.typeArgument);
+ _addImplicitCheck(
+ _commonElements.futureType(typeWithoutNullability.typeArgument));
+ _addImplicitCheck(typeWithoutNullability.typeArgument);
+ } else if (typeWithoutNullability is TypeVariableType) {
+ _addImplicitChecksViaInstantiation(typeWithoutNullability);
}
});
@@ -646,45 +666,45 @@
// Find all instantiated types that are a subtype of a class that uses
// one of its type arguments in an is-check and add the arguments to the
// set of is-checks.
- for (InterfaceType type in world.instantiatedTypes) {
+ for (InterfaceType type in _world.instantiatedTypes) {
// We need the type as instance of its superclass anyway, so we just
// try to compute the substitution; if the result is [:null:], the
// classes are not related.
- InterfaceType instance = types.asInstanceOf(type, cls);
+ InterfaceType instance = _dartTypes.asInstanceOf(type, cls);
if (instance != null) {
for (DartType argument in instance.typeArguments) {
- addImplicitCheck(argument);
+ _addImplicitCheck(argument);
}
}
}
});
- world.forEachStaticTypeArgument(
+ _world.forEachStaticTypeArgument(
(Entity function, Iterable<DartType> typeArguments) {
- if (!_getMethodNode(elementEnvironment, world, function).hasTest) {
+ if (!_getMethodNode(_elementEnvironment, _world, function).hasTest) {
return;
}
- addImplicitChecks(typeArguments);
+ _addImplicitChecks(typeArguments);
});
if (forRtiNeeds) {
_appliedSelectorMap = <Selector, Set<Entity>>{};
}
- world.forEachDynamicTypeArgument(
+ _world.forEachDynamicTypeArgument(
(Selector selector, Iterable<DartType> typeArguments) {
for (CallableNode node in [
..._methods.values,
..._callableProperties.values
]) {
- if (node.selectorApplies(selector, world)) {
+ if (node.selectorApplies(selector, _world)) {
if (forRtiNeeds) {
_appliedSelectorMap
.putIfAbsent(selector, () => {})
.add(node.entity);
}
if (node.hasTest) {
- addImplicitChecks(typeArguments);
+ _addImplicitChecks(typeArguments);
}
}
}
@@ -692,6 +712,25 @@
}
}
+class _DependencyVisitor extends DartTypeStructuralPredicateVisitor {
+ void Function(InterfaceType) onInterface;
+ void Function(TypeVariableType) onTypeVariable;
+
+ _DependencyVisitor({this.onInterface, this.onTypeVariable});
+
+ @override
+ bool handleInterfaceType(InterfaceType type) {
+ onInterface(type);
+ return false;
+ }
+
+ @override
+ bool handleTypeVariableType(TypeVariableType type) {
+ onTypeVariable(type);
+ return false;
+ }
+}
+
/// Interface for the classes and methods that need runtime types.
abstract class RuntimeTypesNeed {
/// Deserializes a [RuntimeTypesNeed] object from [source].
@@ -770,7 +809,7 @@
/// arguments.
// TODO(johnniwinther): Use [functionType].
bool instantiationNeedsTypeArguments(
- DartType functionType, int typeArgumentCount);
+ FunctionType functionType, int typeArgumentCount);
}
class TrivialRuntimeTypesNeed implements RuntimeTypesNeed {
@@ -804,7 +843,7 @@
@override
bool instantiationNeedsTypeArguments(
- DartType functionType, int typeArgumentCount) {
+ FunctionType functionType, int typeArgumentCount) {
return true;
}
}
@@ -903,7 +942,7 @@
@override
bool instantiationNeedsTypeArguments(
- DartType functionType, int typeArgumentCount) {
+ FunctionType functionType, int typeArgumentCount) {
return instantiationsNeedingTypeArguments.contains(typeArgumentCount);
}
}
@@ -963,8 +1002,11 @@
Map<Selector, Set<Entity>> selectorsNeedingTypeArgumentsForTesting;
- Map<GenericInstantiation, Set<Entity>>
- instantiationsNeedingTypeArgumentsForTesting;
+ Map<Entity, Set<GenericInstantiation>>
+ _instantiatedEntitiesNeedingTypeArgumentsForTesting;
+ Map<Entity, Set<GenericInstantiation>>
+ get instantiatedEntitiesNeedingTypeArgumentsForTesting =>
+ _instantiatedEntitiesNeedingTypeArgumentsForTesting ?? const {};
final Set<GenericInstantiation> _genericInstantiations =
new Set<GenericInstantiation>();
@@ -999,7 +1041,6 @@
TypeVariableTests typeVariableTests = new TypeVariableTests(
closedWorld.elementEnvironment,
closedWorld.commonElements,
- closedWorld.dartTypes,
closedWorld,
_genericInstantiations);
Set<ClassEntity> classesNeedingTypeArguments = new Set<ClassEntity>();
@@ -1348,24 +1389,19 @@
}
});
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 (retainDataForTesting) {
- instantiationsNeedingTypeArgumentsForTesting ??=
- <GenericInstantiation, Set<Entity>>{};
- instantiationsNeedingTypeArgumentsForTesting
- .putIfAbsent(instantiation, () => new Set<Entity>())
- .add(target);
- } else {
- return;
- }
+ typeVariableTests.forEachInstantiatedEntity(
+ (Entity target, Set<GenericInstantiation> instantiations) {
+ if (methodsNeedingTypeArguments.contains(target) ||
+ localFunctionsNeedingTypeArguments.contains(target)) {
+ // TODO(johnniwinther): Use the static type of the instantiated
+ // expression.
+ instantiationsNeedingTypeArguments
+ .add(instantiations.first.typeArguments.length);
+ if (retainDataForTesting) {
+ _instantiatedEntitiesNeedingTypeArgumentsForTesting ??= {};
+ _instantiatedEntitiesNeedingTypeArgumentsForTesting
+ .putIfAbsent(target, () => {})
+ .addAll(instantiations);
}
}
});
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 41f9170..216f25e 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -1411,5 +1411,5 @@
bool selectorNeedsTypeArguments(Selector selector);
bool instantiationNeedsTypeArguments(
- DartType functionType, int typeArgumentCount);
+ FunctionType functionType, int typeArgumentCount);
}
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index f2fdbe6..c07ccea 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -528,7 +528,7 @@
@override
bool instantiationNeedsTypeArguments(
- DartType functionType, int typeArgumentCount) =>
+ FunctionType functionType, int typeArgumentCount) =>
true;
}
@@ -568,7 +568,7 @@
@override
bool instantiationNeedsTypeArguments(
- DartType functionType, int typeArgumentCount) =>
+ FunctionType functionType, int typeArgumentCount) =>
rtiNeed.instantiationNeedsTypeArguments(functionType, typeArgumentCount);
}
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index f3df3a2..9a40f68 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -700,7 +700,7 @@
ir.FunctionType expressionType, List<ir.DartType> typeArguments) {
// TODO(johnniwinther): Track which arities are used in instantiation.
impactBuilder.registerInstantiation(new GenericInstantiation(
- elementMap.getDartType(expressionType),
+ elementMap.getDartType(expressionType).withoutNullability,
typeArguments.map(elementMap.getDartType).toList()));
}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 083df95..2831f5c 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -5193,15 +5193,16 @@
node.expression.accept(this);
arguments.add(pop());
StaticType expressionType = _getStaticType(node.expression);
+ FunctionType functionType = expressionType.type.withoutNullability;
bool typeArgumentsNeeded = _rtiNeed.instantiationNeedsTypeArguments(
- expressionType.type, node.typeArguments.length);
+ functionType, node.typeArguments.length);
List<DartType> typeArguments = node.typeArguments
.map((type) => typeArgumentsNeeded
? _elementMap.getDartType(type)
: _commonElements.dynamicType)
.toList();
registry.registerGenericInstantiation(
- new GenericInstantiation(expressionType.type, typeArguments));
+ new GenericInstantiation(functionType, typeArguments));
// TODO(johnniwinther): Can we avoid creating the instantiation object?
for (DartType type in typeArguments) {
HInstruction instruction =
diff --git a/pkg/compiler/lib/src/universe/feature.dart b/pkg/compiler/lib/src/universe/feature.dart
index 7ea60b7..f907c36 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -237,7 +237,7 @@
static const String tag = 'generic-instantiation';
/// The static type of the instantiated expression.
- final DartType functionType;
+ final FunctionType functionType;
/// The type arguments of the instantiation.
final List<DartType> typeArguments;
diff --git a/pkg/compiler/test/rti/data/instantiation1.dart b/pkg/compiler/test/rti/data/instantiation1.dart
index 8fbd5f3..c838bbe 100644
--- a/pkg/compiler/test/rti/data/instantiation1.dart
+++ b/pkg/compiler/test/rti/data/instantiation1.dart
@@ -10,7 +10,7 @@
typedef int F<R>(R a);
-/*spec.class: B:explicit=[int* Function(B.S*)*],indirect,needsArgs*/
+/*spec.class: B:explicit=[int* Function(B.S*)*],implicit=[B.S],indirect,needsArgs*/
class B<S> {
F<S> c;
diff --git a/pkg/compiler/test/rti/data/instantiation2.dart b/pkg/compiler/test/rti/data/instantiation2.dart
index dbb5db8..934152a 100644
--- a/pkg/compiler/test/rti/data/instantiation2.dart
+++ b/pkg/compiler/test/rti/data/instantiation2.dart
@@ -9,8 +9,8 @@
typedef bool F<R>(R a);
-/*spec.class: B:explicit=[bool* Function(B.S*)*],indirect,needsArgs*/
-/*prod.class: B:indirect,needsArgs*/
+/*spec.class: B:explicit=[bool* Function(B.S*)*],implicit=[B.S],indirect,needsArgs*/
+/*prod.class: B:implicit=[B.S],indirect,needsArgs*/
class B<S> {
F<S> c;
diff --git a/pkg/compiler/test/rti/data/instantiation3.dart b/pkg/compiler/test/rti/data/instantiation3.dart
index 96e7c7a..f852f9f 100644
--- a/pkg/compiler/test/rti/data/instantiation3.dart
+++ b/pkg/compiler/test/rti/data/instantiation3.dart
@@ -10,7 +10,7 @@
typedef int F<R>(R a);
-/*spec.class: B:direct,explicit=[int* Function(B.S*)*],needsArgs*/
+/*spec.class: B:direct,explicit=[int* Function(B.S*)*],implicit=[B.S],needsArgs*/
class B<S> {
F<S> c;
diff --git a/pkg/compiler/test/rti/data/instantiation4.dart b/pkg/compiler/test/rti/data/instantiation4.dart
index 7ec0433..be3b975 100644
--- a/pkg/compiler/test/rti/data/instantiation4.dart
+++ b/pkg/compiler/test/rti/data/instantiation4.dart
@@ -9,8 +9,8 @@
typedef bool F<R>(R a);
-/*spec.class: B:direct,explicit=[bool* Function(B.S*)*],needsArgs*/
-/*prod.class: B:indirect,needsArgs*/
+/*spec.class: B:direct,explicit=[bool* Function(B.S*)*],implicit=[B.S],needsArgs*/
+/*prod.class: B:implicit=[B.S],indirect,needsArgs*/
class B<S> {
F<S> c;
diff --git a/pkg/compiler/test/rti/data/instantiation5.dart b/pkg/compiler/test/rti/data/instantiation5.dart
index 80063c5..525be33 100644
--- a/pkg/compiler/test/rti/data/instantiation5.dart
+++ b/pkg/compiler/test/rti/data/instantiation5.dart
@@ -10,7 +10,7 @@
typedef int F<R>(R a);
-/*spec.member: method:indirect,needsArgs*/
+/*spec.member: method:implicit=[method.S],indirect,needsArgs*/
method<S>() {
F<S> c;
diff --git a/pkg/compiler/test/rti/data/instantiation6.dart b/pkg/compiler/test/rti/data/instantiation6.dart
index fdfa1d2..e596af2 100644
--- a/pkg/compiler/test/rti/data/instantiation6.dart
+++ b/pkg/compiler/test/rti/data/instantiation6.dart
@@ -9,7 +9,7 @@
typedef bool F<R>(R a);
-/*member: method:indirect,needsArgs*/
+/*member: method:implicit=[method.S],indirect,needsArgs*/
method<S>() {
F<S> c;
diff --git a/pkg/compiler/test/rti/data/instantiation7.dart b/pkg/compiler/test/rti/data/instantiation7.dart
index fda2e4a..a47924b 100644
--- a/pkg/compiler/test/rti/data/instantiation7.dart
+++ b/pkg/compiler/test/rti/data/instantiation7.dart
@@ -20,7 +20,7 @@
typedef int F2<R, P>(R a, P b, P c);
typedef int F3<R, P, Q>(R a, P b, Q c);
-/*spec.member: method:indirect,needsArgs*/
+/*spec.member: method:implicit=[method.X,method.Y,method.Z],indirect,needsArgs*/
method<X, Y, Z>() {
F1<X> c1;
F2<X, Y> c2;
diff --git a/pkg/compiler/test/rti/data/local_function_signatures_generic.dart b/pkg/compiler/test/rti/data/local_function_signatures_generic.dart
index dc86b33..7956fe4 100644
--- a/pkg/compiler/test/rti/data/local_function_signatures_generic.dart
+++ b/pkg/compiler/test/rti/data/local_function_signatures_generic.dart
@@ -89,8 +89,8 @@
}
method12() {
- /*spec.direct,explicit=[local.T*],needsArgs,needsInst=[<dynamic>,<num*>,<num*>],needsSignature*/
- /*prod.needsArgs,needsInst=[<dynamic>,<num*>,<num*>],needsSignature*/num local<T>(num n, T t) => null;
+ /*spec.direct,explicit=[local.T*],needsArgs,needsSignature*/
+ /*prod.needsArgs,needsSignature*/num local<T>(num n, T t) => null;
return local;
}
diff --git a/pkg/compiler/test/rti/data/method_signatures_generic.dart b/pkg/compiler/test/rti/data/method_signatures_generic.dart
index b3866f8..0d2c352 100644
--- a/pkg/compiler/test/rti/data/method_signatures_generic.dart
+++ b/pkg/compiler/test/rti/data/method_signatures_generic.dart
@@ -28,7 +28,7 @@
}
class Class4 {
- /*spec.member: Class4.method6:direct,explicit=[method6.T*],needsArgs,needsInst=[<num*>,<num*>,<num*>,<num*>]*/
+ /*spec.member: Class4.method6:direct,explicit=[method6.T*],needsArgs*/
num method6<T>(num n, T t) => null;
}
@@ -38,7 +38,7 @@
/*member: method8:*/
T method8<T>(num n) => null;
-/*spec.member: method9:direct,explicit=[method9.T*],needsArgs,needsInst=[<num*>,<num*>,<num*>,<num*>]*/
+/*spec.member: method9:direct,explicit=[method9.T*],needsArgs*/
num method9<T>(num n, T t) => null;
@pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/rti/rti_need_test_helper.dart b/pkg/compiler/test/rti/rti_need_test_helper.dart
index 4170976..4206006 100644
--- a/pkg/compiler/test/rti/rti_need_test_helper.dart
+++ b/pkg/compiler/test/rti/rti_need_test_helper.dart
@@ -160,12 +160,11 @@
features.addElement(Tags.selectors, selector);
}
});
- rtiNeedBuilder.instantiationsNeedingTypeArgumentsForTesting?.forEach(
- (GenericInstantiation instantiation, Set<Entity> targets) {
- if (targets.contains(entity)) {
- features.addElement(
- Tags.instantiationsNeedTypeArguments, instantiation.shortText);
- }
+ rtiNeedBuilder
+ .instantiatedEntitiesNeedingTypeArgumentsForTesting[entity]
+ ?.forEach((GenericInstantiation instantiation) {
+ features.addElement(
+ Tags.instantiationsNeedTypeArguments, instantiation.shortText);
});
}
diff --git a/tests/web/45046_test.dart b/tests/web/45046_test.dart
new file mode 100644
index 0000000..1e4f9b1
--- /dev/null
+++ b/tests/web/45046_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2021, 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.
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+class B extends A {}
+
+class Foo<T> {}
+
+T cast<T>(dynamic x) => x as T;
+
+void test(Foo<A> Function(dynamic) f) {
+ var foo = Foo<B>();
+ Expect.identical(foo, f(foo));
+}
+
+void main() {
+ test(cast);
+}
diff --git a/tests/web_2/45046_test.dart b/tests/web_2/45046_test.dart
new file mode 100644
index 0000000..7f5333e
--- /dev/null
+++ b/tests/web_2/45046_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2021, 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.
+
+// @dart = 2.7
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+class B extends A {}
+
+class Foo<T> {}
+
+T cast<T>(dynamic x) => x as T;
+
+void test(Foo<A> Function(dynamic) f) {
+ var foo = Foo<B>();
+ Expect.identical(foo, f(foo));
+}
+
+void main() {
+ test(cast);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 5b87bd5..132037c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 131
+PRERELEASE 132
PRERELEASE_PATCH 0
\ No newline at end of file