Do substitution of a type enhancement, not only lower and upper bounds
^KT-44439 Fixed
This commit is contained in:
+6
@@ -14189,6 +14189,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
public void testSubstitutionIntoInnerClass() throws Exception {
|
public void testSubstitutionIntoInnerClass() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/substitutions/substitutionIntoInnerClass.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/substitutions/substitutionIntoInnerClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutionOfTypeEnhancement.kt")
|
||||||
|
public void testSubstitutionOfTypeEnhancement() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/substitutions/substitutionOfTypeEnhancement.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+17
-1
@@ -32,6 +32,19 @@ interface NewTypeSubstitutor : TypeSubstitutorMarker {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun substituteTypeEnhancement(
|
||||||
|
enhancementType: KotlinType,
|
||||||
|
keepAnnotation: Boolean,
|
||||||
|
runCapturedChecks: Boolean
|
||||||
|
) = when (val type = enhancementType.unwrap()) {
|
||||||
|
is SimpleType -> substitute(type, keepAnnotation, runCapturedChecks) ?: enhancementType
|
||||||
|
is FlexibleType -> {
|
||||||
|
val substitutedLowerBound = substitute(type.lowerBound, keepAnnotation, runCapturedChecks) ?: type.lowerBound
|
||||||
|
val substitutedUpperBound = substitute(type.upperBound, keepAnnotation, runCapturedChecks) ?: type.upperBound
|
||||||
|
KotlinTypeFactory.flexibleType(substitutedLowerBound.lowerIfFlexible(), substitutedUpperBound.upperIfFlexible())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun substitute(type: UnwrappedType, keepAnnotation: Boolean, runCapturedChecks: Boolean): UnwrappedType? =
|
private fun substitute(type: UnwrappedType, keepAnnotation: Boolean, runCapturedChecks: Boolean): UnwrappedType? =
|
||||||
when (type) {
|
when (type) {
|
||||||
is SimpleType -> substitute(type, keepAnnotation, runCapturedChecks)
|
is SimpleType -> substitute(type, keepAnnotation, runCapturedChecks)
|
||||||
@@ -40,6 +53,9 @@ interface NewTypeSubstitutor : TypeSubstitutorMarker {
|
|||||||
} else {
|
} else {
|
||||||
val lowerBound = substitute(type.lowerBound, keepAnnotation, runCapturedChecks)
|
val lowerBound = substitute(type.lowerBound, keepAnnotation, runCapturedChecks)
|
||||||
val upperBound = substitute(type.upperBound, keepAnnotation, runCapturedChecks)
|
val upperBound = substitute(type.upperBound, keepAnnotation, runCapturedChecks)
|
||||||
|
val enhancement =
|
||||||
|
if (type is TypeWithEnhancement) substituteTypeEnhancement(type, keepAnnotation, runCapturedChecks) else null
|
||||||
|
|
||||||
if (lowerBound == null && upperBound == null) {
|
if (lowerBound == null && upperBound == null) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
@@ -47,7 +63,7 @@ interface NewTypeSubstitutor : TypeSubstitutorMarker {
|
|||||||
KotlinTypeFactory.flexibleType(
|
KotlinTypeFactory.flexibleType(
|
||||||
lowerBound?.lowerIfFlexible() ?: type.lowerBound,
|
lowerBound?.lowerIfFlexible() ?: type.lowerBound,
|
||||||
upperBound?.upperIfFlexible() ?: type.upperBound
|
upperBound?.upperIfFlexible() ?: type.upperBound
|
||||||
).inheritEnhancement(type)
|
).wrapEnhancement(enhancement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+55
@@ -0,0 +1,55 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// FULL_JDK
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// WITH_REFLECT
|
||||||
|
|
||||||
|
// FILE: NonNullApi.java
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target({ElementType.TYPE, ElementType.PACKAGE})
|
||||||
|
@javax.annotation.Nonnull
|
||||||
|
@javax.annotation.meta.TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})
|
||||||
|
@Documented
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface NonNullApi { }
|
||||||
|
|
||||||
|
// FILE: Task2.java
|
||||||
|
|
||||||
|
public class Task2 implements Task {
|
||||||
|
void foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Test.java
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
<T extends Task> void register(Class<T> var2, Foo<? super T> var3) throws IllegalAccessException, InstantiationException {
|
||||||
|
var3.execute(var2.newInstance());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Foo.java
|
||||||
|
|
||||||
|
@NonNullApi
|
||||||
|
public interface Foo<T> {
|
||||||
|
void execute(T t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Task.java
|
||||||
|
|
||||||
|
public interface Task {}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
Test().register(Task2::class.java) { // before the fix, type parameter's type leaked here (type of `it` is `T`)
|
||||||
|
it.foo()
|
||||||
|
it.apply {
|
||||||
|
foo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+39
@@ -0,0 +1,39 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun main(): kotlin.Unit
|
||||||
|
|
||||||
|
@NonNullApi public interface Foo</*0*/ T : kotlin.Any!> {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract fun execute(/*0*/ t: T!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.FILE}) @javax.annotation.Nonnull /* annotation class not found */ @javax.annotation.meta.TypeQualifierDefault(value = {ElementType.METHOD, ElementType.PARAMETER}) /* annotation class not found */ @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final annotation class NonNullApi : kotlin.Annotation {
|
||||||
|
public constructor NonNullApi()
|
||||||
|
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 interface Task {
|
||||||
|
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 Task2 : Task {
|
||||||
|
public constructor Task2()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public/*package*/ open fun foo(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class Test {
|
||||||
|
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/*package*/ open fun </*0*/ T : Task!> register(/*0*/ var2: java.lang.Class<T!>!, /*1*/ var3: Foo<in T!>!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
Generated
+6
@@ -14195,6 +14195,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
public void testSubstitutionIntoInnerClass() throws Exception {
|
public void testSubstitutionIntoInnerClass() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/substitutions/substitutionIntoInnerClass.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/substitutions/substitutionIntoInnerClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("substitutionOfTypeEnhancement.kt")
|
||||||
|
public void testSubstitutionOfTypeEnhancement() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/substitutions/substitutionOfTypeEnhancement.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
Reference in New Issue
Block a user