Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(902)

Unified Diff: pkg/compiler/lib/src/resolution/type_resolver.dart

Issue 2567133002: Add support for the new function-type syntax. (Closed)
Patch Set: Update status files and update test-generator for checked mode. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 3acc024e5fe5b0445a112cae6d98c6e5d5bb4c13..002afe0ad1c7eb54ff05cf8c823dd597e35bc4ef 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<DartType> requiredTypes;
+ final List<DartType> orderedTypes;
+ final List<String> names;
+ final List<DartType> nameTypes;
+
+ _FormalsTypeResolutionResult(
+ this.requiredTypes, this.orderedTypes, this.names, this.nameTypes);
+}
+
class TypeResolver {
final Resolution resolution;
@@ -65,6 +75,153 @@ class TypeResolver {
DartType 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.
+ DartType _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) {
+
+ DartType resolvePositionalType(VariableDefinitions node) {
+ return _resolveTypeAnnotation(
+ visitor, node.type, visibleTypeParameterNames);
+ }
+
+ void fillNamedTypes(
+ NodeList namedFormals, List<String> names, List<DartType> 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;
+ DartType type = node.type == null
+ ? const DynamicType()
+ : _resolveTypeAnnotation(
+ visitor, node.type, visibleTypeParameterNames);
+ names.add(name);
+ types.add(type);
+ }
+ }
+
+ List<DartType> requiredTypes = <DartType>[];
+ 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<DartType> orderedTypes = const <DartType>[];
+ List<String> names = const <String>[];
+ List<DartType> nameTypes = const <DartType>[];
+
+ 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>[];
+ nameTypes = <DartType>[];
+ fillNamedTypes(optionalFormals, names, nameTypes);
+ } else {
+ orderedTypes = <DartType>[];
+ for (Link<Node> link = optionalFormals.nodes;
+ !link.isEmpty;
+ link = link.tail) {
+ orderedTypes.add(resolvePositionalType(link.head));
+ }
+ }
+ }
+ return new _FormalsTypeResolutionResult(
+ requiredTypes, orderedTypes, names, nameTypes);
+ }
+
+ FunctionType _resolveFunctionTypeAnnotation(MappingVisitor visitor,
+ FunctionTypeAnnotation node,
+ List<List<String>> visibleTypeParameterNames,
+ {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);
+ }
+
+ DartType returnType = node.returnType == null
+ ? const DynamicType()
+ : _resolveTypeAnnotation(visitor, node.returnType,
+ visibleTypeParameterNames);
+ var formalTypes =
+ _resolveFormalTypes(visitor, node.formals, visibleTypeParameterNames);
+ var result = new FunctionType.generalized(
+ returnType,
+ formalTypes.requiredTypes,
+ formalTypes.orderedTypes,
+ formalTypes.names,
+ formalTypes.nameTypes);
+ visitor.registry.useType(node, result);
+ return result;
+ }
+
+ DartType resolveNominalTypeAnnotation(MappingVisitor visitor,
+ NominalTypeAnnotation node,
+ List<List<String>> visibleTypeParameterNames,
+ {malformedIsError: false, bool deferredIsMalformed: true}) {
ResolutionRegistry registry = visitor.registry;
Identifier typeName;
@@ -72,8 +229,9 @@ class TypeResolver {
DartType checkNoTypeArguments(DartType type) {
List<DartType> arguments = new List<DartType>();
- bool hasTypeArgumentMismatch =
- resolveTypeArguments(visitor, node, const <DartType>[], arguments);
+ bool hasTypeArgumentMismatch = resolveTypeArguments(
+ visitor, node, const <DartType>[], arguments,
+ visibleTypeParameterNames);
if (hasTypeArgumentMismatch) {
return new MalformedType(
new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH,
@@ -105,9 +263,6 @@ class TypeResolver {
}
}
- Element element = resolveTypeName(prefixName, typeName, visitor.scope,
- deferredIsMalformed: deferredIsMalformed);
-
DartType reportFailureAndCreateType(
MessageKind messageKind, Map messageArguments,
{DartType userProvidedBadType,
@@ -127,13 +282,33 @@ class TypeResolver {
typeName.source, visitor.enclosingElement);
}
List<DartType> arguments = <DartType>[];
- resolveTypeArguments(visitor, node, const <DartType>[], arguments);
+ resolveTypeArguments(visitor, node, const <DartType>[], 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.
Siggi Cherem (dart-lang) 2016/12/29 22:46:58 oh yikes - this does feel very hackish. Can you t
floitsch 2016/12/30 14:55:48 Yes. The problem is, that the function type doesn'
+ if (prefixName == null &&
+ visibleTypeParameterNames.any((n) => n.contains(typeName.source))) {
+ type = const DynamicType();
+ } 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) {
@@ -168,8 +343,9 @@ class TypeResolver {
resolver.ensureClassWillBeResolvedInternal(cls);
cls.computeType(resolution);
List<DartType> arguments = <DartType>[];
- bool hasTypeArgumentMismatch =
- resolveTypeArguments(visitor, node, cls.typeVariables, arguments);
+ bool hasTypeArgumentMismatch = resolveTypeArguments(
+ visitor, node, cls.typeVariables, arguments,
+ visibleTypeParameterNames);
if (hasTypeArgumentMismatch) {
type = new BadInterfaceType(
cls.declaration,
@@ -192,7 +368,8 @@ class TypeResolver {
typdef.computeType(resolution);
List<DartType> arguments = <DartType>[];
bool hasTypeArgumentMismatch = resolveTypeArguments(
- visitor, node, typdef.typeVariables, arguments);
+ visitor, node, typdef.typeVariables, arguments,
+ visibleTypeParameterNames);
if (hasTypeArgumentMismatch) {
type = new BadTypedefType(typdef,
new TypedefType.forUserProvidedBadType(typdef, arguments));
@@ -236,7 +413,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(_, DartType typeArgument,
TypeVariableType typeVariable, DartType bound) {
if (!types.isSubtype(typeArgument, bound)) {
@@ -259,8 +436,9 @@ class TypeResolver {
* Returns [: true :] if the number of type arguments did not match the
* number of type variables.
*/
- bool resolveTypeArguments(MappingVisitor visitor, TypeAnnotation node,
- List<DartType> typeVariables, List<DartType> arguments) {
+ bool resolveTypeArguments(MappingVisitor visitor, NominalTypeAnnotation node,
+ List<DartType> typeVariables, List<DartType> arguments,
+ List<List<String>> visibleTypeParameterNames) {
if (node.typeArguments == null) {
return false;
}
@@ -275,7 +453,8 @@ class TypeResolver {
typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT);
typeArgumentCountMismatch = true;
}
- DartType argType = resolveTypeAnnotation(visitor, typeArguments.head);
+ DartType argType = _resolveTypeAnnotation(
+ visitor, typeArguments.head, visibleTypeParameterNames);
// TODO(karlklose): rewrite to not modify [arguments].
arguments.add(argType);
}

Powered by Google App Engine
This is Rietveld 408576698