diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt index af441705653..c78f0da2bcf 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt @@ -24,9 +24,7 @@ import org.jetbrains.kotlin.fir.java.toNotNullConeKotlinType import org.jetbrains.kotlin.fir.java.types.FirJavaTypeRef import org.jetbrains.kotlin.fir.references.impl.FirResolvedNamedReferenceImpl import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference -import org.jetbrains.kotlin.fir.resolve.constructType -import org.jetbrains.kotlin.fir.resolve.toSymbol -import org.jetbrains.kotlin.fir.resolve.toTypeProjection +import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag @@ -81,7 +79,7 @@ private fun JavaType?.enhancePossiblyFlexible( ): FirResolvedTypeRef { val type = this val arguments = this?.typeArguments().orEmpty() - return when (type) { + val enhanced = when (type) { is JavaClassifierType -> { val lowerResult = type.enhanceInflexibleType( session, javaTypeParameterStack, annotations, arguments, TypeComponentPosition.FLEXIBLE_LOWER, qualifiers, index @@ -90,20 +88,30 @@ private fun JavaType?.enhancePossiblyFlexible( session, javaTypeParameterStack, annotations, arguments, TypeComponentPosition.FLEXIBLE_UPPER, qualifiers, index ) - FirResolvedTypeRefImpl( - source = null, - type = coneFlexibleOrSimpleType(session, lowerResult, upperResult) - ).apply { - this.annotations += annotations + coneFlexibleOrSimpleType(session, lowerResult, upperResult) + } + is JavaArrayType -> { + val baseEnhanced = type.toNotNullConeKotlinType(session, javaTypeParameterStack) + + val upperBound = if (baseEnhanced.typeArguments.isNotEmpty()) { + val typeArgument = baseEnhanced.typeArguments.first() as ConeKotlinType + baseEnhanced.withArguments(arrayOf(ConeKotlinTypeProjectionOut(typeArgument))) + } else { + baseEnhanced } + ConeFlexibleType( + baseEnhanced, + upperBound.withNullability(ConeNullability.NULLABLE) + ) } else -> { - val enhanced = type.toNotNullConeKotlinType(session, javaTypeParameterStack) - FirResolvedTypeRefImpl(source = null, type = enhanced).apply { - this.annotations += annotations - } + type.toNotNullConeKotlinType(session, javaTypeParameterStack) } } + + return FirResolvedTypeRefImpl(source = null, type = enhanced).apply { + this.annotations += annotations + } } private fun JavaType?.subtreeSize(): Int { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ArrayUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ArrayUtils.kt index e5497709691..bb073ca1872 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ArrayUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ArrayUtils.kt @@ -15,8 +15,9 @@ import org.jetbrains.kotlin.fir.symbols.invoke fun ConeKotlinType.createArrayOf(session: FirSession, nullable: Boolean = false): ConeKotlinType { val symbolProvider: FirSymbolProvider = session.firSymbolProvider - if (this is ConeClassType) { - val primitiveArrayId = StandardClassIds.primitiveArrayTypeByElementType[lookupTag.classId] + val type = lowerBoundIfFlexible() + if (type is ConeClassType) { + val primitiveArrayId = StandardClassIds.primitiveArrayTypeByElementType[type.lookupTag.classId] if (primitiveArrayId != null) { return primitiveArrayId.invoke(symbolProvider).constructType(emptyArray(), nullable) } @@ -27,10 +28,11 @@ fun ConeKotlinType.createArrayOf(session: FirSession, nullable: Boolean = false) fun ConeKotlinType.arrayElementType(session: FirSession): ConeKotlinType? { - if (this !is ConeClassType) return null - val classId = this.lookupTag.classId + val type = this.lowerBoundIfFlexible() + if (type !is ConeClassType) return null + val classId = type.lookupTag.classId if (classId == StandardClassIds.Array) - return (typeArguments.first() as ConeTypedProjection).type + return (type.typeArguments.first() as ConeTypedProjection).type val elementType = StandardClassIds.elementTypeByPrimitiveArrayType[classId] if (elementType != null) { return elementType.invoke(session.firSymbolProvider).constructType(emptyArray(), isNullable = false) diff --git a/compiler/fir/resolve/testData/resolve/arguments/javaArrayVariance.kt b/compiler/fir/resolve/testData/resolve/arguments/javaArrayVariance.kt new file mode 100644 index 00000000000..4ead42a36c3 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/arguments/javaArrayVariance.kt @@ -0,0 +1,18 @@ +// FILE: A.java +public class A { + public static void take(A[] array) {} +} + +// FILE: B.java +public class B extends A {} + +// FILE: main.kt + +fun takeA(array: Array) {} +fun takeOutA(array: Array) {} + +fun test(array: Array) { + A.take(array) + takeA(array) + takeOutA(array) +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/arguments/javaArrayVariance.txt b/compiler/fir/resolve/testData/resolve/arguments/javaArrayVariance.txt new file mode 100644 index 00000000000..38b33e16f27 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/arguments/javaArrayVariance.txt @@ -0,0 +1,10 @@ +FILE: main.kt + public final fun takeA(array: R|kotlin/Array|): R|kotlin/Unit| { + } + public final fun takeOutA(array: R|kotlin/Array|): R|kotlin/Unit| { + } + public final fun test(array: R|kotlin/Array|): R|kotlin/Unit| { + Q|A|.R|/A.take|(R|/array|) + #(R|/array|) + R|/takeOutA|(R|/array|) + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index fafec4b52bf..960be0ac189 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -255,6 +255,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/resolve/testData/resolve/arguments/invoke.kt"); } + @TestMetadata("javaArrayVariance.kt") + public void testJavaArrayVariance() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/arguments/javaArrayVariance.kt"); + } + @TestMetadata("lambda.kt") public void testLambda() throws Exception { runTest("compiler/fir/resolve/testData/resolve/arguments/lambda.kt"); diff --git a/compiler/testData/ir/irText/stubs/jdkClassSyntheticProperty.fir.txt b/compiler/testData/ir/irText/stubs/jdkClassSyntheticProperty.fir.txt index e709fd92291..77f238eed7e 100644 --- a/compiler/testData/ir/irText/stubs/jdkClassSyntheticProperty.fir.txt +++ b/compiler/testData/ir/irText/stubs/jdkClassSyntheticProperty.fir.txt @@ -1,8 +1,8 @@ FILE fqName: fileName:/jdkClassSyntheticProperty.kt PROPERTY name:test visibility:public modality:FINAL [val] - FUN name: visibility:public modality:FINAL <> () returnType:kotlin.Array + FUN name: visibility:public modality:FINAL <> () returnType:kotlin.Array? correspondingProperty: PROPERTY name:test visibility:public modality:FINAL [val] BLOCK_BODY - RETURN type=kotlin.Nothing from='public final fun (): kotlin.Array declared in ' - CALL 'public open fun getDeclaredFields (): kotlin.Array declared in java.lang.Class' type=kotlin.Array origin=GET_PROPERTY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Array? declared in ' + CALL 'public open fun getDeclaredFields (): kotlin.Array? declared in java.lang.Class' type=kotlin.Array? origin=GET_PROPERTY $this: ERROR_CALL 'Unresolved reference: this@R|/test|' type=java.lang.Class<*> diff --git a/compiler/testData/loadJava/compiledJava/ArrayTypeVariance.fir.txt b/compiler/testData/loadJava/compiledJava/ArrayTypeVariance.fir.txt index 380ff4b6858..7c8d0a59c91 100644 --- a/compiler/testData/loadJava/compiledJava/ArrayTypeVariance.fir.txt +++ b/compiler/testData/loadJava/compiledJava/ArrayTypeVariance.fir.txt @@ -1,5 +1,5 @@ public final class ArrayTypeVariance : R|kotlin/Any| { - public final operator fun toArray(p0: R|kotlin/Array!>|): R|kotlin/Array!>| + public final operator fun toArray(p0: R|ft!>, kotlin/Array!>?>!|): R|ft!>, kotlin/Array!>?>!| public constructor(): R|test/ArrayTypeVariance| diff --git a/compiler/testData/loadJava/compiledJava/FieldOfArrayType.fir.txt b/compiler/testData/loadJava/compiledJava/FieldOfArrayType.fir.txt index eb638483a54..9099f9e09d0 100644 --- a/compiler/testData/loadJava/compiledJava/FieldOfArrayType.fir.txt +++ b/compiler/testData/loadJava/compiledJava/FieldOfArrayType.fir.txt @@ -1,5 +1,5 @@ public open class FieldOfArrayType : R|kotlin/Any| { - public open field files: R|kotlin/Array!>| + public open field files: R|ft!>, kotlin/Array!>?>!| public constructor(): R|test/FieldOfArrayType| diff --git a/compiler/testData/loadJava/compiledJava/kotlinSignature/ArrayType.fir.txt b/compiler/testData/loadJava/compiledJava/kotlinSignature/ArrayType.fir.txt index 75e3b256a5a..f04c8dc30e5 100644 --- a/compiler/testData/loadJava/compiledJava/kotlinSignature/ArrayType.fir.txt +++ b/compiler/testData/loadJava/compiledJava/kotlinSignature/ArrayType.fir.txt @@ -1,5 +1,5 @@ public open class ArrayType : R|kotlin/Any| { - public open operator fun foo(): R|kotlin/Array!>| + public open operator fun foo(): R|ft!>, kotlin/Array!>?>!| public constructor(): R|test/ArrayType| diff --git a/compiler/testData/loadJava/compiledJava/kotlinSignature/MethodWithVararg.fir.txt b/compiler/testData/loadJava/compiledJava/kotlinSignature/MethodWithVararg.fir.txt index 43e46128294..3cc0bf1e521 100644 --- a/compiler/testData/loadJava/compiledJava/kotlinSignature/MethodWithVararg.fir.txt +++ b/compiler/testData/loadJava/compiledJava/kotlinSignature/MethodWithVararg.fir.txt @@ -1,5 +1,5 @@ public open class MethodWithVararg : R|kotlin/Any| { - public open operator fun foo(vararg s: R|kotlin/Array!>|): R|kotlin/Unit| + public open operator fun foo(vararg s: R|ft!>, kotlin/Array!>?>!|): R|kotlin/Unit| public constructor(): R|test/MethodWithVararg| diff --git a/compiler/testData/loadJava/compiledJava/kotlinSignature/PropertyArrayTypes.fir.txt b/compiler/testData/loadJava/compiledJava/kotlinSignature/PropertyArrayTypes.fir.txt index 1461979e7c9..45d98a11b3a 100644 --- a/compiler/testData/loadJava/compiledJava/kotlinSignature/PropertyArrayTypes.fir.txt +++ b/compiler/testData/loadJava/compiledJava/kotlinSignature/PropertyArrayTypes.fir.txt @@ -1,9 +1,9 @@ public open class PropertyArrayTypes : R|kotlin/Any| { - public open field arrayOfArrays: R|kotlin/Array!>, kotlin/Array!>?>!>| + public open field arrayOfArrays: R|ft!>, kotlin/Array!>?>!>, kotlin/Array!>, kotlin/Array!>?>!>?>!| - public open field array: R|kotlin/Array!>| + public open field array: R|ft!>, kotlin/Array!>?>!| - public open field genericArray: R|kotlin/Array!>| + public open field genericArray: R|ft!>, kotlin/Array!>?>!| public constructor(): R|test/PropertyArrayTypes| diff --git a/compiler/testData/loadJava/compiledJava/kotlinSignature/error/WrongProjectionKind.fir.txt b/compiler/testData/loadJava/compiledJava/kotlinSignature/error/WrongProjectionKind.fir.txt index 9b3d7d82eda..46dd0c4cc8d 100644 --- a/compiler/testData/loadJava/compiledJava/kotlinSignature/error/WrongProjectionKind.fir.txt +++ b/compiler/testData/loadJava/compiledJava/kotlinSignature/error/WrongProjectionKind.fir.txt @@ -1,5 +1,5 @@ public open class WrongProjectionKind : R|kotlin/Any| { - public open operator fun copy(from: R|kotlin/Array!>|, to: R|kotlin/Array!>|): R|ft!>, kotlin/collections/List!>?>!| + public open operator fun copy(from: R|ft!>, kotlin/Array!>?>!|, to: R|ft!>, kotlin/Array!>?>!|): R|ft!>, kotlin/collections/List!>?>!| public constructor(): R|test/WrongProjectionKind| diff --git a/compiler/testData/loadJava/compiledJava/notNull/NotNullIntArray.fir.txt b/compiler/testData/loadJava/compiledJava/notNull/NotNullIntArray.fir.txt index c2f8d6feb27..f8266ca439c 100644 --- a/compiler/testData/loadJava/compiledJava/notNull/NotNullIntArray.fir.txt +++ b/compiler/testData/loadJava/compiledJava/notNull/NotNullIntArray.fir.txt @@ -1,5 +1,5 @@ public open class NotNullIntArray : R|kotlin/Any| { - @R|org/jetbrains/annotations/NotNull|() public open operator fun hi(): R|kotlin/IntArray| + @R|org/jetbrains/annotations/NotNull|() public open operator fun hi(): R|ft!| public constructor(): R|test/NotNullIntArray| diff --git a/compiler/testData/loadJava/compiledJava/notNull/NotNullObjectArray.fir.txt b/compiler/testData/loadJava/compiledJava/notNull/NotNullObjectArray.fir.txt index 58dd9ea6800..bb637000cf0 100644 --- a/compiler/testData/loadJava/compiledJava/notNull/NotNullObjectArray.fir.txt +++ b/compiler/testData/loadJava/compiledJava/notNull/NotNullObjectArray.fir.txt @@ -1,5 +1,5 @@ public open class NotNullObjectArray : R|kotlin/Any| { - @R|org/jetbrains/annotations/NotNull|() public open operator fun hi(): R|kotlin/Array!>| + @R|org/jetbrains/annotations/NotNull|() public open operator fun hi(): R|ft!>, kotlin/Array!>?>!| public constructor(): R|test/NotNullObjectArray| diff --git a/compiler/testData/loadJava/compiledJava/sam/GenericInterfaceParametersWithBounds.fir.txt b/compiler/testData/loadJava/compiledJava/sam/GenericInterfaceParametersWithBounds.fir.txt index 94133370a78..362f6adf8c8 100644 --- a/compiler/testData/loadJava/compiledJava/sam/GenericInterfaceParametersWithBounds.fir.txt +++ b/compiler/testData/loadJava/compiledJava/sam/GenericInterfaceParametersWithBounds.fir.txt @@ -1,4 +1,4 @@ public abstract interface GenericInterfaceParametersWithBounds?|, R|kotlin/Cloneable?|, B : R|kotlin/collections/MutableList?|> : R|kotlin/Any| { - public abstract operator fun method(a: R|kotlin/Array!>|, b: R|ft!|): R|kotlin/Unit| + public abstract operator fun method(a: R|ft!>, kotlin/Array!>?>!|, b: R|ft!|): R|kotlin/Unit| } diff --git a/compiler/testData/loadJava/compiledJava/sam/GenericMethodParameters.fir.txt b/compiler/testData/loadJava/compiledJava/sam/GenericMethodParameters.fir.txt index 8720bdb3319..d055bab41f8 100644 --- a/compiler/testData/loadJava/compiledJava/sam/GenericMethodParameters.fir.txt +++ b/compiler/testData/loadJava/compiledJava/sam/GenericMethodParameters.fir.txt @@ -1,4 +1,4 @@ public abstract interface GenericMethodParameters : R|kotlin/Any| { - public abstract operator fun ?|> method(a: R|kotlin/Array!>|, b: R|ft!|): R|kotlin/Unit| + public abstract operator fun ?|> method(a: R|ft!>, kotlin/Array!>?>!|, b: R|ft!|): R|kotlin/Unit| } diff --git a/compiler/testData/loadJava/compiledJava/sam/VarargParameter.fir.txt b/compiler/testData/loadJava/compiledJava/sam/VarargParameter.fir.txt index 0bffe5d383d..48e18ac79a1 100644 --- a/compiler/testData/loadJava/compiledJava/sam/VarargParameter.fir.txt +++ b/compiler/testData/loadJava/compiledJava/sam/VarargParameter.fir.txt @@ -1,4 +1,4 @@ public abstract interface VarargParameter : R|kotlin/Any| { - public abstract operator fun f(vararg strings: R|kotlin/Array!>|): R|kotlin/Unit| + public abstract operator fun f(vararg strings: R|ft!>, kotlin/Array!>?>!|): R|kotlin/Unit| } diff --git a/compiler/testData/loadJava/compiledJava/vararg/VarargInt.fir.txt b/compiler/testData/loadJava/compiledJava/vararg/VarargInt.fir.txt index 348ee86f7b8..ee0a67e5ff8 100644 --- a/compiler/testData/loadJava/compiledJava/vararg/VarargInt.fir.txt +++ b/compiler/testData/loadJava/compiledJava/vararg/VarargInt.fir.txt @@ -1,5 +1,5 @@ public open class VarargInt : R|kotlin/Any| { - public open operator fun vararg(vararg p: R|kotlin/IntArray|): R|kotlin/Unit| + public open operator fun vararg(vararg p: R|ft!|): R|kotlin/Unit| public constructor(): R|test/VarargInt| diff --git a/compiler/testData/loadJava/compiledJava/vararg/VarargString.fir.txt b/compiler/testData/loadJava/compiledJava/vararg/VarargString.fir.txt index 6f6cb7a43fb..6d52cdf219f 100644 --- a/compiler/testData/loadJava/compiledJava/vararg/VarargString.fir.txt +++ b/compiler/testData/loadJava/compiledJava/vararg/VarargString.fir.txt @@ -1,5 +1,5 @@ public open class VarargString : R|kotlin/Any| { - public open operator fun vararg(vararg strings: R|kotlin/Array!>|): R|kotlin/Unit| + public open operator fun vararg(vararg strings: R|ft!>, kotlin/Array!>?>!|): R|kotlin/Unit| public constructor(): R|test/VarargString| diff --git a/idea/testData/fir/multiModule/basicWithPrimitiveJava/extraDump.java.txt b/idea/testData/fir/multiModule/basicWithPrimitiveJava/extraDump.java.txt index 774b6b80464..12948ceb6ae 100644 --- a/idea/testData/fir/multiModule/basicWithPrimitiveJava/extraDump.java.txt +++ b/idea/testData/fir/multiModule/basicWithPrimitiveJava/extraDump.java.txt @@ -1,7 +1,7 @@ public open class Some : R|kotlin/Any| { public open operator fun foo(param: R|kotlin/Int|): R|kotlin/Boolean| - public open operator fun bar(arr: R|kotlin/IntArray|): R|kotlin/Array!>| + public open operator fun bar(arr: R|ft!|): R|ft!>, kotlin/Array!>?>!| public constructor(): R|Some| diff --git a/idea/testData/fir/multiModule/basicWithPrimitiveJava/jvm/jvm.txt b/idea/testData/fir/multiModule/basicWithPrimitiveJava/jvm/jvm.txt index ad50fc587ea..9d565a82f0b 100644 --- a/idea/testData/fir/multiModule/basicWithPrimitiveJava/jvm/jvm.txt +++ b/idea/testData/fir/multiModule/basicWithPrimitiveJava/jvm/jvm.txt @@ -7,7 +7,7 @@ FILE: jvm.kt public final fun test(): R|kotlin/Unit| { lval res1: R|kotlin/Boolean| = this@R|/Some|.R|/Some.foo|(Int(1)) lval res2: R|kotlin/Boolean| = this@R|/Some|.R|/Some.foo|(Int(1).R|kotlin/Int.unaryMinus|()) - lval res3: R|kotlin/Array!>| = this@R|/Some|.R|/Some.bar|(R|kotlin/intArrayOf|(Int(0), Int(2), Int(2).R|kotlin/Int.unaryMinus|())) + lval res3: R|ft!>, kotlin/Array!>?>!| = this@R|/Some|.R|/Some.bar|(R|kotlin/intArrayOf|(Int(0), Int(2), Int(2).R|kotlin/Int.unaryMinus|())) } }