Process raw types during erasion properly

^KT-46670 Fixed
^KT-46476 Fixed
This commit is contained in:
Victor Petukhov
2021-05-14 18:57:59 +03:00
parent 570d860217
commit 0d6764efc5
14 changed files with 174 additions and 7 deletions
@@ -21304,6 +21304,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedTypeArguments.kt");
}
@Test
@TestMetadata("superTypeErasion.kt")
public void testSuperTypeErasion() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/superTypeErasion.kt");
}
@Test
@TestMetadata("typeEnhancement.kt")
public void testTypeEnhancement() throws Exception {
@@ -21304,6 +21304,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedTypeArguments.kt");
}
@Test
@TestMetadata("superTypeErasion.kt")
public void testSuperTypeErasion() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/superTypeErasion.kt");
}
@Test
@TestMetadata("typeEnhancement.kt")
public void testTypeEnhancement() throws Exception {
@@ -27248,6 +27248,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/platformTypes/kt14989.kt");
}
@Test
@TestMetadata("rawTypeWithNestedClass.kt")
public void testRawTypeWithNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/rawTypeWithNestedClass.kt");
}
@Test
@TestMetadata("specializedMapFull.kt")
public void testSpecializedMapFull() throws Exception {
@@ -27260,6 +27266,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/platformTypes/specializedMapPut.kt");
}
@Test
@TestMetadata("stopComputingOnInterdependentTypeParameters.kt")
public void testStopComputingOnInterdependentTypeParameters() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/stopComputingOnInterdependentTypeParameters.kt");
}
@Test
@TestMetadata("unsafeNullCheck.kt")
public void testUnsafeNullCheck() throws Exception {
@@ -0,0 +1,17 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: OCNewFileActionBase.java
public class OCNewFileActionBase<T extends OCNewFileActionBase<T>.CreateFileDialogBase> {
public class CreateFileDialogBase { }
static OCNewFileActionBase get() { return new OCNewFileActionBase(); }
}
// FILE: main.kt
fun box(): String {
// Before changes in raw types computation: (OCNewFileActionBase<OCNewFileActionBase<*>.CreateFileDialogBase!>..OCNewFileActionBase<out OCNewFileActionBase<*>.CreateFileDialogBase!>?)
// After that: raw (OCNewFileActionBase<*>..OCNewFileActionBase<*>?)
val x = OCNewFileActionBase.get()
return "OK"
}
@@ -0,0 +1,29 @@
// TARGET_BACKEND: JVM
// FILE: AbstractMessageLite.java
public abstract class AbstractMessageLite<
MessageType extends AbstractMessageLite<MessageType, BuilderType>,
BuilderType extends AbstractMessageLite.Builder<MessageType, BuilderType>>
{
public void writeDelimitedTo() {}
public abstract static class Builder<
MessageType extends AbstractMessageLite<MessageType, BuilderType>,
BuilderType extends Builder<MessageType, BuilderType>>
{}
}
// FILE: H.java
public class H extends AbstractMessageLite {}
// FILE: test.kt
fun f(h: H) {
h.writeDelimitedTo()
}
fun box(): String {
f(H())
return "OK"
}
@@ -0,0 +1,26 @@
package
public fun f(/*0*/ h: H): kotlin.Unit
public abstract class AbstractMessageLite</*0*/ MessageType : AbstractMessageLite<MessageType!, BuilderType!>!, /*1*/ BuilderType : AbstractMessageLite.Builder<MessageType!, BuilderType!>!> {
public constructor AbstractMessageLite</*0*/ MessageType : AbstractMessageLite<MessageType!, BuilderType!>!, /*1*/ BuilderType : AbstractMessageLite.Builder<MessageType!, BuilderType!>!>()
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
public open fun writeDelimitedTo(): kotlin.Unit
public abstract class Builder</*0*/ MessageType : AbstractMessageLite<MessageType!, BuilderType!>!, /*1*/ BuilderType : AbstractMessageLite.Builder<MessageType!, BuilderType!>!> {
public constructor Builder</*0*/ MessageType : AbstractMessageLite<MessageType!, BuilderType!>!, /*1*/ BuilderType : AbstractMessageLite.Builder<MessageType!, BuilderType!>!>()
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
}
}
public open class H : AbstractMessageLite<(raw) *, (raw) *> {
public constructor H()
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
public open override /*1*/ /*fake_override*/ fun writeDelimitedTo(): kotlin.Unit
}
@@ -0,0 +1,14 @@
// FIR_IDENTICAL
// FILE: Test.java
class BaseOperation<T extends Bar, L extends Foo<T>> {}
class Foo<E extends Bar> { }
class Bar {}
public class Test extends BaseOperation {}
// FILE: main.kt
fun main() {
val x = Test()
}
@@ -0,0 +1,10 @@
package
public fun main(): kotlin.Unit
public open class Test : BaseOperation<(raw) Bar!, (raw) Foo<Bar!>!> {
public constructor Test()
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
}
@@ -21310,6 +21310,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/substituteSeveralOtherErasedTypeArguments.kt");
}
@Test
@TestMetadata("superTypeErasion.kt")
public void testSuperTypeErasion() throws Exception {
runTest("compiler/testData/diagnostics/tests/platformTypes/rawTypes/superTypeErasion.kt");
}
@Test
@TestMetadata("typeEnhancement.kt")
public void testTypeEnhancement() throws Exception {
@@ -27224,6 +27224,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/platformTypes/kt14989.kt");
}
@Test
@TestMetadata("rawTypeWithNestedClass.kt")
public void testRawTypeWithNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/rawTypeWithNestedClass.kt");
}
@Test
@TestMetadata("specializedMapFull.kt")
public void testSpecializedMapFull() throws Exception {
@@ -27236,6 +27242,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/platformTypes/specializedMapPut.kt");
}
@Test
@TestMetadata("stopComputingOnInterdependentTypeParameters.kt")
public void testStopComputingOnInterdependentTypeParameters() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/stopComputingOnInterdependentTypeParameters.kt");
}
@Test
@TestMetadata("unsafeNullCheck.kt")
public void testUnsafeNullCheck() throws Exception {
@@ -27248,6 +27248,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/platformTypes/kt14989.kt");
}
@Test
@TestMetadata("rawTypeWithNestedClass.kt")
public void testRawTypeWithNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/rawTypeWithNestedClass.kt");
}
@Test
@TestMetadata("specializedMapFull.kt")
public void testSpecializedMapFull() throws Exception {
@@ -27260,6 +27266,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/platformTypes/specializedMapPut.kt");
}
@Test
@TestMetadata("stopComputingOnInterdependentTypeParameters.kt")
public void testStopComputingOnInterdependentTypeParameters() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/stopComputingOnInterdependentTypeParameters.kt");
}
@Test
@TestMetadata("unsafeNullCheck.kt")
public void testUnsafeNullCheck() throws Exception {
@@ -23096,6 +23096,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/platformTypes/kt14989.kt");
}
@TestMetadata("rawTypeWithNestedClass.kt")
public void testRawTypeWithNestedClass() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/rawTypeWithNestedClass.kt");
}
@TestMetadata("specializedMapFull.kt")
public void testSpecializedMapFull() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/specializedMapFull.kt");
@@ -23106,6 +23111,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/platformTypes/specializedMapPut.kt");
}
@TestMetadata("stopComputingOnInterdependentTypeParameters.kt")
public void testStopComputingOnInterdependentTypeParameters() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/stopComputingOnInterdependentTypeParameters.kt");
}
@TestMetadata("unsafeNullCheck.kt")
public void testUnsafeNullCheck() throws Exception {
runTest("compiler/testData/codegen/box/platformTypes/unsafeNullCheck.kt");
@@ -315,6 +315,7 @@ data class JavaTypeAttributes(
val upperBoundOfTypeParameter: TypeParameterDescriptor? = null
) {
fun withFlexibility(flexibility: JavaTypeFlexibility) = copy(flexibility = flexibility)
fun withTypeParameter(upperBoundOfTypeParameter: TypeParameterDescriptor) = copy(upperBoundOfTypeParameter = upperBoundOfTypeParameter)
}
enum class JavaTypeFlexibility {
@@ -346,6 +347,8 @@ internal fun TypeParameterDescriptor.getErasedUpperBound(
): KotlinType {
if (this === typeAttr.upperBoundOfTypeParameter) return defaultValue()
val newTypeAttr = if (typeAttr.upperBoundOfTypeParameter == null) typeAttr.withTypeParameter(this) else typeAttr
/*
* We should do erasure of containing type parameters with their erasure to avoid creating inconsistent types.
* E.g. for `class Foo<T: Foo<B>, B>`, we'd have erasure for lower bound: Foo<Foo<*>, Any>,
@@ -353,12 +356,16 @@ internal fun TypeParameterDescriptor.getErasedUpperBound(
* So we should substitute erasure of the corresponding type parameter: `Foo<Foo<Any>, Any>` or `Foo<Foo<*>, *>`.
*/
val erasedUpperBounds = defaultType.extractTypeParametersFromUpperBounds(typeAttr.upperBoundOfTypeParameter).associate {
it.typeConstructor to RawSubstitution.computeProjection(
this,
// if erasure happens due to invalid arguments number, use star projections instead
if (isRaw) typeAttr else typeAttr.withFlexibility(INFLEXIBLE),
it.getErasedUpperBound(isRaw, typeAttr)
)
val boundProjection = if (it !== typeAttr.upperBoundOfTypeParameter) {
RawSubstitution.computeProjection(
it,
// if erasure happens due to invalid arguments number, use star projections instead
if (isRaw) typeAttr else typeAttr.withFlexibility(INFLEXIBLE),
if (it !== typeAttr.upperBoundOfTypeParameter) it.getErasedUpperBound(isRaw, newTypeAttr) else it.starProjectionType()
)
} else makeStarProjection(it, typeAttr)
it.typeConstructor to boundProjection
}
val erasedUpperBoundsSubstitutor = TypeSubstitutor.create(TypeConstructorSubstitution.createByConstructorsMap(erasedUpperBounds))
@@ -232,7 +232,7 @@ private fun KotlinType.containsSelfTypeParameter(
val typeParameters = (constructor.declarationDescriptor as? ClassifierDescriptorWithTypeParameters)?.declaredTypeParameters
return arguments.withIndex().any { (i, argument) ->
val typeParameter = typeParameters?.get(i)
val typeParameter = typeParameters?.getOrNull(i)
if ((typeParameter != null && typeParameter == upperBoundOfTypeParameter) || argument.isStarProjection) return@any false
argument.type.containsSelfTypeParameter(baseConstructor, upperBoundOfTypeParameter)
}