JVM, JVM IR: erase generic SAM supertypes
Also, do not try to use invokedynamic on SAM calls with intersection
types, because intersection type is not allowed as an immediate type
projection of a supertype, and constructing a fake override in
LambdaMetafactoryArgumentsBuilder led to an exception. This fixes the
problem which was worked around earlier in e6c089ef, effectively
reverting that commit.
The main motivation for this change is that LambdaMetafactory also
doesn't generate generic signature for SAM wrapper classes at runtime.
Since these classes are synthetic, nobody should rely on the fact that
they have generic supertypes, which was observable only via Java
reflection.
#KT-46149 Fixed
#KT-46238 Fixed
This commit is contained in:
+5
-1
@@ -187,7 +187,11 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
}
|
||||
}
|
||||
|
||||
return FunctionReferenceBuilder(reference, samSuperType).build()
|
||||
// Erase generic arguments in the SAM type, because they are not easy to approximate correctly otherwise,
|
||||
// and LambdaMetafactory also uses erased type.
|
||||
val erasedSamSuperType = samSuperType.erasedUpperBound.rawType(context)
|
||||
|
||||
return FunctionReferenceBuilder(reference, erasedSamSuperType).build()
|
||||
}
|
||||
|
||||
private fun canGenerateIndySamConversionOnFunctionalExpression(samSuperType: IrType, expression: IrExpression): Boolean {
|
||||
|
||||
+7
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
internal class LambdaMetafactoryArguments(
|
||||
@@ -105,6 +106,12 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
||||
if (implFun.parents.any { it.isInlineFunction() || it.isCrossinlineLambda() })
|
||||
return null
|
||||
|
||||
// Don't try to use indy on SAM types with non-invariant projections because buildFakeOverrideMember doesn't support such supertypes
|
||||
// (and rightly so: supertypes in Kotlin can't have projections in immediate type arguments). This can happen for example in case
|
||||
// the SAM type is instantiated with an intersection type in arguments, which is approximated to an out-projection in psi2ir.
|
||||
if (samType is IrSimpleType && samType.arguments.any { it is IrTypeProjection && it.variance != Variance.INVARIANT })
|
||||
return null
|
||||
|
||||
// Do the hard work of matching Kotlin functional interface hierarchy against LambdaMetafactory constraints.
|
||||
// Briefly: sometimes we have to force boxing on the primitive and inline class values, sometimes we have to keep them unboxed.
|
||||
// If this results in conflicting requirements, we can't use INVOKEDYNAMIC with LambdaMetafactory for creating a closure.
|
||||
|
||||
Reference in New Issue
Block a user