diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index e58fdf6f44b..c8169a97a6f 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -183,6 +183,7 @@ public class ClassDescriptorResolver { } } } + for (TypeParameterDescriptor parameter : parameters) { if (JetStandardClasses.isNothing(parameter.getBoundsAsType())) { PsiElement nameIdentifier = typeParameters.get(parameter.getIndex()).getNameIdentifier(); @@ -652,7 +653,7 @@ public class ClassDescriptorResolver { return propertyDescriptor; } - public void checkBounds(JetTypeReference typeReference, JetType type) { + public void checkBounds(@NotNull JetTypeReference typeReference, @NotNull JetType type) { if (ErrorUtils.isErrorType(type)) return; JetTypeElement typeElement = typeReference.getTypeElement(); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 27c01026b73..31d70c95684 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -325,15 +325,30 @@ public class TopDownAnalyzer { JetClass jetClass = entry.getKey(); for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) { - JetType type = trace.getBindingContext().resolveTypeReference(delegationSpecifier.getTypeReference()); - classDescriptorResolver.checkBounds(delegationSpecifier.getTypeReference(), type); + JetTypeReference typeReference = delegationSpecifier.getTypeReference(); + if (typeReference != null) { + JetType type = trace.getBindingContext().resolveTypeReference(typeReference); + classDescriptorResolver.checkBounds(typeReference, type); + } } for (JetTypeParameter jetTypeParameter : jetClass.getTypeParameters()) { JetTypeReference extendsBound = jetTypeParameter.getExtendsBound(); if (extendsBound != null) { JetType type = trace.getBindingContext().resolveTypeReference(extendsBound); - classDescriptorResolver.checkBounds(extendsBound, type); + if (type != null) { + classDescriptorResolver.checkBounds(extendsBound, type); + } + } + } + + for (JetTypeConstraint constraint : jetClass.getTypeConstaints()) { + JetTypeReference extendsBound = constraint.getBoundTypeReference(); + if (extendsBound != null) { + JetType type = trace.getBindingContext().resolveTypeReference(extendsBound); + if (type != null) { + classDescriptorResolver.checkBounds(extendsBound, type); + } } } diff --git a/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java index 4fe6cb82b2b..05e9b66a499 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -169,7 +169,7 @@ public class ErrorUtils { return typeConstructor == ERROR_CLASS.getTypeConstructor(); } - public static boolean isErrorType(JetType type) { + public static boolean isErrorType(@NotNull JetType type) { return (type instanceof DeferredType && ((DeferredType) type).getActualType() == null) || type instanceof ErrorTypeImpl || isError(type.getConstructor()); diff --git a/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java b/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java index c992424a5d1..2b59fd9740a 100644 --- a/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/idea/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -94,7 +94,7 @@ public class TypeUtils { new ChainedScope(null, scopes)); // TODO : check intersectibility, don't use a chanied scope } - private static boolean canHaveSubtypes(JetTypeChecker typeChecker, JetType type) { + public static boolean canHaveSubtypes(JetTypeChecker typeChecker, JetType type) { if (type.isNullable()) { return true; } diff --git a/idea/testData/checker/MultipleBounds.jet b/idea/testData/checker/MultipleBounds.jet new file mode 100644 index 00000000000..ff4c3533eb5 --- /dev/null +++ b/idea/testData/checker/MultipleBounds.jet @@ -0,0 +1,47 @@ +namespace Jet87 + +open class A() { + fun foo() : Int +} + +open class B() { + fun bar() : Double; +} + +class C() : A(), B() + +class D() { + class object : A(), B () {} +} + +class Test1 + where + T : B, + B : T, // error + class object T : A, + class object T : B, + class object B : T + () { + + fun test(t : T) { + T.foo() + T.bar() + t.foo() + t.bar() + } +} + +fun test() { + new Test1<B>() + new Test1<A>() + new Test1() +} + +class Foo() {} + +class Bar + +class Buzz where T : Bar<Int>, T : nioho + +class X +class Y<T : Foo> where T : Bar \ No newline at end of file