diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt index e96e915718d..a358f3857cc 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt @@ -255,10 +255,23 @@ open class FirJvmMangleComputer( tBuilder.appendSignature(MangleConstant.ENHANCED_NULLABILITY_MARK) } } + is ConeRawType -> { + mangleType(tBuilder, type.lowerBound) + } is ConeFlexibleType -> { - // Need to reproduce type approximation done for flexible types in TypeTranslator. - // For now, we replicate the current behaviour of Fir2IrTypeConverter and just take the upper bound - mangleType(tBuilder, type.upperBound) + with(session.typeContext) { + // Need to reproduce type approximation done for flexible types in TypeTranslator. + // For now, we replicate the current behaviour of Fir2IrTypeConverter and just take the upper bound + val upper = type.upperBound + if (upper is ConeClassLikeType) { + val lower = type.lowerBound as? ConeClassLikeType ?: error("Expecting class-like type, got ${type.lowerBound}") + val intermediate = if (lower.lookupTag == upper.lookupTag) { + lower.replaceArguments(upper.getArguments()) + } else lower + val mixed = if (upper.isNullable) intermediate.makeNullable() else intermediate.makeDefinitelyNotNullOrNotNull() + mangleType(tBuilder, mixed as ConeKotlinType) + } else mangleType(tBuilder, upper) + } } is ConeDefinitelyNotNullType -> { // E.g. not-null type parameter in Java diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt index a25480c4e4f..fb3acf96fb1 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt @@ -163,13 +163,26 @@ class Fir2IrTypeConverter( // (some reflection tests rely on this) lowerBound.toIrType( typeContext, + annotations, hasFlexibleNullability = lowerBound.nullability != upperBound.nullability, addRawTypeAnnotation = true ) } - is ConeFlexibleType -> { - // TODO: yet we take more general type. Not quite sure it's Ok - upperBound.toIrType(typeContext, hasFlexibleNullability = lowerBound.nullability != upperBound.nullability) + is ConeFlexibleType -> with(session.typeContext) { + if (upperBound is ConeClassLikeType) { + val upper = upperBound as ConeClassLikeType + val lower = lowerBound as? ConeClassLikeType ?: error("Expecting class-like type, got $lowerBound") + val intermediate = if (lower.lookupTag == upper.lookupTag) { + lower.replaceArguments(upper.getArguments()) + } else lower + (intermediate.withNullability(upper.isNullable) as ConeKotlinType) + .withAttributes(lower.attributes) + .toIrType( + typeContext, annotations, hasFlexibleNullability = lower.nullability != upper.nullability + ) + } else { + upperBound.toIrType(typeContext, annotations, hasFlexibleNullability = lowerBound.nullability != upperBound.nullability) + } } is ConeCapturedType -> { val cached = capturedTypeCache[this]