diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaTypeConversion.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaTypeConversion.kt index a6dc8107000..6287684ab6a 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaTypeConversion.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaTypeConversion.kt @@ -78,19 +78,31 @@ internal fun JavaType?.toFirResolvedTypeRef( private fun JavaType?.toConeKotlinType( session: FirSession, javaTypeParameterStack: JavaTypeParameterStack, - mode: FirJavaTypeConversionMode + mode: FirJavaTypeConversionMode, + additionalAnnotations: Collection? = null ): ConeKotlinType = - toConeTypeProjection(session, javaTypeParameterStack, Variance.INVARIANT, mode).type + toConeTypeProjection(session, javaTypeParameterStack, Variance.INVARIANT, mode, additionalAnnotations).type ?: StandardClassIds.Any.toConeFlexibleType(emptyArray(), emptyArray(), ConeAttributes.Empty) private fun JavaType?.toConeTypeProjection( session: FirSession, javaTypeParameterStack: JavaTypeParameterStack, - parameterVariance: Variance, mode: FirJavaTypeConversionMode + parameterVariance: Variance, mode: FirJavaTypeConversionMode, + additionalAnnotations: Collection? = null ): ConeTypeProjection { - val attributes = if (this != null && annotations.isNotEmpty()) - ConeAttributes.create(listOf(CustomAnnotationTypeAttribute(convertAnnotationsToFir(session, javaTypeParameterStack)))) - else + val attributes = if (this != null && (annotations.isNotEmpty() || additionalAnnotations != null)) { + val convertedAnnotations = buildList { + if (annotations.isNotEmpty()) { + addAll(this@toConeTypeProjection.convertAnnotationsToFir(session, javaTypeParameterStack)) + } + if (additionalAnnotations != null) { + addAll(additionalAnnotations.convertAnnotationsToFir(session, javaTypeParameterStack)) + } + } + + ConeAttributes.create(listOf(CustomAnnotationTypeAttribute(convertedAnnotations))) + } else { ConeAttributes.Empty + } return when (this) { is JavaClassifierType -> { @@ -141,7 +153,8 @@ private fun JavaType?.toConeTypeProjection( if (bound == null || (parameterVariance != Variance.INVARIANT && parameterVariance != argumentVariance)) { ConeStarProjection } else { - val boundType = bound.toConeKotlinType(session, javaTypeParameterStack, mode) + val nullabilityAnnotationOnWildcard = extractNullabilityAnnotationOnBoundedWildcard(this)?.let(::listOf) + val boundType = bound.toConeKotlinType(session, javaTypeParameterStack, mode, nullabilityAnnotationOnWildcard) if (isExtends) ConeKotlinTypeProjectionOut(boundType) else ConeKotlinTypeProjectionIn(boundType) } } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt index fbfd907fa49..981f8f8dccc 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt @@ -20,8 +20,11 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildErrorExpression import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.expectedConeType import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.createArrayType +import org.jetbrains.kotlin.load.java.RXJAVA3_ANNOTATIONS +import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.JavaModifierListOwner +import org.jetbrains.kotlin.load.java.structure.JavaWildcardType import org.jetbrains.kotlin.types.ConstantValueKind internal val JavaModifierListOwner.modality: Modality @@ -98,3 +101,9 @@ private fun FirConstExpression<*>.setProperType(session: FirSession): FirConstEx replaceTypeRef(typeRef) return this } + +// For now, it's supported only for RxJava3 annotations, see KT-53041 +fun extractNullabilityAnnotationOnBoundedWildcard(wildcardType: JavaWildcardType): JavaAnnotation? { + require(wildcardType.bound != null) { "Nullability annotations on unbounded wildcards aren't supported" } + return wildcardType.annotations.find { annotation -> RXJAVA3_ANNOTATIONS.any { annotation.classId?.asSingleFqName() == it } } +} diff --git a/compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt b/compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt index 9fcb9225c22..80769187698 100644 --- a/compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt +++ b/compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt @@ -1,5 +1,6 @@ // FIR_IDENTICAL // JVM_TARGET: 1.8 +// TARGET_BACKEND: JVM // NULLABILITY_ANNOTATIONS: @io.reactivex.rxjava3.annotations:strict // IGNORE_LIGHT_ANALYSIS diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java index cf4b71d8f02..3b97544f323 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java @@ -21140,12 +21140,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { public void testAllFilesPresentInTests() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); } - - @Test - @TestMetadata("kt53041.kt") - public void testKt53041() throws Exception { - runTest("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt"); - } } } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java index 8da8f6fa43e..47a85817fd6 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java @@ -21104,12 +21104,6 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { public void testAllFilesPresentInTests() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); } - - @Test - @TestMetadata("kt53041.kt") - public void testKt53041() throws Exception { - runTest("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt"); - } } } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 42657aa8b98..941399f5a89 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -18733,11 +18733,6 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest public void testAllFilesPresentInTests() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true); } - - @TestMetadata("kt53041.kt") - public void testKt53041() throws Exception { - runTest("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt"); - } } } diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java index c1d22454f17..cfd176145c8 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java @@ -23789,12 +23789,6 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest public void testAllFilesPresentInTests() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true); } - - @Test - @TestMetadata("kt53041.kt") - public void testKt53041() throws Exception { - runTest("compiler/testData/codegen/box/javaInterop/foreignAnnotationsTests/tests/kt53041.kt"); - } } }