diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index edc9c50b4ea..5271fce5e28 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -16041,6 +16041,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/javaInterop/generics/javaNestedSamInterface.kt"); } + @TestMetadata("kt42825.kt") + public void testKt42825() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/generics/kt42825.kt"); + } + @TestMetadata("propertyVarianceConflict.kt") public void testPropertyVarianceConflict() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/generics/propertyVarianceConflict.kt"); diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeCheckerContext.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeCheckerContext.kt index f18f9e93ecf..e7dfd0f5878 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeCheckerContext.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeCheckerContext.kt @@ -39,6 +39,13 @@ open class IrTypeCheckerContext(override val irBuiltIns: IrBuiltIns) : IrTypeSys ): AbstractTypeCheckerContext = IrTypeCheckerContext(irBuiltIns) override fun KotlinTypeMarker.isUninferredParameter(): Boolean = false + override fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker { + if (this.isSimpleType()) { + return this.asSimpleType()!!.withNullability(nullable) + } else { + error("withNullability for non-simple types is not supported in IR") + } + } override fun captureFromExpression(type: KotlinTypeMarker): KotlinTypeMarker? = error("Captured type is unsupported in IR") diff --git a/compiler/testData/codegen/box/javaInterop/generics/kt42825.kt b/compiler/testData/codegen/box/javaInterop/generics/kt42825.kt new file mode 100644 index 00000000000..d3119ba3161 --- /dev/null +++ b/compiler/testData/codegen/box/javaInterop/generics/kt42825.kt @@ -0,0 +1,23 @@ +// FILE: Processor.java + +public interface Processor { + boolean process(T t); +} + +// FILE: test.kt + +interface PsiModifierListOwner +interface KtClassOrObject { + fun toLightClass(): PsiModifierListOwner? +} + +fun execute(declaration: Any, consumer: Processor) { + when (declaration) { + is KtClassOrObject -> { + val lightClass = declaration.toLightClass() + consumer.process(lightClass) + } + } +} + +fun box(): String = "OK" \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 84627960359..982fbd94a90 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -17441,6 +17441,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/javaInterop/generics/javaNestedSamInterface.kt"); } + @TestMetadata("kt42825.kt") + public void testKt42825() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/generics/kt42825.kt"); + } + @TestMetadata("propertyVarianceConflict.kt") public void testPropertyVarianceConflict() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/generics/propertyVarianceConflict.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 19c32945df6..7aa64fe4dd0 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -17441,6 +17441,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/javaInterop/generics/javaNestedSamInterface.kt"); } + @TestMetadata("kt42825.kt") + public void testKt42825() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/generics/kt42825.kt"); + } + @TestMetadata("propertyVarianceConflict.kt") public void testPropertyVarianceConflict() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/generics/propertyVarianceConflict.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index b7261d7507b..7fdd83dafa7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -16041,6 +16041,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/javaInterop/generics/javaNestedSamInterface.kt"); } + @TestMetadata("kt42825.kt") + public void testKt42825() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/generics/kt42825.kt"); + } + @TestMetadata("propertyVarianceConflict.kt") public void testPropertyVarianceConflict() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/generics/propertyVarianceConflict.kt"); diff --git a/core/compiler.common/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt b/core/compiler.common/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt index 992c4c0a8a5..74ce295bb8a 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/types/AbstractTypeChecker.kt @@ -407,9 +407,15 @@ object AbstractTypeChecker { val superTypeCaptured = superType.asCapturedType() val lowerType = superTypeCaptured?.lowerType() if (superTypeCaptured != null && lowerType != null) { + // If superType is nullable, e.g., to check if Foo? a subtype of Captured?, we check the LHS, Foo?, + // against the nullable version of the lower type of RHS. See KT-42825 + val nullableLowerType = + if (superType.isMarkedNullable()) + lowerType.withNullability(true) + else lowerType when (getLowerCapturedTypePolicy(subType, superTypeCaptured)) { - CHECK_ONLY_LOWER -> return isSubtypeOf(this, subType, lowerType) - CHECK_SUBTYPE_AND_LOWER -> if (isSubtypeOf(this, subType, lowerType)) return true + CHECK_ONLY_LOWER -> return isSubtypeOf(this, subType, nullableLowerType) + CHECK_SUBTYPE_AND_LOWER -> if (isSubtypeOf(this, subType, nullableLowerType)) return true SKIP_LOWER -> Unit } } diff --git a/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt b/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt index d6bd8ab2765..29b34eb5741 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt @@ -144,9 +144,6 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui fun KotlinTypeMarker.isBuiltinFunctionalTypeOrSubtype(): Boolean - fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker - - fun KotlinTypeMarker.makeDefinitelyNotNullOrNotNull(): KotlinTypeMarker fun SimpleTypeMarker.makeSimpleTypeDefinitelyNotNullOrNotNull(): SimpleTypeMarker @@ -241,7 +238,6 @@ interface TypeSystemContext : TypeSystemOptimizationContext { fun KotlinTypeMarker.isError(): Boolean fun TypeConstructorMarker.isError(): Boolean fun KotlinTypeMarker.isUninferredParameter(): Boolean - fun FlexibleTypeMarker.asDynamicType(): DynamicTypeMarker? fun FlexibleTypeMarker.asRawType(): RawTypeMarker? @@ -259,6 +255,7 @@ interface TypeSystemContext : TypeSystemOptimizationContext { fun SimpleTypeMarker.withNullability(nullable: Boolean): SimpleTypeMarker fun SimpleTypeMarker.typeConstructor(): TypeConstructorMarker + fun KotlinTypeMarker.withNullability(nullable: Boolean): KotlinTypeMarker fun CapturedTypeMarker.typeConstructor(): CapturedTypeConstructorMarker fun CapturedTypeMarker.captureStatus(): CaptureStatus diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 9e7dde16038..f98e7183e9e 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -13895,6 +13895,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes public void testAllFilesPresentInGenerics() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/generics"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); } + + @TestMetadata("kt42825.kt") + public void testKt42825() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/generics/kt42825.kt"); + } } @TestMetadata("compiler/testData/codegen/box/javaInterop/notNullAssertions") diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 1cc3f93e591..a6a2a19a7e0 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -13895,6 +13895,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { public void testAllFilesPresentInGenerics() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/generics"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); } + + @TestMetadata("kt42825.kt") + public void testKt42825() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/generics/kt42825.kt"); + } } @TestMetadata("compiler/testData/codegen/box/javaInterop/notNullAssertions") diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 177ca42bf1b..ef4b905d1fc 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -13960,6 +13960,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { public void testAllFilesPresentInGenerics() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/generics"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); } + + @TestMetadata("kt42825.kt") + public void testKt42825() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/generics/kt42825.kt"); + } } @TestMetadata("compiler/testData/codegen/box/javaInterop/notNullAssertions")