Index: sdk/lib/_internal/compiler/implementation/resolution/members.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart |
index 8660177a3db7d47096d23591c33435a573c18673..cea260dac883e35ab42b2a75dc43a0386350761a 100644 |
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart |
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart |
@@ -1427,22 +1427,9 @@ class TypeResolver { |
} |
} |
- // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean |
- // flags instead of closures. |
- DartType resolveTypeAnnotation( |
- MappingVisitor visitor, |
- TypeAnnotation node, |
- {onFailure(Node node, DualKind kind, [Map arguments])}) { |
- if (onFailure == null) { |
- onFailure = (n, k, [arguments]) {}; |
- } |
- return resolveTypeAnnotationInContext(visitor, node, onFailure); |
- } |
- |
- DartType resolveTypeAnnotationInContext( |
- MappingVisitor visitor, |
- TypeAnnotation node, |
- onFailure(Node node, DualKind kind, [Map arguments])) { |
+ DartType resolveTypeAnnotation(MappingVisitor visitor, TypeAnnotation node, |
+ {bool malformedIsError: false, |
+ bool ambiguousIsError: false}) { |
Identifier typeName; |
SourceString prefixName; |
Send send = node.typeName.asSend(); |
@@ -1458,24 +1445,31 @@ class TypeResolver { |
DartType type; |
DartType reportFailureAndCreateType(DualKind messageKind, |
- Map messageArguments) { |
- onFailure(node, messageKind, messageArguments); |
+ Map messageArguments, |
+ {DartType userProvidedBadType, |
+ bool isError: false, |
+ bool isAmbiguous: false}) { |
+ if (isError) { |
+ visitor.error(node, messageKind.error, messageArguments); |
+ } else { |
+ visitor.warning(node, messageKind.warning, messageArguments); |
+ } |
var erroneousElement = new ErroneousElementX( |
messageKind.error, messageArguments, typeName.source, |
visitor.enclosingElement); |
var arguments = new LinkBuilder<DartType>(); |
- resolveTypeArguments( |
- visitor, node, null, |
- onFailure, arguments); |
- return new MalformedType(erroneousElement, null, arguments.toLink()); |
+ resolveTypeArguments(visitor, node, null, arguments); |
+ return isAmbiguous |
+ ? new AmbiguousType(erroneousElement, arguments.toLink()) |
+ : new MalformedType(erroneousElement, |
+ userProvidedBadType, arguments.toLink()); |
} |
DartType checkNoTypeArguments(DartType type) { |
var arguments = new LinkBuilder<DartType>(); |
- bool hashTypeArgumentMismatch = resolveTypeArguments( |
- visitor, node, const Link<DartType>(), |
- onFailure, arguments); |
- if (hashTypeArgumentMismatch) { |
+ bool hasTypeArgumentMismatch = resolveTypeArguments( |
+ visitor, node, const Link<DartType>(), arguments); |
+ if (hasTypeArgumentMismatch) { |
type = new MalformedType( |
new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, |
{'type': node}, typeName.source, visitor.enclosingElement), |
@@ -1486,33 +1480,33 @@ class TypeResolver { |
if (element == null) { |
type = reportFailureAndCreateType( |
- MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName}); |
+ MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName}, |
+ isError: malformedIsError); |
} else if (element.isAmbiguous()) { |
AmbiguousElement ambiguous = element; |
type = reportFailureAndCreateType( |
- ambiguous.messageKind, ambiguous.messageArguments); |
+ ambiguous.messageKind, ambiguous.messageArguments, |
+ isError: ambiguousIsError, isAmbiguous: true); |
ambiguous.diagnose(visitor.mapping.currentElement, compiler); |
} else if (!element.impliesType()) { |
type = reportFailureAndCreateType( |
- MessageKind.NOT_A_TYPE, {'node': node.typeName}); |
+ MessageKind.NOT_A_TYPE, {'node': node.typeName}, |
+ isError: malformedIsError); |
} else { |
if (identical(element, compiler.types.voidType.element) || |
- identical(element, compiler.types.dynamicType.element)) { |
+ identical(element, compiler.dynamicClass)) { |
type = checkNoTypeArguments(element.computeType(compiler)); |
} else if (element.isClass()) { |
ClassElement cls = element; |
compiler.resolver._ensureClassWillBeResolved(cls); |
element.computeType(compiler); |
var arguments = new LinkBuilder<DartType>(); |
- bool hashTypeArgumentMismatch = resolveTypeArguments( |
- visitor, node, cls.typeVariables, |
- onFailure, arguments); |
- if (hashTypeArgumentMismatch) { |
- type = new MalformedType( |
- new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, |
- {'type': node}, typeName.source, visitor.enclosingElement), |
- new InterfaceType.userProvidedBadType(cls.declaration, |
- arguments.toLink())); |
+ bool hasTypeArgumentMismatch = resolveTypeArguments( |
+ visitor, node, cls.typeVariables, arguments); |
+ if (hasTypeArgumentMismatch) { |
+ type = new BadInterfaceType(cls.declaration, |
+ new InterfaceType.forUserProvidedBadType(cls.declaration, |
+ arguments.toLink())); |
} else { |
if (arguments.isEmpty) { |
type = cls.rawType; |
@@ -1525,14 +1519,12 @@ class TypeResolver { |
// TODO(ahe): Should be [ensureResolved]. |
compiler.resolveTypedef(typdef); |
var arguments = new LinkBuilder<DartType>(); |
- bool hashTypeArgumentMismatch = resolveTypeArguments( |
- visitor, node, typdef.typeVariables, |
- onFailure, arguments); |
- if (hashTypeArgumentMismatch) { |
- type = new MalformedType( |
- new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, |
- {'type': node}, typeName.source, visitor.enclosingElement), |
- new TypedefType.userProvidedBadType(typdef, arguments.toLink())); |
+ bool hasTypeArgumentMismatch = resolveTypeArguments( |
+ visitor, node, typdef.typeVariables, arguments); |
+ if (hasTypeArgumentMismatch) { |
+ type = new BadTypedefType(typdef, |
+ new TypedefType.forUserProvidedBadType(typdef, |
+ arguments.toLink())); |
} else { |
if (arguments.isEmpty) { |
type = typdef.rawType; |
@@ -1550,16 +1542,11 @@ class TypeResolver { |
!isInFactoryConstructor && |
Elements.isInStaticContext(visitor.enclosingElement)) { |
compiler.backend.registerThrowRuntimeError(visitor.mapping); |
- compiler.reportWarningCode( |
- node, |
- MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.warning, |
- {'typeVariableName': node}); |
- type = new MalformedType( |
- new ErroneousElementX( |
- MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.error, |
- {'typeVariableName': node}, |
- typeName.source, visitor.enclosingElement), |
- element.computeType(compiler)); |
+ type = reportFailureAndCreateType( |
+ MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, |
+ {'typeVariableName': node}, |
+ userProvidedBadType: element.computeType(compiler), |
+ isError: malformedIsError); |
} else { |
type = element.computeType(compiler); |
} |
@@ -1583,8 +1570,8 @@ class TypeResolver { |
MappingVisitor visitor, |
TypeAnnotation node, |
Link<DartType> typeVariables, |
- onFailure(Node node, DualKind kind, [Map arguments]), |
- LinkBuilder<DartType> arguments) { |
+ LinkBuilder<DartType> arguments, |
+ {bool ambiguousIsError: false}) { |
if (node.typeArguments == null) { |
return false; |
} |
@@ -1593,19 +1580,20 @@ class TypeResolver { |
!typeArguments.isEmpty; |
typeArguments = typeArguments.tail) { |
if (typeVariables != null && typeVariables.isEmpty) { |
- onFailure(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
+ visitor.warning( |
+ typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT.warning); |
typeArgumentCountMismatch = true; |
} |
- DartType argType = resolveTypeAnnotationInContext(visitor, |
- typeArguments.head, |
- onFailure); |
+ DartType argType = resolveTypeAnnotation(visitor, typeArguments.head, |
+ ambiguousIsError: ambiguousIsError); |
arguments.addLast(argType); |
if (typeVariables != null && !typeVariables.isEmpty) { |
typeVariables = typeVariables.tail; |
} |
} |
if (typeVariables != null && !typeVariables.isEmpty) { |
- onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); |
+ visitor.warning(node.typeArguments, |
+ MessageKind.MISSING_TYPE_ARGUMENT.warning); |
typeArgumentCountMismatch = true; |
} |
return typeArgumentCountMismatch; |
@@ -1661,7 +1649,6 @@ class ResolverVisitor extends MappingVisitor<Element> { |
Scope scope; |
ClassElement currentClass; |
ExpressionStatement currentExpressionStatement; |
- bool typeRequired = false; |
bool sendIsMemberAccess = false; |
StatementScope statementScope; |
int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION |
@@ -2280,13 +2267,13 @@ class ResolverVisitor extends MappingVisitor<Element> { |
String operatorString = node.selector.asOperator().source.stringValue; |
if (operatorString == 'is') { |
DartType type = |
- resolveTypeRequired(node.typeAnnotationFromIsCheckOrCast); |
+ resolveTypeExpression(node.typeAnnotationFromIsCheckOrCast); |
if (type != null) { |
compiler.enqueuer.resolution.registerIsCheck(type, mapping); |
} |
resolvedArguments = true; |
} else if (operatorString == 'as') { |
- DartType type = resolveTypeRequired(node.arguments.head); |
+ DartType type = resolveTypeExpression(node.arguments.head); |
if (type != null) { |
compiler.enqueuer.resolution.registerAsCheck(type, mapping); |
} |
@@ -2698,23 +2685,17 @@ class ResolverVisitor extends MappingVisitor<Element> { |
return node.accept(new ConstructorResolver(compiler, this)); |
} |
- DartType resolveTypeRequired(TypeAnnotation node) { |
- bool old = typeRequired; |
- typeRequired = true; |
- DartType result = resolveTypeAnnotation(node); |
- typeRequired = old; |
- return result; |
+ DartType resolveTypeExpression(TypeAnnotation node) { |
+ return resolveTypeAnnotation(node, isTypeExpression: true); |
} |
- DartType resolveTypeAnnotation(TypeAnnotation node) { |
- Function report = typeRequired ? dualError : dualWarning; |
+ DartType resolveTypeAnnotation(TypeAnnotation node, |
+ {bool isTypeExpression: false}) { |
DartType type = typeResolver.resolveTypeAnnotation( |
- this, node, onFailure: report); |
+ this, node, ambiguousIsError: isTypeExpression); |
if (type == null) return null; |
if (inCheckContext) { |
compiler.enqueuer.resolution.registerIsCheck(type, mapping); |
- } |
- if (typeRequired || inCheckContext) { |
compiler.backend.registerRequiredType(type, enclosingElement); |
} |
return type; |
@@ -2731,12 +2712,13 @@ class ResolverVisitor extends MappingVisitor<Element> { |
if (arguments != null) { |
Link<Node> nodes = arguments.nodes; |
if (nodes.isEmpty) { |
+ // The syntax [: <>[] :] is not allowed. |
error(arguments, MessageKind.MISSING_TYPE_ARGUMENT.error); |
} else { |
- typeArgument = resolveTypeRequired(nodes.head); |
+ typeArgument = resolveTypeExpression(nodes.head); |
for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) { |
- error(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT.error); |
- resolveTypeRequired(nodes.head); |
+ warning(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT.warning); |
+ resolveTypeAnnotation(nodes.head); |
} |
} |
} |
@@ -2754,6 +2736,7 @@ class ResolverVisitor extends MappingVisitor<Element> { |
} |
mapping.setType(node, listType); |
world.registerInstantiatedType(listType, mapping); |
+ compiler.backend.registerRequiredType(listType, enclosingElement); |
visit(node.elements); |
} |
@@ -2935,17 +2918,18 @@ class ResolverVisitor extends MappingVisitor<Element> { |
if (arguments != null) { |
Link<Node> nodes = arguments.nodes; |
if (nodes.isEmpty) { |
+ // The syntax [: <>{} :] is not allowed. |
error(arguments, MessageKind.MISSING_TYPE_ARGUMENT.error); |
} else { |
- keyTypeArgument = resolveTypeRequired(nodes.head); |
+ keyTypeArgument = resolveTypeExpression(nodes.head); |
nodes = nodes.tail; |
if (nodes.isEmpty) { |
- error(arguments, MessageKind.MISSING_TYPE_ARGUMENT.error); |
+ warning(arguments, MessageKind.MISSING_TYPE_ARGUMENT.warning); |
} else { |
- valueTypeArgument = resolveTypeRequired(nodes.head); |
+ valueTypeArgument = resolveTypeExpression(nodes.head); |
for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) { |
- error(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT.error); |
- resolveTypeRequired(nodes.head); |
+ warning(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT.warning); |
+ resolveTypeAnnotation(nodes.head); |
} |
} |
} |
@@ -2967,6 +2951,7 @@ class ResolverVisitor extends MappingVisitor<Element> { |
if (node.isConst()) { |
compiler.backend.registerConstantMap(mapping); |
} |
+ compiler.backend.registerRequiredType(mapType, enclosingElement); |
node.visitChildren(this); |
} |
@@ -3112,10 +3097,7 @@ class ResolverVisitor extends MappingVisitor<Element> { |
} |
Scope blockScope = new BlockScope(scope); |
- var wasTypeRequired = typeRequired; |
- typeRequired = true; |
doInCheckContext(() => visitIn(node.type, blockScope)); |
- typeRequired = wasTypeRequired; |
visitIn(node.formals, blockScope); |
var oldInCatchBlock = inCatchBlock; |
inCatchBlock = true; |
@@ -3173,7 +3155,7 @@ class TypeDefinitionVisitor extends MappingVisitor<DartType> { |
TypeVariableElement variableElement = typeVariable.element; |
if (typeNode.bound != null) { |
DartType boundType = typeResolver.resolveTypeAnnotation( |
- this, typeNode.bound, onFailure: dualWarning); |
+ this, typeNode.bound); |
variableElement.bound = boundType; |
void checkTypeVariableBound() { |
@@ -3445,7 +3427,7 @@ class ClassResolverVisitor extends TypeDefinitionVisitor { |
DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { |
DartType supertype = typeResolver.resolveTypeAnnotation( |
- this, superclass, onFailure: dualError); |
+ this, superclass, malformedIsError: true); |
if (supertype != null) { |
if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) { |
// Error has already been reported. |
@@ -3467,7 +3449,7 @@ class ClassResolverVisitor extends TypeDefinitionVisitor { |
if (interfaces == null) return result; |
for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) { |
DartType interfaceType = typeResolver.resolveTypeAnnotation( |
- this, link.head, onFailure: dualError); |
+ this, link.head, malformedIsError: true); |
if (interfaceType != null) { |
if (identical(interfaceType.kind, TypeKind.MALFORMED_TYPE)) { |
// Error has already been reported. |
@@ -3583,7 +3565,7 @@ class ClassResolverVisitor extends TypeDefinitionVisitor { |
!identical(lib, compiler.coreLibrary) && |
!identical(lib, compiler.jsHelperLibrary) && |
!identical(lib, compiler.interceptorsLibrary) && |
- (identical(type.element, compiler.dynamicClass) || |
+ (identical(type, compiler.types.dynamicType) || |
identical(type.element, compiler.boolClass) || |
identical(type.element, compiler.numClass) || |
identical(type.element, compiler.intClass) || |
@@ -4027,7 +4009,7 @@ class ConstructorResolver extends CommonResolverVisitor<Element> { |
} |
if (type == null) { |
if (Elements.isUnresolved(e)) { |
- type = compiler.dynamicClass.computeType(compiler); |
+ type = compiler.types.dynamicType; |
} else { |
type = e.getEnclosingClass().computeType(compiler).asRaw(); |
} |
@@ -4038,7 +4020,8 @@ class ConstructorResolver extends CommonResolverVisitor<Element> { |
visitTypeAnnotation(TypeAnnotation node) { |
assert(invariant(node, type == null)); |
- type = resolver.resolveTypeRequired(node); |
+ type = resolver.resolveTypeExpression(node); |
+ compiler.backend.registerRequiredType(type, resolver.enclosingElement); |
return resolver.mapping[node]; |
} |