| Index: pkg/compiler/lib/src/js_backend/runtime_types.dart
|
| diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
|
| index 9b54dcd33f539775817e284b82318634206d2440..691cff236f51e861c595eb419b16ff0d8fdf9f4e 100644
|
| --- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
|
| +++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
|
| @@ -2,28 +2,46 @@
|
| // 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.
|
|
|
| -part of js_backend.backend;
|
| +library js_backend.runtime_types;
|
| +
|
| +import '../common_elements.dart' show CommonElements, ElementEnvironment;
|
| +import '../elements/elements.dart' show ClassElement;
|
| +import '../elements/entities.dart';
|
| +import '../elements/resolution_types.dart'
|
| + show
|
| + MalformedType,
|
| + MethodTypeVariableType,
|
| + ResolutionDartTypeVisitor,
|
| + ResolutionTypedefType,
|
| + Types;
|
| +import '../elements/types.dart';
|
| +import '../js/js.dart' as jsAst;
|
| +import '../js/js.dart' show js;
|
| +import '../js_emitter/js_emitter.dart' show Emitter;
|
| +import '../universe/world_builder.dart';
|
| +import '../world.dart' show ClosedWorld;
|
| +import 'backend_usage.dart';
|
| +import 'namer.dart';
|
|
|
| /// For each class, stores the possible class subtype tests that could succeed.
|
| abstract class TypeChecks {
|
| /// Get the set of checks required for class [element].
|
| - Iterable<TypeCheck> operator [](ClassElement element);
|
| + Iterable<TypeCheck> operator [](ClassEntity element);
|
|
|
| /// Get the iterable for all classes that need type checks.
|
| - Iterable<ClassElement> get classes;
|
| + Iterable<ClassEntity> get classes;
|
| }
|
|
|
| -typedef jsAst.Expression OnVariableCallback(
|
| - ResolutionTypeVariableType variable);
|
| +typedef jsAst.Expression OnVariableCallback(TypeVariableType variable);
|
| typedef bool ShouldEncodeTypedefCallback(ResolutionTypedefType variable);
|
|
|
| /// Interface for the classes and methods that need runtime types.
|
| abstract class RuntimeTypesNeed {
|
| - bool classNeedsRti(ClassElement cls);
|
| - bool classNeedsRtiField(ClassElement cls);
|
| - bool methodNeedsRti(MethodElement function);
|
| - bool localFunctionNeedsRti(LocalFunctionElement function);
|
| - bool classUsesTypeVariableExpression(ClassElement cls);
|
| + bool classNeedsRti(ClassEntity cls);
|
| + bool classNeedsRtiField(ClassEntity cls);
|
| + bool methodNeedsRti(FunctionEntity function);
|
| + bool localFunctionNeedsRti(Local function);
|
| + bool classUsesTypeVariableExpression(ClassEntity cls);
|
| }
|
|
|
| /// Interface for computing classes and methods that need runtime types.
|
| @@ -63,44 +81,45 @@ abstract class RuntimeTypesChecks {
|
|
|
| /// Return all classes that are referenced in the type of the function, i.e.,
|
| /// in the return type or the argument types.
|
| - Set<ClassElement> getReferencedClasses(ResolutionFunctionType type);
|
| + Set<ClassEntity> getReferencedClasses(FunctionType type);
|
|
|
| /// Return all classes that are uses a type arguments.
|
| - Set<ClassElement> getRequiredArgumentClasses();
|
| + Set<ClassEntity> getRequiredArgumentClasses();
|
| }
|
|
|
| /// Interface for computing the needed runtime type checks.
|
| abstract class RuntimeTypesChecksBuilder {
|
| void registerTypeVariableBoundsSubtypeCheck(
|
| - ResolutionDartType typeArgument, ResolutionDartType bound);
|
| + DartType typeArgument, DartType bound);
|
|
|
| /// Computes the [RuntimeTypesChecks] for the data in this builder.
|
| - RuntimeTypesChecks computeRequiredChecks();
|
| + RuntimeTypesChecks computeRequiredChecks(
|
| + CodegenWorldBuilder codegenWorldBuilder);
|
|
|
| /// Compute type arguments of classes that use one of their type variables in
|
| /// is-checks and add the is-checks that they imply.
|
| ///
|
| /// This function must be called after all is-checks have been registered.
|
| void registerImplicitChecks(
|
| - WorldBuilder worldBuilder, Iterable<ClassElement> classesUsingChecks);
|
| + WorldBuilder worldBuilder, Iterable<ClassEntity> classesUsingChecks);
|
| }
|
|
|
| /// Interface for computing substitutions need for runtime type checks.
|
| abstract class RuntimeTypesSubstitutions {
|
| - bool isTrivialSubstitution(ClassElement cls, ClassElement check);
|
| + bool isTrivialSubstitution(ClassEntity cls, ClassEntity check);
|
|
|
| - Substitution getSubstitution(ClassElement cls, ClassElement other);
|
| + Substitution getSubstitution(ClassEntity cls, ClassEntity other);
|
|
|
| /// Compute the required type checks and substitutions for the given
|
| /// instantitated and checked classes.
|
| TypeChecks computeChecks(
|
| - Set<ClassElement> instantiated, Set<ClassElement> checked);
|
| + Set<ClassEntity> instantiated, Set<ClassEntity> checked);
|
|
|
| - Set<ClassElement> getClassesUsedInSubstitutions(TypeChecks checks);
|
| + Set<ClassEntity> getClassesUsedInSubstitutions(TypeChecks checks);
|
|
|
| - static bool hasTypeArguments(ResolutionDartType type) {
|
| - if (type is ResolutionInterfaceType) {
|
| - ResolutionInterfaceType interfaceType = type;
|
| + static bool hasTypeArguments(DartType type) {
|
| + if (type is InterfaceType) {
|
| + InterfaceType interfaceType = type;
|
| return !interfaceType.treatAsRaw;
|
| }
|
| return false;
|
| @@ -108,13 +127,13 @@ abstract class RuntimeTypesSubstitutions {
|
| }
|
|
|
| abstract class RuntimeTypesEncoder {
|
| - bool isSimpleFunctionType(ResolutionFunctionType type);
|
| + bool isSimpleFunctionType(FunctionType type);
|
|
|
| jsAst.Expression getSignatureEncoding(
|
| - Emitter emitter, ResolutionDartType type, jsAst.Expression this_);
|
| + Emitter emitter, DartType type, jsAst.Expression this_);
|
|
|
| - jsAst.Expression getSubstitutionRepresentation(Emitter emitter,
|
| - List<ResolutionDartType> types, OnVariableCallback onVariable);
|
| + jsAst.Expression getSubstitutionRepresentation(
|
| + Emitter emitter, List<DartType> types, OnVariableCallback onVariable);
|
| jsAst.Expression getSubstitutionCode(
|
| Emitter emitter, Substitution substitution);
|
|
|
| @@ -130,10 +149,10 @@ abstract class RuntimeTypesEncoder {
|
| /// Returns a [jsAst.Expression] representing the given [type]. Type variables
|
| /// are replaced by the [jsAst.Expression] returned by [onVariable].
|
| jsAst.Expression getTypeRepresentation(
|
| - Emitter emitter, ResolutionDartType type, OnVariableCallback onVariable,
|
| + Emitter emitter, DartType type, OnVariableCallback onVariable,
|
| [ShouldEncodeTypedefCallback shouldEncodeTypedef]);
|
|
|
| - String getTypeRepresentationForTypeConstant(ResolutionDartType type);
|
| + String getTypeRepresentationForTypeConstant(DartType type);
|
| }
|
|
|
| /// Common functionality for [_RuntimeTypesNeedBuilder] and [_RuntimeTypes].
|
| @@ -236,12 +255,12 @@ class _RuntimeTypesNeed implements RuntimeTypesNeed {
|
| return classesNeedingRti.contains(cls);
|
| }
|
|
|
| - bool methodNeedsRti(MethodElement function) {
|
| + bool methodNeedsRti(FunctionEntity function) {
|
| return methodsNeedingRti.contains(function) ||
|
| _backendUsage.isRuntimeTypeUsed;
|
| }
|
|
|
| - bool localFunctionNeedsRti(LocalFunctionElement function) {
|
| + bool localFunctionNeedsRti(Local function) {
|
| return localFunctionsNeedingRti.contains(function) ||
|
| _backendUsage.isRuntimeTypeUsed;
|
| }
|
| @@ -395,7 +414,7 @@ class RuntimeTypesNeedBuilderImpl extends _RuntimeTypesBase
|
| // information.
|
| resolutionWorldBuilder.isChecks.forEach((DartType type) {
|
| if (type.isInterfaceType) {
|
| - ResolutionInterfaceType itf = type;
|
| + InterfaceType itf = type;
|
| if (!itf.treatAsRaw) {
|
| potentiallyAddForRti(itf.element);
|
| }
|
| @@ -474,15 +493,15 @@ class ResolutionRuntimeTypesNeedBuilderImpl
|
| class _RuntimeTypesChecks implements RuntimeTypesChecks {
|
| final RuntimeTypesSubstitutions substitutions;
|
| final TypeChecks requiredChecks;
|
| - final Set<ClassElement> directlyInstantiatedArguments;
|
| - final Set<ClassElement> checkedArguments;
|
| + final Set<ClassEntity> directlyInstantiatedArguments;
|
| + final Set<ClassEntity> checkedArguments;
|
|
|
| _RuntimeTypesChecks(this.substitutions, this.requiredChecks,
|
| this.directlyInstantiatedArguments, this.checkedArguments);
|
|
|
| @override
|
| - Set<ClassElement> getRequiredArgumentClasses() {
|
| - Set<ClassElement> requiredArgumentClasses = new Set<ClassElement>.from(
|
| + Set<ClassEntity> getRequiredArgumentClasses() {
|
| + Set<ClassEntity> requiredArgumentClasses = new Set<ClassEntity>.from(
|
| substitutions.getClassesUsedInSubstitutions(requiredChecks));
|
| return requiredArgumentClasses
|
| ..addAll(directlyInstantiatedArguments)
|
| @@ -490,41 +509,35 @@ class _RuntimeTypesChecks implements RuntimeTypesChecks {
|
| }
|
|
|
| @override
|
| - Set<ClassElement> getReferencedClasses(ResolutionFunctionType type) {
|
| + Set<ClassEntity> getReferencedClasses(FunctionType type) {
|
| FunctionArgumentCollector collector = new FunctionArgumentCollector();
|
| collector.collect(type);
|
| return collector.classes;
|
| }
|
| }
|
|
|
| -class _RuntimeTypes extends _RuntimeTypesBase
|
| +class RuntimeTypesImpl extends _RuntimeTypesBase
|
| implements RuntimeTypesChecksBuilder, RuntimeTypesSubstitutions {
|
| - final Compiler compiler;
|
| + final ElementEnvironment _elementEnvironment;
|
|
|
| // The set of type arguments tested against type variable bounds.
|
| - final Set<ResolutionDartType> checkedTypeArguments;
|
| + final Set<DartType> checkedTypeArguments = new Set<DartType>();
|
| // The set of tested type variable bounds.
|
| - final Set<ResolutionDartType> checkedBounds;
|
| + final Set<DartType> checkedBounds = new Set<DartType>();
|
|
|
| TypeChecks cachedRequiredChecks;
|
|
|
| - JavaScriptBackend get backend => compiler.backend;
|
| -
|
| bool rtiChecksBuilderClosed = false;
|
|
|
| - _RuntimeTypes(Compiler compiler)
|
| - : this.compiler = compiler,
|
| - checkedTypeArguments = new Set<ResolutionDartType>(),
|
| - checkedBounds = new Set<ResolutionDartType>(),
|
| - super(compiler.types);
|
| + RuntimeTypesImpl(this._elementEnvironment, DartTypes types) : super(types);
|
|
|
| - Set<ClassElement> directlyInstantiatedArguments;
|
| - Set<ClassElement> allInstantiatedArguments;
|
| - Set<ClassElement> checkedArguments;
|
| + Set<ClassEntity> directlyInstantiatedArguments;
|
| + Set<ClassEntity> allInstantiatedArguments;
|
| + Set<ClassEntity> checkedArguments;
|
|
|
| @override
|
| void registerTypeVariableBoundsSubtypeCheck(
|
| - ResolutionDartType typeArgument, ResolutionDartType bound) {
|
| + DartType typeArgument, DartType bound) {
|
| checkedTypeArguments.add(typeArgument);
|
| checkedBounds.add(bound);
|
| }
|
| @@ -536,16 +549,14 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| // arguments and record all combination where the element of a checked
|
| // argument is a superclass of the element of an instantiated type.
|
| TypeCheckMapping result = new TypeCheckMapping();
|
| - for (ClassElement element in instantiated) {
|
| + for (ClassEntity element in instantiated) {
|
| if (checked.contains(element)) {
|
| result.add(element, element, null);
|
| }
|
| // Find all supertypes of [element] in [checkedArguments] and add checks
|
| // and precompute the substitutions for them.
|
| - assert(invariant(element, element.allSupertypes != null,
|
| - message: 'Supertypes have not been computed for $element.'));
|
| - for (ResolutionInterfaceType supertype in element.allSupertypes) {
|
| - ClassElement superelement = supertype.element;
|
| + for (InterfaceType supertype in _types.getSupertypes(element)) {
|
| + ClassEntity superelement = supertype.element;
|
| if (checked.contains(superelement)) {
|
| Substitution substitution =
|
| computeSubstitution(element, superelement);
|
| @@ -556,11 +567,12 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| return result;
|
| }
|
|
|
| - RuntimeTypesChecks computeRequiredChecks() {
|
| - Set<ResolutionDartType> isChecks = compiler.codegenWorldBuilder.isChecks;
|
| + RuntimeTypesChecks computeRequiredChecks(
|
| + CodegenWorldBuilder codegenWorldBuilder) {
|
| + Set<DartType> isChecks = codegenWorldBuilder.isChecks;
|
| // These types are needed for is-checks against function types.
|
| - Set<ResolutionDartType> instantiatedTypesAndClosures =
|
| - computeInstantiatedTypesAndClosures(compiler.codegenWorldBuilder);
|
| + Set<DartType> instantiatedTypesAndClosures =
|
| + computeInstantiatedTypesAndClosures(codegenWorldBuilder);
|
| computeInstantiatedArguments(instantiatedTypesAndClosures, isChecks);
|
| computeCheckedArguments(instantiatedTypesAndClosures, isChecks);
|
| cachedRequiredChecks =
|
| @@ -570,27 +582,24 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| directlyInstantiatedArguments, checkedArguments);
|
| }
|
|
|
| - Set<ResolutionDartType> computeInstantiatedTypesAndClosures(
|
| - CodegenWorldBuilder worldBuilder) {
|
| - Set<ResolutionDartType> instantiatedTypes =
|
| - new Set<ResolutionDartType>.from(worldBuilder.instantiatedTypes);
|
| - for (ResolutionInterfaceType instantiatedType
|
| - in worldBuilder.instantiatedTypes) {
|
| - ResolutionFunctionType callType = instantiatedType.callType;
|
| + Set<DartType> computeInstantiatedTypesAndClosures(
|
| + CodegenWorldBuilder codegenWorldBuilder) {
|
| + Set<DartType> instantiatedTypes =
|
| + new Set<DartType>.from(codegenWorldBuilder.instantiatedTypes);
|
| + for (InterfaceType instantiatedType
|
| + in codegenWorldBuilder.instantiatedTypes) {
|
| + FunctionType callType = _types.getCallType(instantiatedType);
|
| if (callType != null) {
|
| instantiatedTypes.add(callType);
|
| }
|
| }
|
| - for (FunctionElement element in worldBuilder.staticFunctionsNeedingGetter) {
|
| - instantiatedTypes.add(element.type);
|
| + for (FunctionEntity element
|
| + in codegenWorldBuilder.staticFunctionsNeedingGetter) {
|
| + instantiatedTypes.add(_elementEnvironment.getFunctionType(element));
|
| }
|
| - // TODO(johnniwinther): We should get this information through the
|
| - // [neededClasses] computed in the emitter instead of storing it and pulling
|
| - // it from resolution, but currently it would introduce a cyclic dependency
|
| - // between [computeRequiredChecks] and [computeNeededClasses].
|
| - for (MethodElement element
|
| - in compiler.resolutionWorldBuilder.closurizedMembers) {
|
| - instantiatedTypes.add(element.type);
|
| +
|
| + for (FunctionEntity element in codegenWorldBuilder.closurizedMembers) {
|
| + instantiatedTypes.add(_elementEnvironment.getFunctionType(element));
|
| }
|
| return instantiatedTypes;
|
| }
|
| @@ -602,8 +611,8 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| * have a type check against this supertype that includes a check against
|
| * the type arguments.
|
| */
|
| - void computeInstantiatedArguments(Set<ResolutionDartType> instantiatedTypes,
|
| - Set<ResolutionDartType> isChecks) {
|
| + void computeInstantiatedArguments(
|
| + Set<DartType> instantiatedTypes, Set<DartType> isChecks) {
|
| ArgumentCollector superCollector = new ArgumentCollector();
|
| ArgumentCollector directCollector = new ArgumentCollector();
|
| FunctionArgumentCollector functionArgumentCollector =
|
| @@ -611,8 +620,8 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
|
|
| // We need to add classes occurring in function type arguments, like for
|
| // instance 'I' for [: o is C<f> :] where f is [: typedef I f(); :].
|
| - void collectFunctionTypeArguments(Iterable<ResolutionDartType> types) {
|
| - for (ResolutionDartType type in types) {
|
| + void collectFunctionTypeArguments(Iterable<DartType> types) {
|
| + for (DartType type in types) {
|
| functionArgumentCollector.collect(type);
|
| }
|
| }
|
| @@ -620,13 +629,13 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| collectFunctionTypeArguments(isChecks);
|
| collectFunctionTypeArguments(checkedBounds);
|
|
|
| - void collectTypeArguments(Iterable<ResolutionDartType> types,
|
| + void collectTypeArguments(Iterable<DartType> types,
|
| {bool isTypeArgument: false}) {
|
| - for (ResolutionDartType type in types) {
|
| + for (DartType type in types) {
|
| directCollector.collect(type, isTypeArgument: isTypeArgument);
|
| - if (type.isInterfaceType) {
|
| - ClassElement cls = type.element;
|
| - for (ResolutionInterfaceType supertype in cls.allSupertypes) {
|
| + if (type is InterfaceType) {
|
| + ClassEntity cls = type.element;
|
| + for (InterfaceType supertype in _types.getSupertypes(cls)) {
|
| superCollector.collect(supertype, isTypeArgument: isTypeArgument);
|
| }
|
| }
|
| @@ -636,8 +645,8 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| collectTypeArguments(instantiatedTypes);
|
| collectTypeArguments(checkedTypeArguments, isTypeArgument: true);
|
|
|
| - for (ClassElement cls in superCollector.classes.toList()) {
|
| - for (ResolutionInterfaceType supertype in cls.allSupertypes) {
|
| + for (ClassEntity cls in superCollector.classes.toList()) {
|
| + for (InterfaceType supertype in _types.getSupertypes(cls)) {
|
| superCollector.collect(supertype);
|
| }
|
| }
|
| @@ -649,8 +658,8 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| }
|
|
|
| /// Collects all type arguments used in is-checks.
|
| - void computeCheckedArguments(Set<ResolutionDartType> instantiatedTypes,
|
| - Set<ResolutionDartType> isChecks) {
|
| + void computeCheckedArguments(
|
| + Set<DartType> instantiatedTypes, Set<DartType> isChecks) {
|
| ArgumentCollector collector = new ArgumentCollector();
|
| FunctionArgumentCollector functionArgumentCollector =
|
| new FunctionArgumentCollector();
|
| @@ -658,8 +667,8 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| // We need to add types occurring in function type arguments, like for
|
| // instance 'J' for [: (J j) {} is f :] where f is
|
| // [: typedef void f(I i); :] and 'J' is a subtype of 'I'.
|
| - void collectFunctionTypeArguments(Iterable<ResolutionDartType> types) {
|
| - for (ResolutionDartType type in types) {
|
| + void collectFunctionTypeArguments(Iterable<DartType> types) {
|
| + for (DartType type in types) {
|
| functionArgumentCollector.collect(type);
|
| }
|
| }
|
| @@ -667,9 +676,9 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| collectFunctionTypeArguments(instantiatedTypes);
|
| collectFunctionTypeArguments(checkedTypeArguments);
|
|
|
| - void collectTypeArguments(Iterable<ResolutionDartType> types,
|
| + void collectTypeArguments(Iterable<DartType> types,
|
| {bool isTypeArgument: false}) {
|
| - for (ResolutionDartType type in types) {
|
| + for (DartType type in types) {
|
| collector.collect(type, isTypeArgument: isTypeArgument);
|
| }
|
| }
|
| @@ -682,10 +691,10 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| }
|
|
|
| @override
|
| - Set<ClassElement> getClassesUsedInSubstitutions(TypeChecks checks) {
|
| - Set<ClassElement> instantiated = new Set<ClassElement>();
|
| + Set<ClassEntity> getClassesUsedInSubstitutions(TypeChecks checks) {
|
| + Set<ClassEntity> instantiated = new Set<ClassEntity>();
|
| ArgumentCollector collector = new ArgumentCollector();
|
| - for (ClassElement target in checks.classes) {
|
| + for (ClassEntity target in checks.classes) {
|
| instantiated.add(target);
|
| for (TypeCheck check in checks[target]) {
|
| Substitution substitution = check.substitution;
|
| @@ -702,7 +711,7 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
|
|
| // TODO(karlklose): maybe precompute this value and store it in typeChecks?
|
| @override
|
| - bool isTrivialSubstitution(ClassElement cls, ClassElement check) {
|
| + bool isTrivialSubstitution(ClassEntity cls, ClassEntity check) {
|
| if (cls.isClosure) {
|
| // TODO(karlklose): handle closures.
|
| return true;
|
| @@ -710,12 +719,12 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
|
|
| // If there are no type variables or the type is the same, we do not need
|
| // a substitution.
|
| - if (check.typeVariables.isEmpty || cls == check) {
|
| + if (!_elementEnvironment.isGenericClass(check) || cls == check) {
|
| return true;
|
| }
|
|
|
| - ResolutionInterfaceType originalType = cls.thisType;
|
| - ResolutionInterfaceType type = originalType.asInstanceOf(check);
|
| + InterfaceType originalType = _elementEnvironment.getThisType(cls);
|
| + InterfaceType type = _types.asInstanceOf(originalType, check);
|
| // [type] is not a subtype of [check]. we do not generate a check and do not
|
| // need a substitution.
|
| if (type == null) return true;
|
| @@ -723,13 +732,13 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| // Run through both lists of type variables and check if the type variables
|
| // are identical at each position. If they are not, we need to calculate a
|
| // substitution function.
|
| - List<ResolutionDartType> variables = cls.typeVariables;
|
| - List<ResolutionDartType> arguments = type.typeArguments;
|
| + List<DartType> variables = originalType.typeArguments;
|
| + List<DartType> arguments = type.typeArguments;
|
| if (variables.length != arguments.length) {
|
| return false;
|
| }
|
| for (int index = 0; index < variables.length; index++) {
|
| - if (variables[index].element != arguments[index].element) {
|
| + if (variables[index] != arguments[index]) {
|
| return false;
|
| }
|
| }
|
| @@ -737,7 +746,7 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| }
|
|
|
| @override
|
| - Substitution getSubstitution(ClassElement cls, ClassElement other) {
|
| + Substitution getSubstitution(ClassEntity cls, ClassEntity other) {
|
| // Look for a precomputed check.
|
| for (TypeCheck check in cachedRequiredChecks[cls]) {
|
| if (check.cls == other) {
|
| @@ -749,16 +758,16 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| return computeSubstitution(cls, other);
|
| }
|
|
|
| - Substitution computeSubstitution(ClassElement cls, ClassElement check,
|
| + Substitution computeSubstitution(ClassEntity cls, ClassEntity check,
|
| {bool alwaysGenerateFunction: false}) {
|
| if (isTrivialSubstitution(cls, check)) return null;
|
|
|
| // Unnamed mixin application classes do not need substitutions, because they
|
| // are never instantiated and their checks are overwritten by the class that
|
| // they are mixed into.
|
| - ResolutionInterfaceType type = cls.thisType;
|
| - ResolutionInterfaceType target = type.asInstanceOf(check);
|
| - List<ResolutionDartType> typeVariables = cls.typeVariables;
|
| + InterfaceType type = _elementEnvironment.getThisType(cls);
|
| + InterfaceType target = _types.asInstanceOf(type, check);
|
| + List<DartType> typeVariables = type.typeArguments;
|
| if (typeVariables.isEmpty && !alwaysGenerateFunction) {
|
| return new Substitution.list(target.typeArguments);
|
| } else {
|
| @@ -767,20 +776,22 @@ class _RuntimeTypes extends _RuntimeTypesBase
|
| }
|
| }
|
|
|
| -class _RuntimeTypesEncoder implements RuntimeTypesEncoder {
|
| +class RuntimeTypesEncoderImpl implements RuntimeTypesEncoder {
|
| final Namer namer;
|
| + final ElementEnvironment _elementEnvironment;
|
| final CommonElements commonElements;
|
| final TypeRepresentationGenerator _representationGenerator;
|
|
|
| - _RuntimeTypesEncoder(this.namer, this.commonElements)
|
| + RuntimeTypesEncoderImpl(
|
| + this.namer, this._elementEnvironment, this.commonElements)
|
| : _representationGenerator = new TypeRepresentationGenerator(namer);
|
|
|
| @override
|
| - bool isSimpleFunctionType(ResolutionFunctionType type) {
|
| + bool isSimpleFunctionType(FunctionType type) {
|
| if (!type.returnType.isDynamic) return false;
|
| if (!type.optionalParameterTypes.isEmpty) return false;
|
| if (!type.namedParameterTypes.isEmpty) return false;
|
| - for (ResolutionDartType parameter in type.parameterTypes) {
|
| + for (DartType parameter in type.parameterTypes) {
|
| if (!parameter.isDynamic) return false;
|
| }
|
| return true;
|
| @@ -802,29 +813,29 @@ class _RuntimeTypesEncoder implements RuntimeTypesEncoder {
|
|
|
| @override
|
| jsAst.Expression getTypeRepresentation(
|
| - Emitter emitter, ResolutionDartType type, OnVariableCallback onVariable,
|
| + Emitter emitter, DartType type, OnVariableCallback onVariable,
|
| [ShouldEncodeTypedefCallback shouldEncodeTypedef]) {
|
| // GENERIC_METHODS: When generic method support is complete enough to
|
| // include a runtime value for method type variables this must be updated.
|
| - return _representationGenerator.getTypeRepresentation(emitter,
|
| - type.dynamifyMethodTypeVariableType, onVariable, shouldEncodeTypedef);
|
| + return _representationGenerator.getTypeRepresentation(
|
| + emitter, type, onVariable, shouldEncodeTypedef);
|
| }
|
|
|
| @override
|
| - jsAst.Expression getSubstitutionRepresentation(Emitter emitter,
|
| - List<ResolutionDartType> types, OnVariableCallback onVariable) {
|
| + jsAst.Expression getSubstitutionRepresentation(
|
| + Emitter emitter, List<DartType> types, OnVariableCallback onVariable) {
|
| List<jsAst.Expression> elements = types
|
| - .map((ResolutionDartType type) =>
|
| - getTypeRepresentation(emitter, type, onVariable))
|
| + .map(
|
| + (DartType type) => getTypeRepresentation(emitter, type, onVariable))
|
| .toList(growable: false);
|
| return new jsAst.ArrayInitializer(elements);
|
| }
|
|
|
| - jsAst.Expression getTypeEncoding(Emitter emitter, ResolutionDartType type,
|
| + jsAst.Expression getTypeEncoding(Emitter emitter, DartType type,
|
| {bool alwaysGenerateFunction: false}) {
|
| - ClassElement contextClass = Types.getClassContext(type);
|
| - jsAst.Expression onVariable(ResolutionTypeVariableType v) {
|
| - return new jsAst.VariableUse(v.name);
|
| + ClassEntity contextClass = Types.getClassContext(type);
|
| + jsAst.Expression onVariable(TypeVariableType v) {
|
| + return new jsAst.VariableUse(v.element.name);
|
| }
|
|
|
| jsAst.Expression encoding =
|
| @@ -834,8 +845,11 @@ class _RuntimeTypesEncoder implements RuntimeTypesEncoder {
|
| } else {
|
| List<String> parameters = const <String>[];
|
| if (contextClass != null) {
|
| - parameters = contextClass.typeVariables.map((type) {
|
| - return type.name;
|
| + parameters = _elementEnvironment
|
| + .getThisType(contextClass)
|
| + .typeArguments
|
| + .map((TypeVariableType type) {
|
| + return type.element.name;
|
| }).toList();
|
| }
|
| return js('function(#) { return # }', [parameters, encoding]);
|
| @@ -844,8 +858,8 @@ class _RuntimeTypesEncoder implements RuntimeTypesEncoder {
|
|
|
| @override
|
| jsAst.Expression getSignatureEncoding(
|
| - Emitter emitter, ResolutionDartType type, jsAst.Expression this_) {
|
| - ClassElement contextClass = Types.getClassContext(type);
|
| + Emitter emitter, DartType type, jsAst.Expression this_) {
|
| + ClassEntity contextClass = Types.getClassContext(type);
|
| jsAst.Expression encoding =
|
| getTypeEncoding(emitter, type, alwaysGenerateFunction: true);
|
| if (contextClass != null) {
|
| @@ -878,23 +892,25 @@ class _RuntimeTypesEncoder implements RuntimeTypesEncoder {
|
| @override
|
| jsAst.Expression getSubstitutionCode(
|
| Emitter emitter, Substitution substitution) {
|
| - jsAst.Expression declaration(ResolutionTypeVariableType variable) {
|
| - return new jsAst.Parameter(getVariableName(variable.name));
|
| + jsAst.Expression declaration(TypeVariableType variable) {
|
| + return new jsAst.Parameter(getVariableName(variable.element.name));
|
| }
|
|
|
| - jsAst.Expression use(ResolutionTypeVariableType variable) {
|
| - return new jsAst.VariableUse(getVariableName(variable.name));
|
| + jsAst.Expression use(TypeVariableType variable) {
|
| + return new jsAst.VariableUse(getVariableName(variable.element.name));
|
| }
|
|
|
| - if (substitution.arguments
|
| - .every((ResolutionDartType type) => type.isDynamic)) {
|
| + if (substitution.arguments.every((DartType type) => type.isDynamic)) {
|
| return emitter.generateFunctionThatReturnsNull();
|
| } else {
|
| jsAst.Expression value =
|
| getSubstitutionRepresentation(emitter, substitution.arguments, use);
|
| if (substitution.isFunction) {
|
| Iterable<jsAst.Expression> formals =
|
| - substitution.parameters.map(declaration);
|
| + // TODO(johnniwinther): Pass [declaration] directly to `map` when
|
| + // `substitution.parameters` can no longer be a
|
| + // `List<ResolutionDartType>`.
|
| + substitution.parameters.map((type) => declaration(type));
|
| return js('function(#) { return # }', [formals, value]);
|
| } else {
|
| return js('function() { return # }', value);
|
| @@ -911,19 +927,24 @@ class _RuntimeTypesEncoder implements RuntimeTypesEncoder {
|
| namer.internalGlobal('functionThatReturnsNull');
|
|
|
| @override
|
| - String getTypeRepresentationForTypeConstant(ResolutionDartType type) {
|
| + String getTypeRepresentationForTypeConstant(DartType type) {
|
| if (type.isDynamic) return "dynamic";
|
| - String name = namer.uniqueNameForTypeConstantElement(type.element);
|
| - if (!type.element.isClass) return name;
|
| - ResolutionInterfaceType interface = type;
|
| - List<ResolutionDartType> variables = interface.element.typeVariables;
|
| + if (type is ResolutionTypedefType) {
|
| + return namer.uniqueNameForTypeConstantElement(
|
| + type.element.library, type.element);
|
| + }
|
| + InterfaceType interface = type;
|
| + String name = namer.uniqueNameForTypeConstantElement(
|
| + interface.element.library, interface.element);
|
| +
|
| // Type constants can currently only be raw types, so there is no point
|
| // adding ground-term type parameters, as they would just be 'dynamic'.
|
| // TODO(sra): Since the result string is used only in constructing constant
|
| // names, it would result in more readable names if the final string was a
|
| // legal JavaScript identifer.
|
| - if (variables.isEmpty) return name;
|
| - String arguments = new List.filled(variables.length, 'dynamic').join(', ');
|
| + if (interface.typeArguments.isEmpty) return name;
|
| + String arguments =
|
| + new List.filled(interface.typeArguments.length, 'dynamic').join(', ');
|
| return '$name<$arguments>';
|
| }
|
| }
|
| @@ -932,7 +953,7 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor {
|
| final Namer namer;
|
| OnVariableCallback onVariable;
|
| ShouldEncodeTypedefCallback shouldEncodeTypedef;
|
| - Map<ResolutionTypeVariableType, jsAst.Expression> typedefBindings;
|
| + Map<TypeVariableType, jsAst.Expression> typedefBindings;
|
|
|
| TypeRepresentationGenerator(this.namer);
|
|
|
| @@ -942,7 +963,7 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor {
|
| */
|
| jsAst.Expression getTypeRepresentation(
|
| Emitter emitter,
|
| - ResolutionDartType type,
|
| + DartType type,
|
| OnVariableCallback onVariable,
|
| ShouldEncodeTypedefCallback encodeTypedef) {
|
| assert(typedefBindings == null);
|
| @@ -956,14 +977,22 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor {
|
| return representation;
|
| }
|
|
|
| - jsAst.Expression getJavaScriptClassName(Element element, Emitter emitter) {
|
| + jsAst.Expression getJavaScriptClassName(Entity element, Emitter emitter) {
|
| return emitter.typeAccess(element);
|
| }
|
|
|
| - @override
|
| - visit(ResolutionDartType type, Emitter emitter) => type.accept(this, emitter);
|
| + jsAst.Expression getDynamicValue() => js('null');
|
|
|
| - visitTypeVariableType(ResolutionTypeVariableType type, Emitter emitter) {
|
| + @override
|
| + visit(DartType type, Emitter emitter) => type.accept(this, emitter);
|
| +
|
| + visitTypeVariableType(TypeVariableType type, Emitter emitter) {
|
| + if (type.element.typeDeclaration is! ClassEntity) {
|
| + /// A [TypeVariableType] from a generic method is replaced by a
|
| + /// [DynamicType].
|
| + /// GENERIC_METHODS: Temporary, only used with '--generic-method-syntax'.
|
| + return getDynamicValue();
|
| + }
|
| if (typedefBindings != null) {
|
| assert(typedefBindings[type] != null);
|
| return typedefBindings[type];
|
| @@ -971,24 +1000,24 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor {
|
| return onVariable(type);
|
| }
|
|
|
| - visitDynamicType(ResolutionDynamicType type, Emitter emitter) {
|
| - return js('null');
|
| + visitDynamicType(DynamicType type, Emitter emitter) {
|
| + return getDynamicValue();
|
| }
|
|
|
| - visitInterfaceType(ResolutionInterfaceType type, Emitter emitter) {
|
| + visitInterfaceType(InterfaceType type, Emitter emitter) {
|
| jsAst.Expression name = getJavaScriptClassName(type.element, emitter);
|
| return type.treatAsRaw
|
| ? name
|
| : visitList(type.typeArguments, emitter, head: name);
|
| }
|
|
|
| - jsAst.Expression visitList(List<ResolutionDartType> types, Emitter emitter,
|
| + jsAst.Expression visitList(List<DartType> types, Emitter emitter,
|
| {jsAst.Expression head}) {
|
| List<jsAst.Expression> elements = <jsAst.Expression>[];
|
| if (head != null) {
|
| elements.add(head);
|
| }
|
| - for (ResolutionDartType type in types) {
|
| + for (DartType type in types) {
|
| jsAst.Expression element = visit(type, emitter);
|
| if (element is jsAst.LiteralNull) {
|
| elements.add(new jsAst.ArrayHole());
|
| @@ -1014,7 +1043,7 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor {
|
| .expressionTemplateFor('{ ${namer.functionTypeTag}: "dynafunc" }');
|
| }
|
|
|
| - visitFunctionType(ResolutionFunctionType type, Emitter emitter) {
|
| + visitFunctionType(FunctionType type, Emitter emitter) {
|
| List<jsAst.Property> properties = <jsAst.Property>[];
|
|
|
| void addProperty(String name, jsAst.Expression value) {
|
| @@ -1041,7 +1070,7 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor {
|
| if (!type.namedParameterTypes.isEmpty) {
|
| List<jsAst.Property> namedArguments = <jsAst.Property>[];
|
| List<String> names = type.namedParameters;
|
| - List<ResolutionDartType> types = type.namedParameterTypes;
|
| + List<DartType> types = type.namedParameterTypes;
|
| assert(types.length == names.length);
|
| for (int index = 0; index < types.length; index++) {
|
| jsAst.Expression name = js.string(names[index]);
|
| @@ -1059,14 +1088,14 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor {
|
| return js('null');
|
| }
|
|
|
| - visitVoidType(ResolutionVoidType type, Emitter emitter) {
|
| + visitVoidType(VoidType type, Emitter emitter) {
|
| // TODO(ahe): Reify void type ("null" means "dynamic").
|
| return js('null');
|
| }
|
|
|
| visitTypedefType(ResolutionTypedefType type, Emitter emitter) {
|
| bool shouldEncode = shouldEncodeTypedef(type);
|
| - ResolutionDartType unaliasedType = type.unaliased;
|
| + DartType unaliasedType = type.unaliased;
|
|
|
| var oldBindings = typedefBindings;
|
| if (typedefBindings == null) {
|
| @@ -1090,8 +1119,8 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor {
|
| // HTypeInfoExpression). This would share all the Set<T> subexpressions
|
| // instead of duplicating them. This would require HTypeInfoExpression
|
| // inputs to correspond to type variables AND typedefs.
|
| - typedefBindings = <ResolutionTypeVariableType, jsAst.Expression>{};
|
| - type.forEachTypeVariable((variable) {
|
| + typedefBindings = <TypeVariableType, jsAst.Expression>{};
|
| + type.forEachTypeVariable((TypeVariableType variable) {
|
| if (variable is! MethodTypeVariableType) {
|
| typedefBindings[variable] = onVariable(variable);
|
| }
|
| @@ -1122,25 +1151,25 @@ class TypeRepresentationGenerator implements ResolutionDartTypeVisitor {
|
| }
|
|
|
| class TypeCheckMapping implements TypeChecks {
|
| - final Map<ClassElement, Set<TypeCheck>> map =
|
| - new Map<ClassElement, Set<TypeCheck>>();
|
| + final Map<ClassEntity, Set<TypeCheck>> map =
|
| + new Map<ClassEntity, Set<TypeCheck>>();
|
|
|
| - Iterable<TypeCheck> operator [](ClassElement element) {
|
| + Iterable<TypeCheck> operator [](ClassEntity element) {
|
| Set<TypeCheck> result = map[element];
|
| return result != null ? result : const <TypeCheck>[];
|
| }
|
|
|
| - void add(ClassElement cls, ClassElement check, Substitution substitution) {
|
| + void add(ClassEntity cls, ClassEntity check, Substitution substitution) {
|
| map.putIfAbsent(cls, () => new Set<TypeCheck>());
|
| map[cls].add(new TypeCheck(check, substitution));
|
| }
|
|
|
| - Iterable<ClassElement> get classes => map.keys;
|
| + Iterable<ClassEntity> get classes => map.keys;
|
|
|
| String toString() {
|
| StringBuffer sb = new StringBuffer();
|
| - for (ClassElement holder in classes) {
|
| - for (ClassElement check in [holder]) {
|
| + for (ClassEntity holder in classes) {
|
| + for (ClassEntity check in [holder]) {
|
| sb.write('${holder.name}.' '${check.name}, ');
|
| }
|
| }
|
| @@ -1149,64 +1178,68 @@ class TypeCheckMapping implements TypeChecks {
|
| }
|
|
|
| class ArgumentCollector extends ResolutionDartTypeVisitor {
|
| - final Set<ClassElement> classes = new Set<ClassElement>();
|
| + final Set<ClassEntity> classes = new Set<ClassEntity>();
|
|
|
| - collect(ResolutionDartType type, {bool isTypeArgument: false}) {
|
| + collect(DartType type, {bool isTypeArgument: false}) {
|
| visit(type, isTypeArgument);
|
| }
|
|
|
| /// Collect all types in the list as if they were arguments of an
|
| /// InterfaceType.
|
| - collectAll(List<ResolutionDartType> types) {
|
| - for (ResolutionDartType type in types) {
|
| + collectAll(List<DartType> types, {bool isTypeArgument: false}) {
|
| + for (DartType type in types) {
|
| visit(type, true);
|
| }
|
| }
|
|
|
| visitTypedefType(ResolutionTypedefType type, bool isTypeArgument) {
|
| - type.unaliased.accept(this, isTypeArgument);
|
| + collect(type.unaliased, isTypeArgument: isTypeArgument);
|
| }
|
|
|
| - visitInterfaceType(ResolutionInterfaceType type, bool isTypeArgument) {
|
| + visitInterfaceType(InterfaceType type, bool isTypeArgument) {
|
| if (isTypeArgument) classes.add(type.element);
|
| - type.visitChildren(this, true);
|
| + collectAll(type.typeArguments, isTypeArgument: true);
|
| }
|
|
|
| - visitFunctionType(ResolutionFunctionType type, _) {
|
| - type.visitChildren(this, true);
|
| + visitFunctionType(FunctionType type, _) {
|
| + collect(type.returnType, isTypeArgument: true);
|
| + collectAll(type.parameterTypes, isTypeArgument: true);
|
| + collectAll(type.optionalParameterTypes, isTypeArgument: true);
|
| + collectAll(type.namedParameterTypes, isTypeArgument: true);
|
| }
|
| }
|
|
|
| class FunctionArgumentCollector extends ResolutionDartTypeVisitor {
|
| - final Set<ClassElement> classes = new Set<ClassElement>();
|
| + final Set<ClassEntity> classes = new Set<ClassEntity>();
|
|
|
| FunctionArgumentCollector();
|
|
|
| - collect(ResolutionDartType type) {
|
| - visit(type, false);
|
| + collect(DartType type, {bool inFunctionType: false}) {
|
| + visit(type, inFunctionType);
|
| }
|
|
|
| - /// Collect all types in the list as if they were arguments of an
|
| - /// InterfaceType.
|
| - collectAll(Link<ResolutionDartType> types) {
|
| - for (ResolutionDartType type in types) {
|
| - visit(type, true);
|
| + collectAll(List<DartType> types, {bool inFunctionType: false}) {
|
| + for (DartType type in types) {
|
| + visit(type, inFunctionType);
|
| }
|
| }
|
|
|
| visitTypedefType(ResolutionTypedefType type, bool inFunctionType) {
|
| - type.unaliased.accept(this, inFunctionType);
|
| + collect(type.unaliased, inFunctionType: inFunctionType);
|
| }
|
|
|
| - visitInterfaceType(ResolutionInterfaceType type, bool inFunctionType) {
|
| + visitInterfaceType(InterfaceType type, bool inFunctionType) {
|
| if (inFunctionType) {
|
| classes.add(type.element);
|
| }
|
| - type.visitChildren(this, inFunctionType);
|
| + collectAll(type.typeArguments, inFunctionType: inFunctionType);
|
| }
|
|
|
| - visitFunctionType(ResolutionFunctionType type, _) {
|
| - type.visitChildren(this, true);
|
| + visitFunctionType(FunctionType type, _) {
|
| + collect(type.returnType, inFunctionType: true);
|
| + collectAll(type.parameterTypes, inFunctionType: true);
|
| + collectAll(type.optionalParameterTypes, inFunctionType: true);
|
| + collectAll(type.namedParameterTypes, inFunctionType: true);
|
| }
|
| }
|
|
|
| @@ -1222,12 +1255,12 @@ class FunctionArgumentCollector extends ResolutionDartTypeVisitor {
|
| //TODO(floitsch): Remove support for non-function substitutions.
|
| class Substitution {
|
| final bool isFunction;
|
| - final List<ResolutionDartType> arguments;
|
| - final List<ResolutionDartType> parameters;
|
| + final List<DartType> arguments;
|
| + final List<DartType> parameters;
|
|
|
| Substitution.list(this.arguments)
|
| : isFunction = false,
|
| - parameters = const <ResolutionDartType>[];
|
| + parameters = const <DartType>[];
|
|
|
| Substitution.function(this.arguments, this.parameters) : isFunction = true;
|
| }
|
| @@ -1237,7 +1270,7 @@ class Substitution {
|
| * substition for this check.
|
| */
|
| class TypeCheck {
|
| - final ClassElement cls;
|
| + final ClassEntity cls;
|
| final Substitution substitution;
|
| final int hashCode = _nextHash = (_nextHash + 100003).toUnsigned(30);
|
| static int _nextHash = 0;
|
|
|