Index: compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java |
diff --git a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java |
index c9761333d2a33ed23b0db34c9bfc79ffed9ce477..522c60943dc54f072377477b9fc5a5ae77279203 100644 |
--- a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java |
+++ b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java |
@@ -1,4 +1,4 @@ |
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
// 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. |
@@ -604,6 +604,34 @@ public class TypeAnalyzer implements DartCompilationPhase { |
} |
} |
+ /* Check for a type variable is repeated in its own bounds: |
+ * e.g. Foo<T extends T> |
+ */ |
+ private void checkCyclicBounds(List<? extends Type> arguments) { |
+ for (Type argument : arguments) { |
+ if (TypeKind.of(argument).equals(TypeKind.VARIABLE)) { |
+ TypeVariable typeVar = (TypeVariable) argument; |
+ checkCyclicBound(typeVar, typeVar.getTypeVariableElement().getBound()); |
+ } |
+ } |
+ } |
+ |
+ private void checkCyclicBound(TypeVariable variable, Type bound) { |
+ switch(TypeKind.of(bound)) { |
+ case VARIABLE: { |
+ TypeVariable boundType = (TypeVariable)bound; |
+ if (boundType.equals(variable)) { |
+ onError(boundType.getElement().getNode(), |
+ TypeErrorCode.CYCLIC_REFERENCE_TO_TYPE_VARIABLE, |
+ boundType.getElement().getOriginalSymbolName()); |
+ } |
+ break; |
+ } |
+ default: |
+ break; |
+ } |
+ } |
+ |
Type typeOf(DartNode node) { |
if (node == null) { |
return dynamicType; |
@@ -713,6 +741,7 @@ public class TypeAnalyzer implements DartCompilationPhase { |
public Type visitClass(DartClass node) { |
ClassElement element = node.getSymbol(); |
InterfaceType type = element.getType(); |
+ checkCyclicBounds(type.getArguments()); |
findUnimplementedMembers(element); |
setCurrentClass(type); |
visit(node.getTypeParameters()); |
@@ -883,7 +912,6 @@ public class TypeAnalyzer implements DartCompilationPhase { |
typeError(iterableExpression, TypeErrorCode.FOR_IN_WITH_ITERATOR_FIELD); |
} |
} |
- |
return typeAsVoid(node); |
} |
@@ -914,6 +942,10 @@ public class TypeAnalyzer implements DartCompilationPhase { |
@Override |
public Type visitFunctionTypeAlias(DartFunctionTypeAlias node) { |
+ if (TypeKind.of(node.getSymbol().getType()).equals(TypeKind.FUNCTION_ALIAS)) { |
+ FunctionAliasType type = node.getSymbol().getType(); |
+ checkCyclicBounds(type.getElement().getTypeParameters()); |
+ } |
return typeAsVoid(node); |
} |