Index: pkg/compiler/lib/src/resolution/type_resolver.dart |
diff --git a/pkg/compiler/lib/src/resolution/type_resolver.dart b/pkg/compiler/lib/src/resolution/type_resolver.dart |
index 318e7488f429e86e8c8693d209a82407658f3935..34e5cab4dc2d1a45624868171b19b9f6f5bf6edb 100644 |
--- a/pkg/compiler/lib/src/resolution/type_resolver.dart |
+++ b/pkg/compiler/lib/src/resolution/type_resolver.dart |
@@ -27,6 +27,16 @@ import 'registry.dart' show ResolutionRegistry; |
import 'resolution_common.dart' show MappingVisitor; |
import 'scope.dart' show Scope; |
+class _FormalsTypeResolutionResult { |
+ final List<ResolutionDartType> requiredTypes; |
+ final List<ResolutionDartType> orderedTypes; |
+ final List<String> names; |
+ final List<ResolutionDartType> nameTypes; |
+ |
+ _FormalsTypeResolutionResult( |
+ this.requiredTypes, this.orderedTypes, this.names, this.nameTypes); |
+} |
+ |
class TypeResolver { |
final Resolution resolution; |
@@ -66,6 +76,154 @@ class TypeResolver { |
ResolutionDartType resolveTypeAnnotation( |
MappingVisitor visitor, TypeAnnotation node, |
{bool malformedIsError: false, bool deferredIsMalformed: true}) { |
+ return _resolveTypeAnnotation( |
+ visitor, node, const [], malformedIsError: malformedIsError, |
+ deferredIsMalformed: deferredIsMalformed); |
+ } |
+ |
+ // TODO(floitsch): the [visibleTypeParameterNames] is a hack to put |
+ // type parameters in scope for the nested types. |
+ // |
+ // For example, in the following example, the generic type "A" would be stored |
+ // in `visibleTypeParameterNames`. |
+ // `typedef F = Function(List<A> Function<A>(A x))`. |
+ // |
+ // They are resolved to `dynamic` until dart2js supports generic methods. |
+ ResolutionDartType _resolveTypeAnnotation( |
+ MappingVisitor visitor, TypeAnnotation node, |
+ List<List<String>> visibleTypeParameterNames, |
+ {bool malformedIsError: false, bool deferredIsMalformed: true}) { |
+ |
+ if (node.asNominalTypeAnnotation() != null) { |
+ return resolveNominalTypeAnnotation( |
+ visitor, node, |
+ visibleTypeParameterNames, |
+ malformedIsError: malformedIsError, |
+ deferredIsMalformed: deferredIsMalformed); |
+ } |
+ assert(node.asFunctionTypeAnnotation() != null); |
+ return _resolveFunctionTypeAnnotation( |
+ visitor, node, visibleTypeParameterNames, |
+ malformedIsError: malformedIsError, |
+ deferredIsMalformed: deferredIsMalformed); |
+ } |
+ |
+ /// Resolves the types of a parameter list. |
+ /// |
+ /// This function does not accept "inline" function types. For example |
+ /// `foo(int bar(String x))` is not accepted. |
+ /// |
+ /// However, it does work with nested generalized function types: |
+ /// `foo(int Function(String) x)`. |
+ _FormalsTypeResolutionResult _resolveFormalTypes( |
+ MappingVisitor visitor, NodeList formals, |
+ List<List<String>> visibleTypeParameterNames) { |
+ |
+ ResolutionDartType resolvePositionalType(VariableDefinitions node) { |
+ return _resolveTypeAnnotation( |
+ visitor, node.type, visibleTypeParameterNames); |
+ } |
+ |
+ void fillNamedTypes(NodeList namedFormals, |
+ List<String> names, List<ResolutionDartType> types) { |
+ List<Node> nodes = namedFormals.nodes.toList(growable: false); |
+ |
+ // Sort the named arguments first. |
+ nodes.sort((node1, node2) { |
+ VariableDefinitions a = node1; |
+ VariableDefinitions b = node2; |
+ assert(a.definitions.nodes.tail.isEmpty); |
+ assert(b.definitions.nodes.tail.isEmpty); |
+ return a.definitions.nodes.head.asIdentifier().source.compareTo( |
+ b.definitions.nodes.head.asIdentifier().source); |
+ }); |
+ |
+ for (VariableDefinitions node in nodes) { |
+ String name = node.definitions.nodes.head.asIdentifier().source; |
+ ResolutionDartType type = node.type == null |
+ ? const ResolutionDynamicType() |
+ : _resolveTypeAnnotation( |
+ visitor, node.type, visibleTypeParameterNames); |
+ names.add(name); |
+ types.add(type); |
+ } |
+ } |
+ |
+ List<ResolutionDartType> requiredTypes = <ResolutionDartType>[]; |
+ NodeList optionalFormals = null; |
+ for (Link<Node> link = formals.nodes; !link.isEmpty; link = link.tail) { |
+ if (link.tail.isEmpty && link.head is NodeList) { |
+ optionalFormals = link.head; |
+ break; |
+ } |
+ requiredTypes.add(resolvePositionalType(link.head)); |
+ } |
+ |
+ |
+ List<ResolutionDartType> orderedTypes = const <ResolutionDartType>[]; |
+ List<String> names = const <String>[]; |
+ List<ResolutionDartType> namedTypes = const <ResolutionDartType>[]; |
+ |
+ if (optionalFormals != null) { |
+ // This must be a list of optional arguments. |
+ String value = optionalFormals.beginToken.stringValue; |
+ if ((!identical(value, '[')) && (!identical(value, '{'))) { |
+ reporter.internalError(optionalFormals, "expected optional parameters"); |
+ } |
+ bool optionalParametersAreNamed = (identical(value, '{')); |
+ |
+ if (optionalParametersAreNamed) { |
+ names = <String>[]; |
+ namedTypes = <ResolutionDartType>[]; |
+ fillNamedTypes(optionalFormals, names, namedTypes); |
+ } else { |
+ orderedTypes = <ResolutionDartType>[]; |
+ for (Link<Node> link = optionalFormals.nodes; |
+ !link.isEmpty; |
+ link = link.tail) { |
+ orderedTypes.add(resolvePositionalType(link.head)); |
+ } |
+ } |
+ } |
+ return new _FormalsTypeResolutionResult( |
+ requiredTypes, orderedTypes, names, namedTypes); |
+ } |
+ |
+ ResolutionFunctionType _resolveFunctionTypeAnnotation(MappingVisitor visitor, |
+ FunctionTypeAnnotation node, |
+ List<List<String>> visibleTypeParameterNames, |
+ {bool malformedIsError: false, bool deferredIsMalformed: true}) { |
+ |
+ assert(visibleTypeParameterNames != null); |
+ |
+ if (node.typeParameters != null) { |
+ List<String> newTypeNames = node.typeParameters.map((TypeVariable node) { |
+ return node.name.asIdentifier().source; |
+ }).toList(); |
+ visibleTypeParameterNames = |
+ visibleTypeParameterNames.toList()..add(newTypeNames); |
+ } |
+ |
+ ResolutionDartType returnType = node.returnType == null |
+ ? const ResolutionDynamicType() |
+ : _resolveTypeAnnotation(visitor, node.returnType, |
+ visibleTypeParameterNames); |
+ var formalTypes = |
+ _resolveFormalTypes(visitor, node.formals, visibleTypeParameterNames); |
+ var result = new ResolutionFunctionType.generalized( |
+ returnType, |
+ formalTypes.requiredTypes, |
+ formalTypes.orderedTypes, |
+ formalTypes.names, |
+ formalTypes.nameTypes); |
+ visitor.registry.useType(node, result); |
+ return result; |
+ } |
+ |
+ ResolutionDartType resolveNominalTypeAnnotation(MappingVisitor visitor, |
+ NominalTypeAnnotation node, |
+ List<List<String>> visibleTypeParameterNames, |
+ {bool malformedIsError: false, bool deferredIsMalformed: true}) { |
ResolutionRegistry registry = visitor.registry; |
Identifier typeName; |
@@ -74,7 +232,8 @@ class TypeResolver { |
ResolutionDartType checkNoTypeArguments(ResolutionDartType type) { |
List<ResolutionDartType> arguments = new List<ResolutionDartType>(); |
bool hasTypeArgumentMismatch = resolveTypeArguments( |
- visitor, node, const <ResolutionDartType>[], arguments); |
+ visitor, node, const <ResolutionDartType>[], arguments, |
+ visibleTypeParameterNames); |
if (hasTypeArgumentMismatch) { |
return new MalformedType( |
new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, |
@@ -106,9 +265,6 @@ class TypeResolver { |
} |
} |
- Element element = resolveTypeName(prefixName, typeName, visitor.scope, |
- deferredIsMalformed: deferredIsMalformed); |
- |
ResolutionDartType reportFailureAndCreateType( |
MessageKind messageKind, Map messageArguments, |
{ResolutionDartType userProvidedBadType, |
@@ -128,14 +284,33 @@ class TypeResolver { |
typeName.source, visitor.enclosingElement); |
} |
List<ResolutionDartType> arguments = <ResolutionDartType>[]; |
- resolveTypeArguments( |
- visitor, node, const <ResolutionDartType>[], arguments); |
+ resolveTypeArguments(visitor, node, const <ResolutionDartType>[], |
+ arguments, visibleTypeParameterNames); |
return new MalformedType( |
erroneousElement, userProvidedBadType, arguments); |
} |
+ Element element; |
+ // Resolve references to type names as dynamic. |
+ // TODO(floitsch): this hackishly resolves generic function type arguments |
+ // to dynamic. |
+ if (prefixName == null && |
+ visibleTypeParameterNames.any((n) => n.contains(typeName.source))) { |
+ type = const ResolutionDynamicType(); |
+ } else { |
+ element = resolveTypeName(prefixName, typeName, visitor.scope, |
+ deferredIsMalformed: deferredIsMalformed); |
+ } |
+ |
// Try to construct the type from the element. |
- if (element == null) { |
+ if (type != null) { |
+ // Already assigned to through the visibleTypeParameterNames. |
+ // Just make sure that it doesn't have type arguments. |
+ if (node.typeArguments != null) { |
+ reporter.reportWarningMessage(node.typeArguments.nodes.head, |
+ MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
+ } |
+ } else if (element == null) { |
type = reportFailureAndCreateType( |
MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName}); |
} else if (element.isAmbiguous) { |
@@ -170,8 +345,9 @@ class TypeResolver { |
resolver.ensureClassWillBeResolvedInternal(cls); |
cls.computeType(resolution); |
List<ResolutionDartType> arguments = <ResolutionDartType>[]; |
- bool hasTypeArgumentMismatch = |
- resolveTypeArguments(visitor, node, cls.typeVariables, arguments); |
+ bool hasTypeArgumentMismatch = resolveTypeArguments( |
+ visitor, node, cls.typeVariables, arguments, |
+ visibleTypeParameterNames); |
if (hasTypeArgumentMismatch) { |
type = new BadInterfaceType( |
cls.declaration, |
@@ -194,7 +370,8 @@ class TypeResolver { |
typdef.computeType(resolution); |
List<ResolutionDartType> arguments = <ResolutionDartType>[]; |
bool hasTypeArgumentMismatch = resolveTypeArguments( |
- visitor, node, typdef.typeVariables, arguments); |
+ visitor, node, typdef.typeVariables, arguments, |
+ visibleTypeParameterNames); |
if (hasTypeArgumentMismatch) { |
type = new BadTypedefType( |
typdef, |
@@ -241,7 +418,7 @@ class TypeResolver { |
} |
/// Checks the type arguments of [type] against the type variable bounds. |
- void checkTypeVariableBounds(TypeAnnotation node, GenericType type) { |
+ void checkTypeVariableBounds(NominalTypeAnnotation node, GenericType type) { |
void checkTypeVariableBound(_, ResolutionDartType typeArgument, |
ResolutionTypeVariableType typeVariable, ResolutionDartType bound) { |
if (!types.isSubtype(typeArgument, bound)) { |
@@ -266,9 +443,10 @@ class TypeResolver { |
*/ |
bool resolveTypeArguments( |
MappingVisitor visitor, |
- TypeAnnotation node, |
+ NominalTypeAnnotation node, |
List<ResolutionDartType> typeVariables, |
- List<ResolutionDartType> arguments) { |
+ List<ResolutionDartType> arguments, |
+ List<List<String>> visibleTypeParameterNames) { |
if (node.typeArguments == null) { |
return false; |
} |
@@ -283,8 +461,8 @@ class TypeResolver { |
typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
typeArgumentCountMismatch = true; |
} |
- ResolutionDartType argType = |
- resolveTypeAnnotation(visitor, typeArguments.head); |
+ ResolutionDartType argType = _resolveTypeAnnotation( |
+ visitor, typeArguments.head, visibleTypeParameterNames); |
// TODO(karlklose): rewrite to not modify [arguments]. |
arguments.add(argType); |
} |