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 8f937bceea68cd9effa21784bab6986581875dc8..a0491a0144979840e8961f56deec3c6a17c9f765 100644 |
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart |
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart |
@@ -1038,6 +1038,18 @@ class TypeResolver { |
TypeResolver(this.compiler); |
+ bool anyMalformedTypesInThere(Link<DartType> list) { |
ngeoffray
2012/11/27 09:37:35
Personal taste, but I would remove 'InThere'.
aam-me
2012/11/28 01:49:47
I understand. No objections to this.
|
+ for (Link<DartType> link = list; |
+ !link.isEmpty; |
+ link = link.tail) { |
+ DartType dtype = link.head; |
+ if (dtype is MalformedType) { |
+ return true; |
+ } |
+ } |
+ return false; |
+ } |
+ |
Element resolveTypeName(Scope scope, TypeAnnotation node) { |
Identifier typeName = node.typeName.asIdentifier(); |
Send send = node.typeName.asSend(); |
@@ -1081,6 +1093,7 @@ class TypeResolver { |
DartType resolveTypeAnnotation( |
TypeAnnotation node, |
Scope scope, |
+ bool inStaticContext, |
{onFailure(Node node, MessageKind kind, [List arguments]), |
whenResolved(Node node, DartType type)}) { |
if (onFailure == null) { |
@@ -1092,11 +1105,12 @@ class TypeResolver { |
if (scope == null) { |
compiler.internalError('resolveTypeAnnotation: no scope specified'); |
} |
- return resolveTypeAnnotationInContext(scope, node, onFailure, |
- whenResolved); |
+ return resolveTypeAnnotationInContext(scope, node, inStaticContext, |
+ onFailure, whenResolved); |
} |
DartType resolveTypeAnnotationInContext(Scope scope, TypeAnnotation node, |
+ bool inStaticContext, |
onFailure, whenResolved) { |
Element element = resolveTypeName(scope, node); |
DartType type; |
@@ -1115,13 +1129,21 @@ class TypeResolver { |
ClassElement cls = element; |
cls.ensureResolved(compiler); |
Link<DartType> arguments = |
- resolveTypeArguments(node, cls.typeVariables, scope, |
+ resolveTypeArguments(node, cls.typeVariables, |
+ inStaticContext, scope, |
onFailure, whenResolved); |
if (cls.typeVariables.isEmpty && arguments.isEmpty) { |
// Use the canonical type if it has no type parameters. |
type = cls.computeType(compiler); |
} else { |
- type = new InterfaceType(cls.declaration, arguments); |
+ // In checked mode malformed-ness of the type argument bubbles up. |
ngeoffray
2012/11/27 09:37:35
Why not in non-checked mode? Is that an optimizati
aam-me
2012/11/28 01:49:47
When we produce MalformedTypeElement here, it trig
ahe
2012/11/28 02:08:50
I think what Nicolas is saying is that we generall
|
+ if (anyMalformedTypesInThere(arguments) && |
+ compiler.enableTypeAssertions) { |
+ type = new MalformedType( |
+ new MalformedTypeElement(node, element)); |
+ } else { |
+ type = new InterfaceType(cls.declaration, arguments); |
+ } |
} |
} else if (element.isTypedef()) { |
TypedefElement typdef = element; |
@@ -1129,7 +1151,7 @@ class TypeResolver { |
compiler.resolveTypedef(typdef); |
typdef.computeType(compiler); |
Link<DartType> arguments = resolveTypeArguments( |
- node, typdef.typeVariables, |
+ node, typdef.typeVariables, inStaticContext, |
scope, onFailure, whenResolved); |
if (typdef.typeVariables.isEmpty && arguments.isEmpty) { |
// Return the canonical type if it has no type parameters. |
@@ -1138,7 +1160,14 @@ class TypeResolver { |
type = new TypedefType(typdef, arguments); |
} |
} else if (element.isTypeVariable()) { |
- type = element.computeType(compiler); |
+ if (inStaticContext) { |
+ compiler.reportWarning(node, |
+ MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.message( |
+ [element])); |
+ type = new MalformedType(new MalformedTypeElement(node, element)); |
+ } else { |
+ type = element.computeType(compiler); |
+ } |
} else { |
compiler.cancel("unexpected element kind ${element.kind}", |
node: node); |
@@ -1150,6 +1179,7 @@ class TypeResolver { |
Link<DartType> resolveTypeArguments(TypeAnnotation node, |
Link<DartType> typeVariables, |
+ bool inStaticContext, |
Scope scope, onFailure, whenResolved) { |
if (node.typeArguments == null) { |
return const Link<DartType>(); |
@@ -1163,6 +1193,7 @@ class TypeResolver { |
} |
DartType argType = resolveTypeAnnotationInContext(scope, |
typeArguments.head, |
+ inStaticContext, |
onFailure, |
whenResolved); |
arguments.addLast(argType); |
@@ -2057,21 +2088,10 @@ class ResolverVisitor extends CommonResolverVisitor<Element> { |
} |
DartType resolveTypeAnnotation(TypeAnnotation node) { |
- // TODO(johnniwinther): Remove this together with the named arguments |
- // on [TypeResolver.resolveTypeAnnotation]. |
- void checkAndUseType(TypeAnnotation annotation, DartType type) { |
- useType(annotation, type); |
- if (type != null && |
- identical(type.kind, TypeKind.TYPE_VARIABLE) && |
- enclosingElement.isInStaticMember()) { |
- warning(annotation, MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, |
- [type]); |
- } |
- } |
- |
Function report = typeRequired ? error : warning; |
DartType type = typeResolver.resolveTypeAnnotation( |
- node, scope, onFailure: report, whenResolved: checkAndUseType); |
+ node, scope, enclosingElement.isInStaticMember(), |
+ onFailure: report, whenResolved: useType); |
if (type == null) return null; |
if (inCheckContext) { |
compiler.enqueuer.resolution.registerIsCheck(type); |
@@ -2438,7 +2458,8 @@ class TypeDefinitionVisitor extends CommonResolverVisitor<DartType> { |
TypeVariableElement variableElement = typeVariable.element; |
if (typeNode.bound != null) { |
DartType boundType = typeResolver.resolveTypeAnnotation( |
- typeNode.bound, scope, onFailure: warning); |
+ typeNode.bound, scope, element.isInStaticMember(), |
+ onFailure: warning); |
if (boundType != null && boundType.element == variableElement) { |
// TODO(johnniwinther): Check for more general cycles, like |
// [: <A extends B, B extends C, C extends B> :]. |