diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index e5c111460fc..acf3ec4799e 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -14189,6 +14189,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti public void testSubstitutionIntoInnerClass() throws Exception { 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 diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt index f637d19717a..9a7aed50205 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/NewTypeSubstitutor.kt @@ -32,6 +32,19 @@ interface NewTypeSubstitutor : TypeSubstitutorMarker { 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? = when (type) { is SimpleType -> substitute(type, keepAnnotation, runCapturedChecks) @@ -40,6 +53,9 @@ interface NewTypeSubstitutor : TypeSubstitutorMarker { } else { val lowerBound = substitute(type.lowerBound, 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) { null } else { @@ -47,7 +63,7 @@ interface NewTypeSubstitutor : TypeSubstitutorMarker { KotlinTypeFactory.flexibleType( lowerBound?.lowerIfFlexible() ?: type.lowerBound, upperBound?.upperIfFlexible() ?: type.upperBound - ).inheritEnhancement(type) + ).wrapEnhancement(enhancement) } } } diff --git a/compiler/testData/diagnostics/tests/inference/substitutions/substitutionOfTypeEnhancement.kt b/compiler/testData/diagnostics/tests/inference/substitutions/substitutionOfTypeEnhancement.kt new file mode 100644 index 00000000000..4119a190bc8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/substitutions/substitutionOfTypeEnhancement.kt @@ -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 { + void register(Class var2, Foo var3) throws IllegalAccessException, InstantiationException { + var3.execute(var2.newInstance()); + } +} + +// FILE: Foo.java + +@NonNullApi +public interface Foo { + 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() + } + } +} diff --git a/compiler/testData/diagnostics/tests/inference/substitutions/substitutionOfTypeEnhancement.txt b/compiler/testData/diagnostics/tests/inference/substitutions/substitutionOfTypeEnhancement.txt new file mode 100644 index 00000000000..ff32d607d69 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/substitutions/substitutionOfTypeEnhancement.txt @@ -0,0 +1,39 @@ +package + +public fun main(): kotlin.Unit + +@NonNullApi public interface Foo { + 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 register(/*0*/ var2: java.lang.Class!, /*1*/ var3: Foo!): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 06d706e40c3..74f5057f586 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -14195,6 +14195,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { public void testSubstitutionIntoInnerClass() throws Exception { 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