Fix casts of the null constant to SAM types

This commit is contained in:
pyos
2019-04-03 12:26:57 +02:00
committed by max-kammerer
parent f47d9d54c0
commit ee59530f71
@@ -71,15 +71,15 @@ class SingleAbstractMethodLowering(val context: CommonBackendContext) : ClassLow
// Not an exhaustive check, but enough to cover the most common cases. // Not an exhaustive check, but enough to cover the most common cases.
if (invokable is IrFunctionReference) { if (invokable is IrFunctionReference) {
// Runnable(::function) // Runnable(::function)
createFunctionProxyInstance(superType, invokable) +createFunctionProxyInstance(superType, invokable)
} else if (invokable is IrBlock && invokable.statements.last() is IrFunctionReference) { } else if (invokable is IrBlock && invokable.statements.last() is IrFunctionReference) {
// Runnable { lambda } // Runnable { lambda }
for (statement in invokable.statements.dropLast(1)) for (statement in invokable.statements.dropLast(1))
+statement +statement
createFunctionProxyInstance(superType, invokable.statements.last() as IrFunctionReference) +createFunctionProxyInstance(superType, invokable.statements.last() as IrFunctionReference)
} else { } else {
// Fall back to materializing an invokable object. // Fall back to materializing an invokable object.
createObjectProxyInstance(superType, invokable) +createObjectProxyInstance(superType, invokable)
} }
} }
} }
@@ -166,16 +166,19 @@ class SingleAbstractMethodLowering(val context: CommonBackendContext) : ClassLow
} }
} }
private fun IrBlockBuilder.createObjectProxyInstance(superType: IrType, invokable: IrExpression) { private fun IrBlockBuilder.createObjectProxyInstance(superType: IrType, invokable: IrExpression): IrExpression {
// Do not generate a wrapper class for null, it has no invoke() anyway.
if (invokable.isNullConst())
return invokable
val implementation = cachedImplementations.getOrPut(superType.toKotlinType() to invokable.type.toKotlinType()) { val implementation = cachedImplementations.getOrPut(superType.toKotlinType() to invokable.type.toKotlinType()) {
createObjectProxy(superType, invokable.type) createObjectProxy(superType, invokable.type)
} }
if (superType.isNullable() && invokable.type.isNullable()) { return if (superType.isNullable() && invokable.type.isNullable()) {
val invokableVariable = irTemporary(invokable) val invokableVariable = irTemporary(invokable)
val instance = irCall(implementation.constructors.single()).apply { putValueArgument(0, irGet(invokableVariable)) } val instance = irCall(implementation.constructors.single()).apply { putValueArgument(0, irGet(invokableVariable)) }
+irIfNull(superType, irGet(invokableVariable), irNull(), instance) irIfNull(superType, irGet(invokableVariable), irNull(), instance)
} else { } else {
+irCall(implementation.constructors.single()).apply { putValueArgument(0, invokable) } irCall(implementation.constructors.single()).apply { putValueArgument(0, invokable) }
} }
} }
@@ -217,10 +220,10 @@ class SingleAbstractMethodLowering(val context: CommonBackendContext) : ClassLow
} }
} }
private fun IrBlockBuilder.createFunctionProxyInstance(superType: IrType, reference: IrFunctionReference) { private fun IrBlockBuilder.createFunctionProxyInstance(superType: IrType, reference: IrFunctionReference): IrExpression {
val implementation = createFunctionProxy(superType, reference) val implementation = createFunctionProxy(superType, reference)
localImplementations += implementation localImplementations += implementation
+irCall(implementation.constructors.single()).apply { return irCall(implementation.constructors.single()).apply {
reference.arguments.filterNotNull().forEachIndexed(::putValueArgument) reference.arguments.filterNotNull().forEachIndexed(::putValueArgument)
} }
} }