Permalink
Browse files

KT-1863 Wrong nullability for class derived from java classes.

 #KT-1863 In progress
  • Loading branch information...
1 parent dcc2728 commit 08de6d8d0730201dfb845d1144a5e5b7c2297960 @abreslav abreslav committed Apr 28, 2012
View
2 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java
@@ -959,7 +959,7 @@ private void transformSupertypeList(List<JetType> result, PsiClassType[] extends
continue;
}
- JetType transform = semanticServices.getTypeTransformer().transformToType(type, typeVariableResolver);
+ JetType transform = semanticServices.getTypeTransformer().transformToType(type, JavaTypeTransformer.TypeUsage.SUPERTYPE, typeVariableResolver);
result.add(TypeUtils.makeNotNullable(transform));
}
View
47 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java
@@ -33,11 +33,9 @@
import org.jetbrains.jet.rt.signature.JetSignatureReader;
import javax.inject.Inject;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
+
+import static org.jetbrains.jet.lang.resolve.java.JavaTypeTransformer.TypeUsage.*;
/**
* @author abreslav
@@ -66,9 +64,11 @@ public void setResolver(JavaDescriptorResolver resolver) {
@NotNull
- public TypeProjection transformToTypeProjection(@NotNull final PsiType javaType,
+ private TypeProjection transformToTypeProjection(@NotNull final PsiType javaType,
@NotNull final TypeParameterDescriptor typeParameterDescriptor,
- @NotNull final TypeVariableResolver typeVariableByPsiResolver) {
+ @NotNull final TypeVariableResolver typeVariableByPsiResolver,
+ @NotNull final TypeUsage howThisTypeIsUsed
+ ) {
TypeProjection result = javaType.accept(new PsiTypeVisitor<TypeProjection>() {
@Override
@@ -85,12 +85,12 @@ public TypeProjection visitWildcardType(PsiWildcardType wildcardType) {
PsiType bound = wildcardType.getBound();
assert bound != null;
- return new TypeProjection(variance, transformToType(bound, TypeUsage.UPPER_BOUND, typeVariableByPsiResolver));
+ return new TypeProjection(variance, transformToType(bound, UPPER_BOUND, typeVariableByPsiResolver));
}
@Override
public TypeProjection visitType(PsiType type) {
- return new TypeProjection(transformToType(type, TypeUsage.TYPE_ARGUMENT, typeVariableByPsiResolver));
+ return new TypeProjection(transformToType(type, howThisTypeIsUsed, typeVariableByPsiResolver));
}
});
return result;
@@ -136,28 +136,32 @@ public JetType visitClassType(PsiClassType classType) {
if (psiMethod.isConstructor()) {
Set<JetType> supertypesJet = Sets.newHashSet();
for (PsiClassType supertype : typeParameter.getExtendsListTypes()) {
- supertypesJet.add(transformToType(supertype, TypeUsage.UPPER_BOUND, typeVariableResolver));
+ supertypesJet.add(transformToType(supertype, UPPER_BOUND, typeVariableResolver));
}
return TypeUtils.intersect(JetTypeChecker.INSTANCE, supertypesJet);
}
}
TypeParameterDescriptor typeParameterDescriptor = typeVariableResolver.getTypeVariable(typeParameter.getName());
- if (howThisTypeIsUsed == TypeUsage.TYPE_ARGUMENT || howThisTypeIsUsed == TypeUsage.UPPER_BOUND) {
- // In Java: ArrayList<T>
- // In Kotlin: ArrayList<T>, not ArrayList<T?>
- // nullability will be taken care of in individual member signatures
- return typeParameterDescriptor.getDefaultType();
+ // In Java: ArrayList<T>
+ // In Kotlin: ArrayList<T>, not ArrayList<T?>
+ // nullability will be taken care of in individual member signatures
+ boolean nullable = !EnumSet.of(TYPE_ARGUMENT, UPPER_BOUND, SUPERTYPE_ARGUMENT).contains(howThisTypeIsUsed);
+ if (nullable) {
+ return TypeUtils.makeNullable(typeParameterDescriptor.getDefaultType());
}
else {
- return TypeUtils.makeNullable(typeParameterDescriptor.getDefaultType());
+ return typeParameterDescriptor.getDefaultType();
}
}
else {
+ // 'L extends List<T>' in Java is a List<T> in Kotlin, not a List<T?>
+ boolean nullable = !EnumSet.of(SUPERTYPE_ARGUMENT, SUPERTYPE).contains(howThisTypeIsUsed);
+
JetType jetAnalog = getKotlinAnalog(new FqName(psiClass.getQualifiedName()));
if (jetAnalog != null) {
- return jetAnalog;
+ return TypeUtils.makeNullableAsSpecified(jetAnalog, nullable);
}
final ClassDescriptor classData =
@@ -187,13 +191,15 @@ public JetType visitClassType(PsiClassType classType) {
PsiType psiArgument = psiArguments[i];
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
- arguments.add(transformToTypeProjection(psiArgument, typeParameterDescriptor, typeVariableResolver));
+ TypeUsage howTheProjectionIsUsed = howThisTypeIsUsed == SUPERTYPE ? SUPERTYPE_ARGUMENT : TYPE_ARGUMENT;
+ arguments.add(transformToTypeProjection(psiArgument, typeParameterDescriptor, typeVariableResolver, howTheProjectionIsUsed));
}
}
+
return new JetTypeImpl(
Collections.<AnnotationDescriptor>emptyList(),
classData.getTypeConstructor(),
- true,
+ nullable,
arguments,
classData.getMemberScope(arguments));
}
@@ -291,6 +297,7 @@ public ClassDescriptor unwrapPrimitive(@NotNull FqName fqName) {
MEMBER_SIGNATURE_COVARIANT,
MEMBER_SIGNATURE_CONTRAVARIANT,
MEMBER_SIGNATURE_INVARIANT,
- SUPERTYPE
+ SUPERTYPE,
+ SUPERTYPE_ARGUMENT
}
}
View
23 ...ler/testData/diagnostics/tests/j+k/SupertypeArgumentsNullability-NotNull-SpecialTypes.jet
@@ -0,0 +1,23 @@
+// FILE: A.java
+public class A {}
+
+// FILE: X.java
+import org.jetbrains.annotations.NotNull;
+
+public class X<T> {
+ @NotNull T fooN() {return null;}
+ void barN(@NotNull T a) {}
+}
+
+// FILE: Y.java
+public class Y extends X<String> {
+
+}
+
+// FILE: test.kt
+
+fun main() {
+ Y().fooN() : Any
+ Y().barN(<!ERROR_COMPILE_TIME_VALUE!>null<!>);
+}
+
View
23 compiler/testData/diagnostics/tests/j+k/SupertypeArgumentsNullability-NotNull-UserTypes.jet
@@ -0,0 +1,23 @@
+// FILE: A.java
+public class A {}
+
+// FILE: X.java
+import org.jetbrains.annotations.NotNull;
+
+public class X<T> {
+ @NotNull T fooN() {return null;}
+ void barN(@NotNull T a) {}
+}
+
+// FILE: Y.java
+public class Y extends X<A> {
+
+}
+
+// FILE: test.kt
+
+fun main() {
+ Y().fooN() : Any
+ Y().barN(<!ERROR_COMPILE_TIME_VALUE!>null<!>);
+}
+
View
21 compiler/testData/diagnostics/tests/j+k/SupertypeArgumentsNullability-SpecialTypes.jet
@@ -0,0 +1,21 @@
+// FILE: A.java
+public class A {}
+
+// FILE: X.java
+public class X<T> {
+ T foo() {return null;}
+ void bar(T a) {}
+}
+
+// FILE: Y.java
+public class Y extends X<String> {
+
+}
+
+// FILE: test.kt
+
+fun main() {
+ Y().foo()<!UNSAFE_CALL!>.<!>length
+ Y().bar(null)
+}
+
View
21 compiler/testData/diagnostics/tests/j+k/SupertypeArgumentsNullability-UserTypes.jet
@@ -0,0 +1,21 @@
+// FILE: A.java
+public class A {}
+
+// FILE: X.java
+public class X<T> {
+ T foo() {return null;}
+ void bar(T a) {}
+}
+
+// FILE: Y.java
+public class Y extends X<A> {
+
+}
+
+// FILE: test.kt
+
+fun main() {
+ Y().foo()<!UNSAFE_CALL!>.<!>hashCode()
+ Y().bar(null)
+}
+

0 comments on commit 08de6d8

Please sign in to comment.