Don't use TypeIntersector when loading generic Java constructors
This is not entirely type-safe but this case is so rare that hardly anyone will be able to spot the change
This commit is contained in:
+18
@@ -0,0 +1,18 @@
|
|||||||
|
// FILE: J.java
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class J {
|
||||||
|
public <T extends Cloneable & Serializable> J(T t) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: K.kt
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
// TODO: report TYPE_MISMATCH here as well
|
||||||
|
fun cloneable(c: Cloneable) = J(c)
|
||||||
|
|
||||||
|
fun serializable(s: Serializable) = J(<!TYPE_MISMATCH!>s<!>)
|
||||||
|
|
||||||
|
fun <T> both(t: T) where T : Cloneable, T : Serializable = J(t)
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ T : kotlin.Cloneable> both(/*0*/ t: T): J where T : java.io.Serializable
|
||||||
|
public fun cloneable(/*0*/ c: kotlin.Cloneable): J
|
||||||
|
public fun serializable(/*0*/ s: java.io.Serializable): J
|
||||||
|
|
||||||
|
public open class J {
|
||||||
|
public constructor J(/*0*/ t: kotlin.Cloneable!)
|
||||||
|
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 override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -9048,6 +9048,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("genericConstructorWithMultipleBounds.kt")
|
||||||
|
public void testGenericConstructorWithMultipleBounds() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/genericConstructorWithMultipleBounds.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("GenericsInSupertypes.kt")
|
@TestMetadata("GenericsInSupertypes.kt")
|
||||||
public void testGenericsInSupertypes() throws Exception {
|
public void testGenericsInSupertypes() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/GenericsInSupertypes.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/GenericsInSupertypes.kt");
|
||||||
|
|||||||
+9
-18
@@ -28,22 +28,16 @@ import org.jetbrains.kotlin.load.java.components.TypeUsage.*
|
|||||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaAnnotations
|
import org.jetbrains.kotlin.load.java.lazy.LazyJavaAnnotations
|
||||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||||
import org.jetbrains.kotlin.load.java.lazy.TypeParameterResolver
|
import org.jetbrains.kotlin.load.java.lazy.TypeParameterResolver
|
||||||
import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeFlexibility.FLEXIBLE_LOWER_BOUND
|
import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeFlexibility.*
|
||||||
import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeFlexibility.FLEXIBLE_UPPER_BOUND
|
|
||||||
import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeFlexibility.INFLEXIBLE
|
|
||||||
import org.jetbrains.kotlin.load.java.structure.*
|
import org.jetbrains.kotlin.load.java.structure.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||||
import org.jetbrains.kotlin.resolve.jvm.PLATFORM_TYPES
|
import org.jetbrains.kotlin.resolve.jvm.PLATFORM_TYPES
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.Variance.INVARIANT
|
import org.jetbrains.kotlin.types.Variance.*
|
||||||
import org.jetbrains.kotlin.types.Variance.IN_VARIANCE
|
|
||||||
import org.jetbrains.kotlin.types.Variance.OUT_VARIANCE
|
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.createProjection
|
import org.jetbrains.kotlin.types.typeUtil.createProjection
|
||||||
import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations
|
import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
private val JAVA_LANG_CLASS_FQ_NAME: FqName = FqName("java.lang.Class")
|
private val JAVA_LANG_CLASS_FQ_NAME: FqName = FqName("java.lang.Class")
|
||||||
|
|
||||||
@@ -168,19 +162,16 @@ class LazyJavaTypeResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We do not memoize the results of this method, because it would consume much memory, and the real gain is little:
|
// We do not memoize the results of this method, because it would consume much memory, and the real gain is little:
|
||||||
// the case this method accounts for is very rare, not point in optimizing it
|
// the case this method accounts for is very rare, no point in optimizing it
|
||||||
private fun getConstructorTypeParameterSubstitute(): KotlinType {
|
private fun getConstructorTypeParameterSubstitute(): KotlinType {
|
||||||
// If a Java-constructor declares its own type parameters, we have no way of directly expressing them in Kotlin,
|
// If a Java constructor declares its own type parameters, we have no way of directly expressing them in Kotlin,
|
||||||
// so we replace them by intersections of their upper bounds
|
// so we replace each type parameter with its representative upper bound (which in Java is also the first bound)
|
||||||
val supertypesJet = HashSet<KotlinType>()
|
val upperBounds = (classifier() as JavaTypeParameter).upperBounds
|
||||||
for (supertype in (classifier() as JavaTypeParameter).getUpperBounds()) {
|
if (upperBounds.isEmpty()) {
|
||||||
supertypesJet.add(transformJavaType(supertype, UPPER_BOUND.toAttributes()))
|
|
||||||
}
|
|
||||||
if (supertypesJet.isEmpty()) {
|
|
||||||
return c.module.builtIns.nullableAnyType
|
return c.module.builtIns.nullableAnyType
|
||||||
}
|
}
|
||||||
return TypeIntersector.intersectTypes(KotlinTypeChecker.DEFAULT, supertypesJet)
|
|
||||||
?: ErrorUtils.createErrorType("Can't intersect upper bounds of " + javaType.getPresentableText())
|
return transformJavaType(upperBounds.first(), UPPER_BOUND.toAttributes())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isRaw(): Boolean {
|
private fun isRaw(): Boolean {
|
||||||
|
|||||||
Reference in New Issue
Block a user