Generic type with Nothing in arguments compiles to raw type
This commit is contained in:
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.codegen.state;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import kotlin.CollectionsKt;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.BuiltinsPackageFragment;
|
||||
@@ -595,6 +597,11 @@ public class JetTypeMapper {
|
||||
boolean projectionsAllowed
|
||||
) {
|
||||
if (signatureVisitor != null) {
|
||||
if (hasNothingInArguments(jetType)) {
|
||||
signatureVisitor.writeAsmType(asmType);
|
||||
return;
|
||||
}
|
||||
|
||||
signatureVisitor.writeClassBegin(asmType);
|
||||
|
||||
List<TypeProjection> arguments = jetType.getArguments();
|
||||
@@ -622,6 +629,24 @@ public class JetTypeMapper {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasNothingInArguments(JetType jetType) {
|
||||
boolean hasNothingInArguments = CollectionsKt.any(jetType.getArguments(), new Function1<TypeProjection, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(TypeProjection projection) {
|
||||
return KotlinBuiltIns.isNothingOrNullableNothing(projection.getType());
|
||||
}
|
||||
});
|
||||
|
||||
if (hasNothingInArguments) return true;
|
||||
|
||||
return CollectionsKt.any(jetType.getArguments(), new Function1<TypeProjection, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(TypeProjection projection) {
|
||||
return !projection.isStarProjection() && hasNothingInArguments(projection.getType());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static Variance getEffectiveVariance(Variance parameterVariance, Variance projectionKind, Variance howThisTypeIsUsed) {
|
||||
// Return type must not contain wildcards
|
||||
if (howThisTypeIsUsed == Variance.OUT_VARIANCE) return projectionKind;
|
||||
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
package foo
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class A<T>
|
||||
class B<T, Y, U>
|
||||
|
||||
class TestRaw {
|
||||
val a1: A<Nothing> = A()
|
||||
val a2: A<Nothing>? = A()
|
||||
val a3: A<Nothing?> = A()
|
||||
val a4: A<Nothing?>? = A()
|
||||
|
||||
var b1: B<Nothing, Int, Int> = B()
|
||||
var b2: B<String, Nothing, Int> = B()
|
||||
|
||||
val l: List<Nothing> = listOf()
|
||||
|
||||
fun test1(a: A<Nothing?>, b: B<Nothing, String, A<Int>>): A<Nothing>? = A()
|
||||
fun test2(a: A<Nothing?>?, b: B<Int, String, Nothing>): B<Int?, Int?, Nothing?> = B()
|
||||
}
|
||||
|
||||
class TestNotRaw {
|
||||
val a1: A<String> = A()
|
||||
val a2: A<B<Nothing, Int, Int>>? = A()
|
||||
val a3: A<Int?> = A()
|
||||
val a4: A<Int?>? = A()
|
||||
|
||||
var b1: B<Int, Int, Int> = B()
|
||||
var b2: B<String, A<String>, Int> = B()
|
||||
|
||||
val l: List<String> = listOf()
|
||||
|
||||
fun test1(a: A<Int?>, b: B<Int, String, A<Int>>): A<Int>? = A()
|
||||
fun test2(a: A<Int>?, b: B<Int, String, A<Nothing>>): B<Int?, Int?, Int> = B()
|
||||
}
|
||||
|
||||
abstract class C<T> {
|
||||
abstract val foo: A<T>
|
||||
abstract fun bar(): A<T>?
|
||||
}
|
||||
|
||||
class C1 : C<Nothing>() {
|
||||
override val foo = A<Nothing>()
|
||||
override fun bar() = foo
|
||||
}
|
||||
class C2 : C<String>() {
|
||||
override val foo = A<String>()
|
||||
override fun bar() = foo
|
||||
}
|
||||
|
||||
fun testAllDeclaredMembers(klass: KClass<*>, expectedIsRaw: Boolean): String? {
|
||||
val clazz = klass.java
|
||||
|
||||
for (it in clazz.declaredFields) {
|
||||
if ((it.type == it.genericType) == expectedIsRaw) return "failed on field '${clazz.simpleName}::${it.name}'"
|
||||
}
|
||||
|
||||
for (m in clazz.declaredMethods) {
|
||||
for (i in m.parameterTypes.indices) {
|
||||
if ((m.parameterTypes[i] == m.genericParameterTypes[i]) == expectedIsRaw) return "failed on type of param#$i of method '${clazz.simpleName}::${m.name}'"
|
||||
}
|
||||
if (m.returnType != Void.TYPE && (m.returnType == m.genericReturnType) == expectedIsRaw) return "failed on return type of method '${clazz.simpleName}::${m.name}'"
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
testAllDeclaredMembers(TestRaw::class, expectedIsRaw = true) ?:
|
||||
testAllDeclaredMembers(TestNotRaw::class, expectedIsRaw = false)?.let { return it }
|
||||
|
||||
if (C1::class.java.superclass != C1::class.java.genericSuperclass) return "failed on C1 superclass"
|
||||
|
||||
if (C2::class.java.superclass == C2::class.java.genericSuperclass) return "failed on C2 superclass"
|
||||
|
||||
testAllDeclaredMembers(C1::class, expectedIsRaw = true) ?:
|
||||
testAllDeclaredMembers(C2::class, expectedIsRaw = false)?.let { return it }
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
class C<T>
|
||||
fun f(p: Nothing, p1: C<Nothing>): Nothing = throw Exception()
|
||||
fun f(p: Nothing, p1: C<Nothing>, p2: C<C<Nothing>>, p3: C<C<Nothing>>?): Nothing = throw Exception()
|
||||
|
||||
// method: _DefaultPackage::f
|
||||
// jvm signature: (Ljava/lang/Void;LC;)Ljava/lang/Void;
|
||||
// generic signature: (Ljava/lang/Void;LC<Ljava/lang/Void;>;)Ljava/lang/Void;
|
||||
// jvm signature: (Ljava/lang/Void;LC;LC;LC;)Ljava/lang/Void;
|
||||
// generic signature: null
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class C<T>
|
||||
fun f(p: Nothing?, p1: C<Nothing?>): Nothing? = throw Exception()
|
||||
fun f(p: Nothing?, p1: C<Nothing?>, p2: C<C<Nothing?>>, p3: C<C<Nothing?>>?): Nothing? = throw Exception()
|
||||
|
||||
// method: _DefaultPackage::f
|
||||
// jvm signature: (Ljava/lang/Void;LC;)Ljava/lang/Void;
|
||||
// generic signature: (Ljava/lang/Void;LC<Ljava/lang/Void;>;)Ljava/lang/Void;
|
||||
// jvm signature: (Ljava/lang/Void;LC;LC;LC;)Ljava/lang/Void;
|
||||
// generic signature: null
|
||||
|
||||
+15
@@ -4643,6 +4643,21 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/typeMapping")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class TypeMapping extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInTypeMapping() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/typeMapping"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("genericTypeWithNothing.kt")
|
||||
public void testGenericTypeWithNothing() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/typeMapping/genericTypeWithNothing.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/vararg")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user