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 extends T>
+ 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 *0*/ P : jet.Any?>f(/*0*/ p0: P): jet.Tuple0
+ final fun *0*/ P : jet.Any?>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()
}
/*