Fix false positive unreachable code in case of Nothing!-typed calls

Note, that this change potentially has some other effects in corner cases
(like the changed test data that is rather sensible because `bar`
in the example is not effectively projected out and can be called
with nulls)

Probably, we need to consider rewriting all other isSomeType methods
in KotlinBuiltins, but now it seems to be a rather dangerous change

 #KT-16424 Fixed
This commit is contained in:
Denis Zharkov
2018-03-12 14:57:16 +03:00
parent a7854bc0ce
commit cff88a3f8b
6 changed files with 44 additions and 3 deletions
@@ -17,7 +17,8 @@ fun main(a: A<*>, j: JavaClass<*>, i2: Inv2<*>) {
j.foo() checkType { <!NI;DEBUG_INFO_UNRESOLVED_WITH_TARGET, NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Any?>() }
i2.x checkType { <!NI;DEBUG_INFO_UNRESOLVED_WITH_TARGET, NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Any?>() }
j.<!OI;MEMBER_PROJECTED_OUT!>bar<!>(<!NI;CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>, <!NI;CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!>, <!NI;TYPE_MISMATCH!>Any()<!>)
j.bar(<!NI;CONSTANT_EXPECTED_TYPE_MISMATCH, OI;CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>, <!NI;CONSTANT_EXPECTED_TYPE_MISMATCH, OI;CONSTANT_EXPECTED_TYPE_MISMATCH!>2<!>, <!NI;TYPE_MISMATCH, OI;TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>Any()<!>)
j.bar(null)
}
// FILE: JavaClass.java
@@ -0,0 +1,17 @@
// FILE: TestClass.java
import org.jetbrains.annotations.Nullable;
public class TestClass {
public <T> T set(@Nullable String key, @Nullable T t) {
return t;
}
}
// FILE: main.kt
fun run() {
val testClass = TestClass()
// inferred as `set<Nothing>()`, return type is Nothing!
testClass.set("test", null)
// Should not be unreachable
run()
}
@@ -0,0 +1,11 @@
package
public fun run(): kotlin.Unit
public open class TestClass {
public constructor TestClass()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open operator fun </*0*/ T : kotlin.Any!> set(/*0*/ @org.jetbrains.annotations.Nullable key: kotlin.String?, /*1*/ @org.jetbrains.annotations.Nullable t: T?): T!
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -12578,6 +12578,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("flexibleNothing.kt")
public void testFlexibleNothing() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/flexibleNothing.kt");
doTest(fileName);
}
@TestMetadata("genericConstructorWithMultipleBounds.kt")
public void testGenericConstructorWithMultipleBounds() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/genericConstructorWithMultipleBounds.kt");
@@ -12578,6 +12578,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
doTest(fileName);
}
@TestMetadata("flexibleNothing.kt")
public void testFlexibleNothing() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/flexibleNothing.kt");
doTest(fileName);
}
@TestMetadata("genericConstructorWithMultipleBounds.kt")
public void testGenericConstructorWithMultipleBounds() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/genericConstructorWithMultipleBounds.kt");
@@ -976,12 +976,12 @@ public abstract class KotlinBuiltIns {
public static boolean isNothing(@NotNull KotlinType type) {
return isNothingOrNullableNothing(type)
&& !type.isMarkedNullable();
&& !TypeUtils.isNullableType(type);
}
public static boolean isNullableNothing(@NotNull KotlinType type) {
return isNothingOrNullableNothing(type)
&& type.isMarkedNullable();
&& TypeUtils.isNullableType(type);
}
public static boolean isNothingOrNullableNothing(@NotNull KotlinType type) {