JET-84 Support generic parameter constraints for class objects
Test for classes + small fixes
This commit is contained in:
@@ -183,6 +183,7 @@ public class ClassDescriptorResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (TypeParameterDescriptor parameter : parameters) {
|
for (TypeParameterDescriptor parameter : parameters) {
|
||||||
if (JetStandardClasses.isNothing(parameter.getBoundsAsType())) {
|
if (JetStandardClasses.isNothing(parameter.getBoundsAsType())) {
|
||||||
PsiElement nameIdentifier = typeParameters.get(parameter.getIndex()).getNameIdentifier();
|
PsiElement nameIdentifier = typeParameters.get(parameter.getIndex()).getNameIdentifier();
|
||||||
@@ -652,7 +653,7 @@ public class ClassDescriptorResolver {
|
|||||||
return propertyDescriptor;
|
return propertyDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkBounds(JetTypeReference typeReference, JetType type) {
|
public void checkBounds(@NotNull JetTypeReference typeReference, @NotNull JetType type) {
|
||||||
if (ErrorUtils.isErrorType(type)) return;
|
if (ErrorUtils.isErrorType(type)) return;
|
||||||
|
|
||||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||||
|
|||||||
@@ -325,15 +325,30 @@ public class TopDownAnalyzer {
|
|||||||
JetClass jetClass = entry.getKey();
|
JetClass jetClass = entry.getKey();
|
||||||
|
|
||||||
for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) {
|
for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) {
|
||||||
JetType type = trace.getBindingContext().resolveTypeReference(delegationSpecifier.getTypeReference());
|
JetTypeReference typeReference = delegationSpecifier.getTypeReference();
|
||||||
classDescriptorResolver.checkBounds(delegationSpecifier.getTypeReference(), type);
|
if (typeReference != null) {
|
||||||
|
JetType type = trace.getBindingContext().resolveTypeReference(typeReference);
|
||||||
|
classDescriptorResolver.checkBounds(typeReference, type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JetTypeParameter jetTypeParameter : jetClass.getTypeParameters()) {
|
for (JetTypeParameter jetTypeParameter : jetClass.getTypeParameters()) {
|
||||||
JetTypeReference extendsBound = jetTypeParameter.getExtendsBound();
|
JetTypeReference extendsBound = jetTypeParameter.getExtendsBound();
|
||||||
if (extendsBound != null) {
|
if (extendsBound != null) {
|
||||||
JetType type = trace.getBindingContext().resolveTypeReference(extendsBound);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ public class ErrorUtils {
|
|||||||
return typeConstructor == ERROR_CLASS.getTypeConstructor();
|
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) ||
|
return (type instanceof DeferredType && ((DeferredType) type).getActualType() == null) ||
|
||||||
type instanceof ErrorTypeImpl ||
|
type instanceof ErrorTypeImpl ||
|
||||||
isError(type.getConstructor());
|
isError(type.getConstructor());
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public class TypeUtils {
|
|||||||
new ChainedScope(null, scopes)); // TODO : check intersectibility, don't use a chanied scope
|
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()) {
|
if (type.isNullable()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<T : A>
|
||||||
|
where
|
||||||
|
T : B,
|
||||||
|
<error>B</error> : T, // error
|
||||||
|
class object T : A,
|
||||||
|
class object T : B,
|
||||||
|
class object <error>B</error> : T
|
||||||
|
() {
|
||||||
|
|
||||||
|
fun test(t : T) {
|
||||||
|
T.foo()
|
||||||
|
T.bar()
|
||||||
|
t.foo()
|
||||||
|
t.bar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
new Test1<<error>B</error>>()
|
||||||
|
new Test1<<error>A</error>>()
|
||||||
|
new Test1<C>()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo() {}
|
||||||
|
|
||||||
|
class Bar<T : Foo>
|
||||||
|
|
||||||
|
class Buzz<T> where T : Bar<<error>Int</error>>, T : <error>nioho</error>
|
||||||
|
|
||||||
|
class X<T : Foo>
|
||||||
|
class Y<<error>T</error> : Foo> where T : Bar<Foo>
|
||||||
Reference in New Issue
Block a user