Avoid leaking SamConstructorDescriptors from psi2ir
This commit is contained in:
+2
-18
@@ -44,27 +44,11 @@ class SingleAbstractMethodLowering(val context: CommonBackendContext) : ClassLow
|
||||
val cachedImplementations = mutableMapOf<Pair<KotlinType, KotlinType>, IrClass>()
|
||||
val localImplementations = mutableListOf<IrClass>()
|
||||
irClass.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
if (expression.symbol.owner.descriptor !is SamConstructorDescriptor)
|
||||
return super.visitCall(expression)
|
||||
// Direct construction of an interface:
|
||||
// Runnable { print("Hello, World!") }
|
||||
return createInstance(expression.type, expression.getValueArgument(0)!!.transform(this, null))
|
||||
}
|
||||
|
||||
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression {
|
||||
if (expression.operator != IrTypeOperator.SAM_CONVERSION)
|
||||
return super.visitTypeOperator(expression)
|
||||
// Implicit conversion to an interface:
|
||||
// // FILE: 1.java
|
||||
// class A { public static void f(Runnable r) { r.run() } }
|
||||
// // FILE: 2.kt
|
||||
// A.f { print("Hello, World!") }
|
||||
return createInstance(expression.typeOperand, expression.argument.transform(this, null))
|
||||
}
|
||||
|
||||
// Replace a SAM-conversion of a callable object with an instance of an appropriate implementation.
|
||||
private fun createInstance(superType: IrType, invokable: IrExpression): IrExpression {
|
||||
val superType = expression.typeOperand
|
||||
val invokable = expression.argument.transform(this, null)
|
||||
// Running in the class context, so empty scope means this is a field/anonymous initializer.
|
||||
val scopeOwnerSymbol = currentScope?.scope?.scopeOwnerSymbol ?: irClass.symbol
|
||||
return context.createIrBuilder(scopeOwnerSymbol).irBlock(invokable, null, superType) {
|
||||
|
||||
@@ -43,7 +43,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
fun generateCall(startOffset: Int, endOffset: Int, call: CallBuilder, origin: IrStatementOrigin? = null): IrExpression {
|
||||
val descriptor = call.descriptor
|
||||
|
||||
if (context.extensions.samConversion.isSamConstructor(descriptor)) {
|
||||
if (context.extensions.samConversion.isSamConstructor(descriptor.original)) {
|
||||
return generateSamConstructorCall(descriptor, startOffset, endOffset, call)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,4 +4,6 @@ fun test1() = Runnable { }
|
||||
fun test2(a: () -> Unit) = Runnable(a)
|
||||
|
||||
fun foo() {}
|
||||
fun test3() = Runnable(::foo)
|
||||
fun test3() = Runnable(::foo)
|
||||
|
||||
fun test4() = Comparator<Int> { a, b -> a - b }
|
||||
@@ -22,3 +22,18 @@ FILE fqName:<root> fileName:/samConstructors.kt
|
||||
RETURN type=kotlin.Nothing from='public final fun test3 (): java.lang.Runnable declared in <root>'
|
||||
TYPE_OP type=java.lang.Runnable origin=SAM_CONVERSION typeOperand=java.lang.Runnable
|
||||
FUNCTION_REFERENCE 'public final fun foo (): kotlin.Unit declared in <root>' type=kotlin.reflect.KFunction0<kotlin.Unit> origin=null
|
||||
FUN name:test4 visibility:public modality:FINAL <> () returnType:java.util.Comparator<kotlin.Int>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test4 (): java.util.Comparator<kotlin.Int> declared in <root>'
|
||||
TYPE_OP type=java.util.Comparator<kotlin.Int> origin=SAM_CONVERSION typeOperand=java.util.Comparator<kotlin.Int>
|
||||
TYPE_OP type=kotlin.Function2<T of java.util.Comparator?, T of java.util.Comparator?, kotlin.Int> origin=IMPLICIT_CAST typeOperand=kotlin.Function2<T of java.util.Comparator?, T of java.util.Comparator?, kotlin.Int>
|
||||
BLOCK type=kotlin.Function2<kotlin.Int?, kotlin.Int?, kotlin.Int> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (a:kotlin.Int?, b:kotlin.Int?) returnType:kotlin.Int
|
||||
VALUE_PARAMETER name:a index:0 type:kotlin.Int?
|
||||
VALUE_PARAMETER name:b index:1 type:kotlin.Int?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (a: kotlin.Int?, b: kotlin.Int?): kotlin.Int declared in <root>.test4'
|
||||
CALL 'public final fun minus (other: kotlin.Int): kotlin.Int declared in kotlin.Int' type=kotlin.Int origin=MINUS
|
||||
$this: GET_VAR 'a: kotlin.Int? declared in <root>.test4.<anonymous>' type=kotlin.Int? origin=null
|
||||
other: GET_VAR 'b: kotlin.Int? declared in <root>.test4.<anonymous>' type=kotlin.Int? origin=null
|
||||
FUNCTION_REFERENCE 'local final fun <anonymous> (a: kotlin.Int?, b: kotlin.Int?): kotlin.Int declared in <root>.test4' type=kotlin.Function2<kotlin.Int?, kotlin.Int?, kotlin.Int> origin=LAMBDA
|
||||
|
||||
Reference in New Issue
Block a user