[IR] Reworked adapted references building + test

As a side effect, this fixes https://youtrack.jetbrains.com/issue/KT-43887

(cherry picked from commit 387c09e7aed7666f5a178b2ac342fb17ed3cdda3)
This commit is contained in:
Igor Chevdar
2021-02-08 20:13:02 +05:00
committed by Space
parent 3c5e3d8d50
commit 31835f1921
3 changed files with 57 additions and 29 deletions
@@ -213,30 +213,8 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
private val samSuperClass = samSuperType?.let { it.classOrNull ?: error("Expected a class but was: ${it.render()}") }
private val adapteeCall: IrFunctionAccessExpression? =
// TODO: Copied from JVM.
if (referencedFunction.origin == IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE) {
// The body of a callable reference adapter contains either only a call, or an IMPLICIT_COERCION_TO_UNIT type operator
// applied to a call. That call's target is the original function which we need to get owner/name/signature.
val call = when (val statement = referencedFunction.body!!.statements.single()) {
is IrTypeOperatorCall -> {
assert(statement.operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT) {
"Unexpected type operator in ADAPTER_FOR_CALLABLE_REFERENCE: ${referencedFunction.render()}"
}
statement.argument
}
is IrReturn -> statement.value
else -> statement
}
if (call !is IrFunctionAccessExpression) {
throw UnsupportedOperationException("Unknown structure of ADAPTER_FOR_CALLABLE_REFERENCE: ${referencedFunction.render()}")
}
call
} else {
null
}
private val adaptedReferenceOriginalTarget: IrFunction? = functionReference.reflectionTarget?.owner
private val adaptedReferenceOriginalTarget: IrFunction? = adapteeCall?.symbol?.owner
private val functionReferenceTarget = adaptedReferenceOriginalTarget ?: referencedFunction
private val functionReferenceClass: IrClass =
@@ -404,13 +382,21 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
}
private fun hasVarargMappedToElement(): Boolean {
if (adapteeCall == null) return false
for (i in 0 until adapteeCall.valueArgumentsCount) {
val arg = adapteeCall.getValueArgument(i) ?: continue
if (arg !is IrVararg) continue
for (varargElement in arg.elements) {
if (varargElement is IrGetValue) return true
if (adaptedReferenceOriginalTarget == null) return false
val originalParameters = adaptedReferenceOriginalTarget.allParameters
val adaptedParameters = functionReference.symbol.owner.allParameters
var index = 0
// TODO: There should be similar code somewhere in the resolve.
while (index < originalParameters.size && index < adaptedParameters.size) {
val originalParameter = originalParameters[index]
val adaptedParameter = adaptedParameters[index]
if (originalParameter.defaultValue != null) return false
if (originalParameter.isVararg) {
if (originalParameter.varargElementType!!.erasureForTypeOperation()
== adaptedParameter.type.erasureForTypeOperation())
return true
}
++index
}
return false
}
@@ -2779,6 +2779,10 @@ task funInterface_nonTrivialProjectionInSuperType(type: KonanLocalTest) {
source = "codegen/funInterface/nonTrivialProjectionInSuperType.kt"
}
task funInterface_kt43887(type: KonanLocalTest) {
source = "codegen/funInterface/kt43887.kt"
}
task objectExpression1(type: KonanLocalTest) {
goldValue = "aabb\n"
source = "codegen/objectExpression/expr1.kt"
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package codegen.funInterface.kt43887
import kotlin.test.*
import kotlinx.cinterop.*
typealias heap_t = IntVar
fun heap_create(size: Long): CPointer<heap_t>? = null
fun heap_alloc(heap: CPointer<heap_t>?, size: ULong): CPointer<*>? = null
fun heap_free(heap: CPointer<heap_t>?, ptr: CPointer<*>?): CPointer<BooleanVar>? = null
inline fun Heap(size: Long): CPointer<heap_t>? {
return heap_create(size)
}
inline fun <reified T : CVariable> CPointer<heap_t>?.use(f: (CPointer<T>) -> Unit) {
alloc<T>()
?.also(f)
?.also(::free)
}
inline fun <reified T : CVariable> CPointer<heap_t>?.alloc(): CPointer<T>? {
return heap_alloc(this, sizeOf<T>().toULong())?.reinterpret()
}
inline fun CPointer<heap_t>?.free(ptr: CPointer<*>?): Boolean {
return heap_free(this, ptr)?.pointed?.value ?: false
}
@Test
fun runTest(): Unit = memScoped {
val heap = Heap(1024)
heap.use<IntVar> { ptr ->
ptr.pointed.value = 40
//println("PTR ${ptr.pointed}")
}
}