diff --git a/build.xml b/build.xml index 8bfdcb0c50f..a564aadeafb 100644 --- a/build.xml +++ b/build.xml @@ -174,7 +174,7 @@ - + diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index ccb75ede668..0f1aa136143 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -737,11 +737,11 @@ public class JavaDescriptorResolver { typeParameterDescriptor.addUpperBound(JetStandardClasses.getNullableAnyType()); } else if (referencedTypes.length == 1) { - typeParameterDescriptor.addUpperBound(semanticServices.getTypeTransformer().transformToType(referencedTypes[0], typeVariableByPsiResolver)); + typeParameterDescriptor.addUpperBound(semanticServices.getTypeTransformer().transformToType(referencedTypes[0], JavaTypeTransformer.TypeUsage.UPPER_BOUND, typeVariableByPsiResolver)); } else { for (PsiClassType referencedType : referencedTypes) { - typeParameterDescriptor.addUpperBound(semanticServices.getTypeTransformer().transformToType(referencedType, typeVariableByPsiResolver)); + typeParameterDescriptor.addUpperBound(semanticServices.getTypeTransformer().transformToType(referencedType, JavaTypeTransformer.TypeUsage.UPPER_BOUND, typeVariableByPsiResolver)); } } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java index 4ae8fbafcca..c1aa87085a1 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java @@ -80,12 +80,12 @@ public class JavaTypeTransformer { PsiType bound = wildcardType.getBound(); assert bound != null; - return new TypeProjection(variance, transformToType(bound, typeVariableByPsiResolver)); + return new TypeProjection(variance, transformToType(bound, TypeUsage.UPPER_BOUND, typeVariableByPsiResolver)); } @Override public TypeProjection visitType(PsiType type) { - return new TypeProjection(transformToType(type, typeVariableByPsiResolver)); + return new TypeProjection(transformToType(type, TypeUsage.TYPE_ARGUMENT, typeVariableByPsiResolver)); } }); return result; @@ -106,6 +106,12 @@ public class JavaTypeTransformer { @NotNull public JetType transformToType(@NotNull PsiType javaType, + @NotNull final TypeVariableResolver typeVariableResolver) { + return transformToType(javaType, TypeUsage.MEMBER_SIGNATURE_INVARIANT, typeVariableResolver); + } + + @NotNull + public JetType transformToType(@NotNull PsiType javaType, @NotNull final TypeUsage howThisTypeIsUsed, @NotNull final TypeVariableResolver typeVariableResolver) { return javaType.accept(new PsiTypeVisitor() { @Override @@ -119,8 +125,16 @@ public class JavaTypeTransformer { if (psiClass instanceof PsiTypeParameter) { PsiTypeParameter typeParameter = (PsiTypeParameter) psiClass; TypeParameterDescriptor typeParameterDescriptor = typeVariableResolver.getTypeVariable(typeParameter.getName()); -// return TypeUtils.makeNullable(typeParameterDescriptor.getDefaultType()); - return typeParameterDescriptor.getDefaultType(); + + if (howThisTypeIsUsed == TypeUsage.TYPE_ARGUMENT || howThisTypeIsUsed == TypeUsage.UPPER_BOUND) { + // In Java: ArrayList + // In Kotlin: ArrayList, not ArrayList + // nullability will be taken care of in individual member signatures + return typeParameterDescriptor.getDefaultType(); + } + else { + return TypeUtils.makeNullable(typeParameterDescriptor.getDefaultType()); + } } else { JetType jetAnalog = getClassTypesMap().get(psiClass.getQualifiedName()); @@ -211,7 +225,8 @@ public class JavaTypeTransformer { classTypesMap = new HashMap(); for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType(); - classTypesMap.put(jvmPrimitiveType.getWrapper().getFqName(), JetStandardLibrary.getInstance().getNullablePrimitiveJetType(primitiveType)); + classTypesMap.put(jvmPrimitiveType.getWrapper().getFqName(), JetStandardLibrary.getInstance().getNullablePrimitiveJetType( + primitiveType)); } classTypesMap.put("java.lang.Object", JetStandardClasses.getNullableAnyType()); classTypesMap.put("java.lang.String", JetStandardLibrary.getInstance().getNullableStringType()); @@ -234,4 +249,18 @@ public class JavaTypeTransformer { } return classDescriptorMap; } + + /** + * We convert Java types differently, depending on where they occur in the Java code + * This enum encodes the kinds of occurrences + */ + public enum TypeUsage { + // Type T occurs somewhere as a generic argument, e.g.: List or List + TYPE_ARGUMENT, + UPPER_BOUND, + MEMBER_SIGNATURE_COVARIANT, + MEMBER_SIGNATURE_CONTRAVARIANT, + MEMBER_SIGNATURE_INVARIANT, + SUPERTYPE + } } diff --git a/compiler/testData/codegen/regressions/kt529.kt b/compiler/testData/codegen/regressions/kt529.kt index 9f6e87e1334..be27ebbc55c 100644 --- a/compiler/testData/codegen/regressions/kt529.kt +++ b/compiler/testData/codegen/regressions/kt529.kt @@ -61,7 +61,7 @@ class Luhny() { private fun printOneDigit() { while (!buffer.isEmpty()) { - val c = buffer.removeFirst() + val c = buffer.removeFirst().sure() print(c) if (c.isDigit()) { digits.removeFirst() diff --git a/compiler/testData/diagnostics/tests/j+k/UnboxingNulls.jet b/compiler/testData/diagnostics/tests/j+k/UnboxingNulls.jet new file mode 100644 index 00000000000..2512d00714e --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/UnboxingNulls.jet @@ -0,0 +1,13 @@ +// FILE: a/Test.java +package a; + +public class Test { + T t() {return null;} +} +// FILE: b.kt +package a + +fun foo() { + // If this fails, it means that we have broken the rule that Java returns are always nullable + a.Test.t() + 1 +} diff --git a/compiler/testData/readJavaBinaryClass/MethosWithPRefTP.kt b/compiler/testData/readJavaBinaryClass/MethosWithPRefTP.kt index 34aafd20ac9..04c67e7b423 100644 --- a/compiler/testData/readJavaBinaryClass/MethosWithPRefTP.kt +++ b/compiler/testData/readJavaBinaryClass/MethosWithPRefTP.kt @@ -1,5 +1,5 @@ package test final class MethosWithPRefTP() { - fun f(p0: P) = #() + fun f(p0: P?) = #() } diff --git a/compiler/testData/readJavaBinaryClass/MethosWithPRefTP.txt b/compiler/testData/readJavaBinaryClass/MethosWithPRefTP.txt index 8383dae7829..b349f077535 100644 --- a/compiler/testData/readJavaBinaryClass/MethosWithPRefTP.txt +++ b/compiler/testData/readJavaBinaryClass/MethosWithPRefTP.txt @@ -2,5 +2,5 @@ namespace test final class test.MethosWithPRefTP : jet.Any { final /*constructor*/ fun (): test.MethosWithPRefTP - final fun f(/*0*/ p0: P): jet.Tuple0 + final fun f(/*0*/ p0: P?): jet.Tuple0 } diff --git a/libraries/stdlib/src/Arrays.kt b/libraries/stdlib/src/Arrays.kt index 422b5bcce65..2fde990771c 100644 --- a/libraries/stdlib/src/Arrays.kt +++ b/libraries/stdlib/src/Arrays.kt @@ -84,7 +84,7 @@ inline fun FloatArray.copyOf(newLength: Int = this.size) = Arrays.copyOf(this, inline fun DoubleArray.copyOf(newLength: Int = this.size) = Arrays.copyOf(this, newLength).sure() inline fun CharArray.copyOf(newLength: Int = this.size) = Arrays.copyOf(this, newLength).sure() -inline fun Array.copyOf(newLength: Int = this.size) : Array = Arrays.copyOf(this, newLength).sure() +inline fun Array.copyOf(newLength: Int = this.size) : Array = Arrays.copyOf(this as Array, newLength) as Array inline fun BooleanArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to).sure() inline fun ByteArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to).sure() @@ -95,7 +95,7 @@ inline fun FloatArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(thi inline fun DoubleArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to).sure() inline fun CharArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to).sure() -inline fun Array.copyOfRange(from: Int, to: Int) : Array = Arrays.copyOfRange(this, from, to).sure() +inline fun Array.copyOfRange(from: Int, to: Int) : Array = Arrays.copyOfRange(this as Array, from, to) as Array inline val ByteArray.inputStream : ByteArrayInputStream get() = ByteArrayInputStream(this) diff --git a/libraries/stdlib/src/Standard.kt b/libraries/stdlib/src/Standard.kt index c575a484de6..22915330b50 100644 --- a/libraries/stdlib/src/Standard.kt +++ b/libraries/stdlib/src/Standard.kt @@ -10,7 +10,7 @@ import java.util.TreeSet /** Helper to make jet.Iterator usable in for */ -inline fun jet.Iterator.iterator() = this +inline fun Iterator.iterator() = this /** Helper to make java.util.Iterator usable in for @@ -24,7 +24,7 @@ fun java.util.Enumeration.iterator(): Iterator = object: Iterat override val hasNext: Boolean get() = hasMoreElements() - override fun next() = nextElement() + override fun next() = nextElement().sure() } /*