From c74a0a62cc40975fc47c9719a90750837613caac Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Sat, 12 Nov 2011 20:29:38 +0400 Subject: [PATCH] KT-313 Bug in substitutions in a function returning its type parameter T --- .../jet/lang/descriptors/TypeParameterDescriptor.java | 2 +- .../org/jetbrains/jet/lang/resolve/TypeResolver.java | 2 +- .../org/jetbrains/jet/lang/types/JetTypeChecker.java | 4 +++- .../org/jetbrains/jet/lang/types/TypeSubstitutor.java | 2 +- .../src/org/jetbrains/jet/lang/types/TypeUtils.java | 4 ++-- .../lang/types/inference/ConstraintSystemImpl.java | 11 +++++++---- .../testData/checkerWithErrorTypes/full/Variance.jet | 4 ++-- .../checkerWithErrorTypes/full/regression/kt313.jet | 11 +++++++++++ compiler/testData/codegen/regressions/kt326.jet | 4 ++-- compiler/testData/codegen/traits/stdlib.jet | 6 +++--- .../tests/org/jetbrains/jet/codegen/ArrayGenTest.java | 2 +- idea/testData/checker/Variance.jet | 4 ++-- 12 files changed, 36 insertions(+), 20 deletions(-) create mode 100644 compiler/testData/checkerWithErrorTypes/full/regression/kt313.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java index 536d0e11600..d02bbb786af 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java @@ -144,7 +144,7 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement defaultType = new JetTypeImpl( Collections.emptyList(), getTypeConstructor(), - TypeUtils.hasNullableBound(this), + TypeUtils.hasNullableLowerBound(this), Collections.emptyList(), new LazyScopeAdapter(new LazyValue() { @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index 012932b4653..5fd39256dfe 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -78,7 +78,7 @@ public class TypeResolver { result[0] = new JetTypeImpl( annotations, typeParameterDescriptor.getTypeConstructor(), - nullable || TypeUtils.hasNullableBound(typeParameterDescriptor), + nullable || TypeUtils.hasNullableLowerBound(typeParameterDescriptor), Collections.emptyList(), getScopeForTypeParameter(typeParameterDescriptor) ); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeChecker.java index 6573f54fc19..d06f37c4841 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeChecker.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeChecker.java @@ -97,12 +97,14 @@ public class JetTypeChecker { if (!supertype.isNullable() && subtype.isNullable()) { return false; } + subtype = TypeUtils.makeNotNullable(subtype); + supertype = TypeUtils.makeNotNullable(supertype); if (JetStandardClasses.isNothingOrNullableNothing(subtype)) { return true; } @Nullable JetType closestSupertype = findCorrespondingSupertype(subtype, supertype); if (closestSupertype == null) { - if (!constraintBuilder.noCorrespondingSupertype(subtype, supertype)) return false; + return constraintBuilder.noCorrespondingSupertype(subtype, supertype); // if this returns true, there still isn't any supertype to continue with } return checkSubtypeForTheSameConstructor(closestSupertype, supertype); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java index 48699139afd..dac071017cd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java @@ -130,7 +130,7 @@ public class TypeSubstitutor { if (value != null) { assert constructor.getDeclarationDescriptor() instanceof TypeParameterDescriptor; - return substitutionResult((TypeParameterDescriptor) constructor.getDeclarationDescriptor(), howThisTypeIsUsed, Variance.INVARIANT, value).getType(); + return TypeUtils.makeNullableIfNeeded(substitutionResult((TypeParameterDescriptor) constructor.getDeclarationDescriptor(), howThisTypeIsUsed, Variance.INVARIANT, value).getType(), type.isNullable()); // if (!allows(howThisTypeIsUsed, value.getProjectionKind())) { // throw new SubstitutionException("!!" + value.toString()); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java index cb6360ab21d..6304adf84db 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -385,8 +385,8 @@ public class TypeUtils { return result; } - public static boolean hasNullableBound(@NotNull TypeParameterDescriptor typeParameterDescriptor) { - for (JetType bound : typeParameterDescriptor.getUpperBounds()) { + public static boolean hasNullableLowerBound(@NotNull TypeParameterDescriptor typeParameterDescriptor) { + for (JetType bound : typeParameterDescriptor.getLowerBounds()) { if (bound.isNullable()) { return true; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java index db786b2b28d..e693c3dddf1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/inference/ConstraintSystemImpl.java @@ -209,7 +209,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) { boolean result = delegate.noCorrespondingSupertype(subtype, supertype); if (!result) { - println("-- " + subtype + " has supertype corresponding to " + supertype); + println("-- " + subtype + " has no supertype corresponding to " + supertype); } return result; } @@ -273,9 +273,12 @@ public class ConstraintSystemImpl implements ConstraintSystem { DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); if (declarationDescriptor instanceof TypeParameterDescriptor) { TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor; - UnknownType unknownType = unknownTypes.get(typeParameterDescriptor); - if (unknownType != null) { - return unknownType; + // Checking that this is not a T?, but exactly T + if (typeParameterDescriptor.getDefaultType().isNullable() == type.isNullable()) { + UnknownType unknownType = unknownTypes.get(typeParameterDescriptor); + if (unknownType != null) { + return unknownType; + } } } diff --git a/compiler/testData/checkerWithErrorTypes/full/Variance.jet b/compiler/testData/checkerWithErrorTypes/full/Variance.jet index 9b6531ffd02..0607a6f0a13 100644 --- a/compiler/testData/checkerWithErrorTypes/full/Variance.jet +++ b/compiler/testData/checkerWithErrorTypes/full/Variance.jet @@ -18,8 +18,8 @@ fun foo(c: Consumer, p: Producer, u: Usual) { } //Arrays copy example -class Array(val length : Int) { - fun get(index : Int) : T { return null } +class Array(val length : Int, val t : T) { + fun get(index : Int) : T { return t } fun set(index : Int, value : T) { /* ... */ } } diff --git a/compiler/testData/checkerWithErrorTypes/full/regression/kt313.jet b/compiler/testData/checkerWithErrorTypes/full/regression/kt313.jet new file mode 100644 index 00000000000..d22f0dc4f2e --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/full/regression/kt313.jet @@ -0,0 +1,11 @@ +// KT-313 Bug in substitutions in a function returning its type parameter T + +fun Iterable.join(separator : String?) : String { + return separator.npe() +} + +fun T?.npe() : T { + if (this == null) + throw NullPointerException() + return this; +} diff --git a/compiler/testData/codegen/regressions/kt326.jet b/compiler/testData/codegen/regressions/kt326.jet index 8afc31e7eab..3d9b4ad8e54 100644 --- a/compiler/testData/codegen/regressions/kt326.jet +++ b/compiler/testData/codegen/regressions/kt326.jet @@ -1,7 +1,7 @@ namespace test class List(len: Int) { - val a : Array = Array(len) + val a : Array = Array(len) fun reverse() { var i = 0 @@ -29,7 +29,7 @@ fun box() : String { val c = List>(1) c.a[0] = Array(4,{-1}) - println(c.a[0].size) + println(c.a[0]?.size) val e = List(5) e.a[0] = 0 diff --git a/compiler/testData/codegen/traits/stdlib.jet b/compiler/testData/codegen/traits/stdlib.jet index aa9fe5d5072..af0db549b40 100644 --- a/compiler/testData/codegen/traits/stdlib.jet +++ b/compiler/testData/codegen/traits/stdlib.jet @@ -36,8 +36,8 @@ trait WriteOnlyArray : ISized { } } -class MutableArray(length: Int) : ReadOnlyArray, WriteOnlyArray { - private val array = Array(length) +class MutableArray(length: Int, init : fun(Int) : T) : ReadOnlyArray, WriteOnlyArray { + private val array = Array(length, init) override fun get(index : Int) : T = array[index] override fun set(index : Int, value : T) : Unit { array[index] = value } @@ -47,7 +47,7 @@ class MutableArray(length: Int) : ReadOnlyArray, WriteOnlyArray { } fun box() : String { - var a = MutableArray (4) + var a = MutableArray (4, {0}) a [0] = 10 a.set(1, 2, 13) a [3] = 40 diff --git a/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java index de66903a8e9..7a1b926962c 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ArrayGenTest.java @@ -38,7 +38,7 @@ public class ArrayGenTest extends CodegenTestCase { } public void testCreateMultiGenerics () throws Exception { - loadText("class L() { val a = Array(5) } fun foo() = L.a"); + loadText("class L() { val a = Array(5) } fun foo() = L.a"); System.out.println(generateToText()); Method foo = generateFunction(); Object invoke = foo.invoke(null); diff --git a/idea/testData/checker/Variance.jet b/idea/testData/checker/Variance.jet index 0f27cbc73ff..0d173e86dc8 100644 --- a/idea/testData/checker/Variance.jet +++ b/idea/testData/checker/Variance.jet @@ -18,8 +18,8 @@ fun foo(c: Consumer, p: Producer, u: Usual) { } //Arrays copy example -class Array(val length : Int) { - fun get(index : Int) : T { return null } +class Array(val length : Int, val t : T) { + fun get(index : Int) : T { return t } fun set(index : Int, value : T) { /* ... */ } }