| 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 c3151530f65bd9c55b207c7a51a1ee61ef4edc09..c92bc7958e02ff5819cca0f012df6d91cb234090 100644
|
| --- a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
|
| +++ b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
|
| @@ -655,6 +655,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;
|
| @@ -764,6 +792,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());
|
| @@ -934,7 +963,6 @@ public class TypeAnalyzer implements DartCompilationPhase {
|
| typeError(iterableExpression, TypeErrorCode.FOR_IN_WITH_ITERATOR_FIELD);
|
| }
|
| }
|
| -
|
| return typeAsVoid(node);
|
| }
|
|
|
| @@ -965,6 +993,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);
|
| }
|
|
|
|
|