KT-987 Unboxing nulls
#KT-987 Fixed
This commit is contained in:
@@ -174,7 +174,7 @@
|
|||||||
<chmod dir="${kotlin-home}/bin" includes="*" perm="755"/>
|
<chmod dir="${kotlin-home}/bin" includes="*" perm="755"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="dist" depends="init,jarRT,copyKotlinJars,jarJDKHeaders,jarLang,jar,buildToolsJar"/>
|
<target name="dist" depends="init,copyKotlinJars,jar,buildToolsJar,jarJDKHeaders,jarRT,jarLang"/>
|
||||||
|
|
||||||
<target name="doc" depends="dist"/>
|
<target name="doc" depends="dist"/>
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -737,11 +737,11 @@ public class JavaDescriptorResolver {
|
|||||||
typeParameterDescriptor.addUpperBound(JetStandardClasses.getNullableAnyType());
|
typeParameterDescriptor.addUpperBound(JetStandardClasses.getNullableAnyType());
|
||||||
}
|
}
|
||||||
else if (referencedTypes.length == 1) {
|
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 {
|
else {
|
||||||
for (PsiClassType referencedType : referencedTypes) {
|
for (PsiClassType referencedType : referencedTypes) {
|
||||||
typeParameterDescriptor.addUpperBound(semanticServices.getTypeTransformer().transformToType(referencedType, typeVariableByPsiResolver));
|
typeParameterDescriptor.addUpperBound(semanticServices.getTypeTransformer().transformToType(referencedType, JavaTypeTransformer.TypeUsage.UPPER_BOUND, typeVariableByPsiResolver));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-5
@@ -80,12 +80,12 @@ public class JavaTypeTransformer {
|
|||||||
|
|
||||||
PsiType bound = wildcardType.getBound();
|
PsiType bound = wildcardType.getBound();
|
||||||
assert bound != null;
|
assert bound != null;
|
||||||
return new TypeProjection(variance, transformToType(bound, typeVariableByPsiResolver));
|
return new TypeProjection(variance, transformToType(bound, TypeUsage.UPPER_BOUND, typeVariableByPsiResolver));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeProjection visitType(PsiType type) {
|
public TypeProjection visitType(PsiType type) {
|
||||||
return new TypeProjection(transformToType(type, typeVariableByPsiResolver));
|
return new TypeProjection(transformToType(type, TypeUsage.TYPE_ARGUMENT, typeVariableByPsiResolver));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
@@ -106,6 +106,12 @@ public class JavaTypeTransformer {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JetType transformToType(@NotNull PsiType javaType,
|
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) {
|
@NotNull final TypeVariableResolver typeVariableResolver) {
|
||||||
return javaType.accept(new PsiTypeVisitor<JetType>() {
|
return javaType.accept(new PsiTypeVisitor<JetType>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -119,8 +125,16 @@ public class JavaTypeTransformer {
|
|||||||
if (psiClass instanceof PsiTypeParameter) {
|
if (psiClass instanceof PsiTypeParameter) {
|
||||||
PsiTypeParameter typeParameter = (PsiTypeParameter) psiClass;
|
PsiTypeParameter typeParameter = (PsiTypeParameter) psiClass;
|
||||||
TypeParameterDescriptor typeParameterDescriptor = typeVariableResolver.getTypeVariable(typeParameter.getName());
|
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<T>
|
||||||
|
// In Kotlin: ArrayList<T>, not ArrayList<T?>
|
||||||
|
// nullability will be taken care of in individual member signatures
|
||||||
|
return typeParameterDescriptor.getDefaultType();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return TypeUtils.makeNullable(typeParameterDescriptor.getDefaultType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
JetType jetAnalog = getClassTypesMap().get(psiClass.getQualifiedName());
|
JetType jetAnalog = getClassTypesMap().get(psiClass.getQualifiedName());
|
||||||
@@ -211,7 +225,8 @@ public class JavaTypeTransformer {
|
|||||||
classTypesMap = new HashMap<String, JetType>();
|
classTypesMap = new HashMap<String, JetType>();
|
||||||
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
|
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
|
||||||
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
|
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.Object", JetStandardClasses.getNullableAnyType());
|
||||||
classTypesMap.put("java.lang.String", JetStandardLibrary.getInstance().getNullableStringType());
|
classTypesMap.put("java.lang.String", JetStandardLibrary.getInstance().getNullableStringType());
|
||||||
@@ -234,4 +249,18 @@ public class JavaTypeTransformer {
|
|||||||
}
|
}
|
||||||
return classDescriptorMap;
|
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<T> or List<? extends T>
|
||||||
|
TYPE_ARGUMENT,
|
||||||
|
UPPER_BOUND,
|
||||||
|
MEMBER_SIGNATURE_COVARIANT,
|
||||||
|
MEMBER_SIGNATURE_CONTRAVARIANT,
|
||||||
|
MEMBER_SIGNATURE_INVARIANT,
|
||||||
|
SUPERTYPE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class Luhny() {
|
|||||||
|
|
||||||
private fun printOneDigit() {
|
private fun printOneDigit() {
|
||||||
while (!buffer.isEmpty()) {
|
while (!buffer.isEmpty()) {
|
||||||
val c = buffer.removeFirst()
|
val c = buffer.removeFirst().sure()
|
||||||
print(c)
|
print(c)
|
||||||
if (c.isDigit()) {
|
if (c.isDigit()) {
|
||||||
digits.removeFirst()
|
digits.removeFirst()
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// FILE: a/Test.java
|
||||||
|
package a;
|
||||||
|
|
||||||
|
public class Test<T> {
|
||||||
|
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<Int>.t() <!UNSAFE_INFIX_CALL!>+<!> 1
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
final class MethosWithPRefTP() {
|
final class MethosWithPRefTP() {
|
||||||
fun <erased P> f(p0: P) = #()
|
fun <erased P> f(p0: P?) = #()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ namespace test
|
|||||||
|
|
||||||
final class test.MethosWithPRefTP : jet.Any {
|
final class test.MethosWithPRefTP : jet.Any {
|
||||||
final /*constructor*/ fun <init>(): test.MethosWithPRefTP
|
final /*constructor*/ fun <init>(): 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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 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 CharArray.copyOf(newLength: Int = this.size) = Arrays.copyOf(this, newLength).sure()
|
||||||
|
|
||||||
inline fun <T> Array<T>.copyOf(newLength: Int = this.size) : Array<T> = Arrays.copyOf(this, newLength).sure()
|
inline fun <T> Array<T>.copyOf(newLength: Int = this.size) : Array<T> = Arrays.copyOf(this as Array<T?>, newLength) as Array<T>
|
||||||
|
|
||||||
inline fun BooleanArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to).sure()
|
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()
|
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 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 CharArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to).sure()
|
||||||
|
|
||||||
inline fun <T> Array<T>.copyOfRange(from: Int, to: Int) : Array<T> = Arrays.copyOfRange(this, from, to).sure()
|
inline fun <T> Array<T>.copyOfRange(from: Int, to: Int) : Array<T> = Arrays.copyOfRange(this as Array<T?>, from, to) as Array<T>
|
||||||
|
|
||||||
inline val ByteArray.inputStream : ByteArrayInputStream
|
inline val ByteArray.inputStream : ByteArrayInputStream
|
||||||
get() = ByteArrayInputStream(this)
|
get() = ByteArrayInputStream(this)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.util.TreeSet
|
|||||||
/**
|
/**
|
||||||
Helper to make jet.Iterator usable in for
|
Helper to make jet.Iterator usable in for
|
||||||
*/
|
*/
|
||||||
inline fun <T> jet.Iterator<T>.iterator() = this
|
inline fun <T> Iterator<T>.iterator() = this
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Helper to make java.util.Iterator usable in for
|
Helper to make java.util.Iterator usable in for
|
||||||
@@ -24,7 +24,7 @@ fun <erased T> java.util.Enumeration<T>.iterator(): Iterator<T> = object: Iterat
|
|||||||
override val hasNext: Boolean
|
override val hasNext: Boolean
|
||||||
get() = hasMoreElements()
|
get() = hasMoreElements()
|
||||||
|
|
||||||
override fun next() = nextElement()
|
override fun next() = nextElement().sure()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user