[Wasm] Reuse Callable reference and SAM lowerings from JS

This commit is contained in:
Svyatoslav Kuzmich
2021-10-06 15:23:55 +03:00
parent fbbd436e54
commit 9ef899ef10
80 changed files with 74 additions and 441 deletions
@@ -223,11 +223,15 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
extensionReceiverParameter = superMethod.extensionReceiverParameter?.copyTo(this)
valueParameters = superMethod.valueParameters.map { it.copyTo(this) }
body = context.createIrBuilder(symbol).irBlockBody {
+irReturn(irCall(wrappedFunctionClass.functions.single { it.name == OperatorNameConventions.INVOKE }).apply {
dispatchReceiver = irGetField(irGet(dispatchReceiverParameter!!), field)
extensionReceiverParameter?.let { putValueArgument(0, irGet(it)) }
valueParameters.forEachIndexed { i, parameter -> putValueArgument(extensionReceiversCount + i, irGet(parameter)) }
})
+irReturn(
irCall(
wrappedFunctionClass.functions.single { it.name == OperatorNameConventions.INVOKE }.symbol,
superMethod.returnType
).apply {
dispatchReceiver = irGetField(irGet(dispatchReceiverParameter!!), field)
extensionReceiverParameter?.let { putValueArgument(0, irGet(it)) }
valueParameters.forEachIndexed { i, parameter -> putValueArgument(extensionReceiversCount + i, irGet(parameter)) }
})
}
}
@@ -318,7 +322,7 @@ class SamEqualsHashCodeMethodsGenerator(
private fun generateHashCode(anyGenerator: MethodsFromAnyGeneratorForLowerings) {
anyGenerator.createHashCodeMethodDeclaration().apply {
val hashCode = context.irBuiltIns.functionClass.owner.functions.single{ it.isHashCode() }.symbol
val hashCode = context.irBuiltIns.functionClass.owner.functions.single { it.isHashCode() }.symbol
body = context.createIrBuilder(symbol).run {
irExprBody(
irCall(hashCode).also {
@@ -21,9 +21,7 @@ import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -120,9 +118,20 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
private val superClass = if (isSuspendLambda) context.ir.symbols.coroutineImpl.owner.defaultType else context.irBuiltIns.anyType
private var boundReceiverField: IrField? = null
private val superFunctionInterface = reference.type.classOrNull?.owner ?: error("Expected functional type")
private val referenceType = reference.type as IrSimpleType
private val superFunctionInterface: IrClass = referenceType.classOrNull?.owner ?: error("Expected functional type")
private val isKReference = superFunctionInterface.name.identifier[0] == 'K'
// If we implement KFunctionN we also need FunctionN
private val secondFunctionInterface: IrClass? = if (isKReference) {
val arity = referenceType.arguments.size - 1
if (function.isSuspend)
context.ir.symbols.suspendFunctionN(arity).owner
else
context.ir.symbols.functionN(arity).owner
} else null
private fun StringBuilder.collectNamesForLambda(d: IrDeclarationWithName) {
val parent = d.parent
@@ -167,7 +176,7 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
origin = if (isKReference || !isLambda) FUNCTION_REFERENCE_IMPL else LAMBDA_IMPL
name = makeContextDependentName()
}.apply {
superTypes = listOf(superClass, reference.type)
superTypes = listOfNotNull(superClass, referenceType, secondFunctionInterface?.symbol?.typeWithArguments(referenceType.arguments))
// if (samSuperType == null)
// superTypes += functionSuperClass.typeWith(parameterTypes)
// if (irFunctionReference.isSuspend) superTypes += context.ir.symbols.suspendFunctionInterface.defaultType
@@ -241,7 +250,14 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
isSuspend = superMethod.isSuspend
isOperator = superMethod.isOperator
}.apply {
overriddenSymbols = listOf(superMethod.symbol)
val secondSuperMethods: List<IrSimpleFunction>? =
secondFunctionInterface?.declarations?.filterIsInstance<IrSimpleFunction>()
val secondSuperMethod = secondSuperMethods?.single { it.name.asString() == "invoke" }
overriddenSymbols = listOfNotNull(
superMethod.symbol,
secondSuperMethod?.symbol
)
dispatchReceiverParameter = buildReceiverParameter(this, clazz.origin, clazz.defaultType, startOffset, endOffset)
if (isLambda) createLambdaInvokeMethod() else createFunctionReferenceInvokeMethod()
@@ -391,7 +407,10 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
private fun createNameProperty(clazz: IrClass) {
if (!isKReference) return
val superProperty = superFunctionInterface.declarations.filterIsInstance<IrProperty>().single()
val superProperty = superFunctionInterface.declarations
.filterIsInstance<IrProperty>()
.single { it.name == Name.identifier("name") } // In K/Wasm interfaces can have fake overridden properties from Any
val supperGetter = superProperty.getter ?: error("Expected getter for KFunction.name property")
val nameProperty = clazz.addProperty() {
@@ -206,7 +206,7 @@ class InteropCallableReferenceLowering(val context: JsIrBackendContext) : BodyLo
newDeclarations: MutableList<IrDeclaration>
): IrBlockBody {
val invokeFun = lambdaClass.declarations.filterIsInstance<IrSimpleFunction>().single { it.name.asString() == "invoke" }
val superInvokeFun = invokeFun.overriddenSymbols.single { it.owner.isSuspend == invokeFun.isSuspend }.owner
val superInvokeFun = invokeFun.overriddenSymbols.first { it.owner.isSuspend == invokeFun.isSuspend }.owner
val lambdaName = Name.identifier("${lambdaClass.name.asString()}\$lambda")
val superClass = superInvokeFun.parentAsClass
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.lower.SingleAbstractMethodLowering
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
@@ -22,7 +23,7 @@ import org.jetbrains.kotlin.ir.util.file
import org.jetbrains.kotlin.ir.util.parentClassOrNull
import org.jetbrains.kotlin.ir.util.render
class JsSingleAbstractMethodLowering(context: JsIrBackendContext) : SingleAbstractMethodLowering(context), BodyLoweringPass {
class JsSingleAbstractMethodLowering(context: CommonBackendContext) : SingleAbstractMethodLowering(context), BodyLoweringPass {
override fun getWrapperVisibility(expression: IrTypeOperatorCall, scopes: List<ScopeWithIr>): DescriptorVisibility =
DescriptorVisibilities.LOCAL
@@ -186,11 +186,18 @@ private val propertyReferenceLowering = makeWasmModulePhase(
)
private val callableReferencePhase = makeWasmModulePhase(
::WasmCallableReferenceLowering,
::CallableReferenceLowering,
name = "WasmCallableReferenceLowering",
description = "Handle callable references"
)
private val singleAbstractMethodPhase = makeWasmModulePhase(
::JsSingleAbstractMethodLowering,
name = "SingleAbstractMethod",
description = "Replace SAM conversions with instances of interface-implementing classes"
)
private val localDelegatedPropertiesLoweringPhase = makeWasmModulePhase(
{ LocalDelegatedPropertiesLowering() },
name = "LocalDelegatedPropertiesLowering",
@@ -455,6 +462,7 @@ val wasmPhases = NamedCompilerPhase(
sharedVariablesLoweringPhase then
propertyReferenceLowering then
callableReferencePhase then
singleAbstractMethodPhase then
localDelegatedPropertiesLoweringPhase then
localDeclarationsLoweringPhase then
localClassExtractionPhase then
@@ -52,6 +52,15 @@ fun compileWasm(
ExternalDependenciesGenerator(symbolTable, listOf(deserializer)).generateUnboundSymbolsAsDependencies()
}
// Preloading function interfaces that will potentially be referenced by IR lowering.
// TODO: Do a smart preload based on what references we have in IR and support big arity
repeat(22) {
irBuiltIns.functionN(it)
irBuiltIns.kFunctionN(it)
irBuiltIns.kSuspendFunctionN(it)
irBuiltIns.suspendFunctionN(it)
}
val irFiles = allModules.flatMap { it.files }
moduleFragment.files.clear()
moduleFragment.files += irFiles
@@ -1,308 +0,0 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.wasm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.backend.common.ir.isSuspend
import org.jetbrains.kotlin.backend.common.ir.moveBodyTo
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
/**
* TODO: Temporary lowering stub. Needs to be redone.
* This is a copy of JVM lowering, but parts that don't compile are commented out.
* Turns out this works decently as a stub in most tests.
*/
val IrStatementOrigin?.isLambda: Boolean
get() = this == IrStatementOrigin.LAMBDA || this == IrStatementOrigin.ANONYMOUS_FUNCTION
// Originally copied from K/Native
internal class WasmCallableReferenceLowering(private val context: WasmBackendContext) : FileLoweringPass,
IrElementTransformerVoidWithContext() {
// This pass ignores suspend function references and function references used in inline arguments to inline functions.
private val ignoredFunctionReferences = mutableSetOf<IrFunctionReference>()
private val IrFunctionReference.isIgnored: Boolean
get() = (!type.isFunctionOrKFunction() || ignoredFunctionReferences.contains(this)) && !isSuspendCallableReference()
// TODO: Currently, origin of callable references is null. Do we need to create one?
private fun IrFunctionReference.isSuspendCallableReference(): Boolean = isSuspend && origin == null
override fun lower(irFile: IrFile) {
// ignoredFunctionReferences.addAll(IrInlineReferenceLocator.scan(context, irFile))
irFile.transformChildrenVoid(this)
}
override fun visitBlock(expression: IrBlock): IrExpression {
if (!expression.origin.isLambda)
return super.visitBlock(expression)
val reference = expression.statements.last() as IrFunctionReference
if (reference.isIgnored)
return super.visitBlock(expression)
expression.statements.dropLast(1).forEach { it.transform(this, null) }
reference.transformChildrenVoid(this)
return FunctionReferenceBuilder(reference).build()
}
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
expression.transformChildrenVoid(this)
return if (expression.isIgnored) expression else FunctionReferenceBuilder(expression).build()
}
// Handle SAM conversions which wrap a function reference:
// class sam$n(private val receiver: R) : Interface { override fun method(...) = receiver.target(...) }
//
// This avoids materializing an invokable KFunction representing, thus producing one less class.
// This is actually very common, as `Interface { something }` is a local function + a SAM-conversion
// of a reference to it into an implementation.
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression {
if (expression.operator == IrTypeOperator.SAM_CONVERSION) {
val invokable = expression.argument
val reference = if (invokable is IrFunctionReference) {
invokable
} else if (invokable is IrBlock && invokable.origin.isLambda && invokable.statements.last() is IrFunctionReference) {
invokable.statements.dropLast(1).forEach { it.transform(this, null) }
invokable.statements.last() as IrFunctionReference
} else {
return super.visitTypeOperator(expression)
}
reference.transformChildrenVoid()
return FunctionReferenceBuilder(reference, expression.typeOperand).build()
}
return super.visitTypeOperator(expression)
}
private inner class FunctionReferenceBuilder(val irFunctionReference: IrFunctionReference, val samSuperType: IrType? = null) {
private val isLambda = irFunctionReference.origin.isLambda
private val callee = irFunctionReference.symbol.owner
// Only function references can bind a receiver and even then we can only bind either an extension or a dispatch receiver.
// However, when we bind a value of an inline class type as a receiver, the receiver will turn into an argument of
// the function in question. Yet we still need to record it as the "receiver" in CallableReference in order for reflection
// to work correctly.
private val boundReceiver: Pair<IrValueParameter, IrExpression>? = irFunctionReference.getArgumentsWithIr().singleOrNull()
// The type of the reference is KFunction<in A1, ..., in An, out R>
private val parameterTypes = (irFunctionReference.type as IrSimpleType).arguments.map { (it as IrTypeProjection).type }
private val argumentTypes = parameterTypes.dropLast(1)
private val referenceReturnType = parameterTypes.last()
private val typeArgumentsMap = irFunctionReference.typeSubstitutionMap
private val functionSuperClass =
samSuperType?.classOrNull
?: if (irFunctionReference.isSuspend)
context.ir.symbols.suspendFunctionN(argumentTypes.size)
else
context.ir.symbols.functionN(argumentTypes.size)
private val superMethod =
functionSuperClass.functions.single { it.owner.modality == Modality.ABSTRACT }
// TODO(WASM)
// private val superType =
// samSuperType ?: (if (isLambda) context.ir.symbols.lambdaClass else context.ir.symbols.functionReference).defaultType
private val functionReferenceClass = context.irFactory.buildClass {
setSourceRange(irFunctionReference)
visibility = DescriptorVisibilities.LOCAL
// A callable reference results in a synthetic class, while a lambda is not synthetic.
// We don't produce GENERATED_SAM_IMPLEMENTATION, which is always synthetic.
// TODO(WASM)
// origin = if (isLambda) JvmLoweredDeclarationOrigin.LAMBDA_IMPL else JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
name = SpecialNames.NO_NAME_PROVIDED
}.apply {
parent = currentDeclarationParent!!
// TODO(WASM)
// superTypes += superType
if (samSuperType == null)
superTypes += functionSuperClass.typeWith(parameterTypes)
// TODO(WASM)
// if (irFunctionReference.isSuspend) superTypes += context.ir.symbols.suspendFunctionInterface.defaultType
createImplicitParameterDeclarationWithWrappedDescriptor()
copyAttributes(irFunctionReference)
if (isLambda) {
this.metadata = irFunctionReference.symbol.owner.metadata
}
addField("receiver", context.irBuiltIns.anyNType)
}
// WASM(TODO)
// private val receiverFieldFromSuper = context.ir.symbols.functionReferenceReceiverField.owner
//
// val fakeOverrideReceiverField = functionReferenceClass.addField {
// name = receiverFieldFromSuper.name
// origin = IrDeclarationOrigin.FAKE_OVERRIDE
// type = receiverFieldFromSuper.type
// isFinal = receiverFieldFromSuper.isFinal
// isStatic = receiverFieldFromSuper.isStatic
// visibility = receiverFieldFromSuper.visibility
// }
fun build(): IrExpression = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol).run {
irBlock {
val constructor = createConstructor()
createInvokeMethod(
if (samSuperType != null && boundReceiver != null) {
irTemporary(boundReceiver.second)
} else null
)
// WASM(TODO)
// if (!isLambda && samSuperType == null) {
// createGetSignatureMethod(this@run.irSymbols.functionReferenceGetSignature.owner)
// createGetNameMethod(this@run.irSymbols.functionReferenceGetName.owner)
// createGetOwnerMethod(this@run.irSymbols.functionReferenceGetOwner.owner)
// }
+functionReferenceClass
+irCall(constructor.symbol).apply {
if (valueArgumentsCount > 0) putValueArgument(0, boundReceiver!!.second)
}
}
}
private fun createConstructor(): IrConstructor =
functionReferenceClass.addConstructor {
// origin = JvmLoweredDeclarationOrigin.GENERATED_MEMBER_IN_CALLABLE_REFERENCE
returnType = functionReferenceClass.defaultType
isPrimary = true
}.apply {
// Add receiver parameter for bound function references
if (samSuperType == null) {
boundReceiver?.first?.let { param ->
valueParameters += param.copyTo(
irFunction = this,
index = 0,
type = param.type.substitute(typeArgumentsMap)
)
}
}
// Super constructor:
// - For SAM references, the super class is Any
// - For function references with bound receivers, accepts arity and receiver
// - For lambdas and function references without bound receivers, accepts arity
// WASM_TODO
// val constructor = if (samSuperType != null) {
// context.irBuiltIns.anyClass.owner.constructors.single()
// } else {
// superType.getClass()!!.constructors.single {
// it.valueParameters.size == if (boundReceiver != null) 2 else 1
// }
// }
val constructor = context.irBuiltIns.anyClass.owner.constructors.single()
body = context.createIrBuilder(symbol).irBlockBody(startOffset, endOffset) {
+irDelegatingConstructorCall(constructor).apply {
// WASM_TODO
// if (samSuperType == null) {
// putValueArgument(0, irInt(argumentTypes.size + if (irFunctionReference.isSuspend) 1 else 0))
// if (boundReceiver != null)
// putValueArgument(1, irGet(valueParameters.first()))
// }
}
+IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, context.irBuiltIns.unitType)
if (samSuperType == null && boundReceiver != null) {
+irSetField(
irGet(functionReferenceClass.thisReceiver!!),
functionReferenceClass.fields.first(),
irGet(valueParameters.first())
)
}
}
}
private fun createInvokeMethod(receiverVar: IrValueDeclaration?): IrSimpleFunction =
functionReferenceClass.addFunction {
setSourceRange(if (isLambda) callee else irFunctionReference)
name = superMethod.owner.name
returnType = callee.returnType
isSuspend = callee.isSuspend
}.apply {
overriddenSymbols += superMethod
dispatchReceiverParameter = parentAsClass.thisReceiver!!.copyTo(this)
if (isLambda) createLambdaInvokeMethod() else createFunctionReferenceInvokeMethod(receiverVar)
}
// Inline the body of an anonymous function into the generated lambda subclass.
private fun IrSimpleFunction.createLambdaInvokeMethod() {
annotations += callee.annotations
val valueParameterMap = callee.explicitParameters.withIndex().associate { (index, param) ->
param to param.copyTo(this, index = index)
}
valueParameters += valueParameterMap.values
body = callee.moveBodyTo(this, valueParameterMap)
}
private fun IrSimpleFunction.createFunctionReferenceInvokeMethod(receiver: IrValueDeclaration?) {
for ((index, argumentType) in argumentTypes.withIndex()) {
addValueParameter {
name = Name.identifier("p$index")
type = argumentType
}
}
body = context.createIrBuilder(symbol, startOffset, endOffset).run {
var unboundIndex = 0
val call = irCall(callee.symbol, referenceReturnType).apply {
for (typeParameter in irFunctionReference.symbol.owner.allTypeParameters) {
putTypeArgument(typeParameter.index, typeArgumentsMap[typeParameter.symbol])
}
for (parameter in callee.explicitParameters) {
when {
boundReceiver?.first == parameter ->
// Bound receiver parameter. For function references, this is stored in a field of the superclass.
// For sam references, we just capture the value in a local variable and LocalDeclarationsLowering
// will put it into a field.
if (samSuperType == null)
irImplicitCast(
irGetField(
irGet(dispatchReceiverParameter!!),
functionReferenceClass.fields.first(),
),
boundReceiver.second.type
)
else
irGet(receiver!!)
unboundIndex >= argumentTypes.size ->
// Default value argument (this pass doesn't handle suspend functions, otherwise
// it could also be the continuation argument)
null
else ->
irGet(valueParameters[unboundIndex++])
}?.let { putArgument(callee, parameter, it) }
}
}
irExprBody(call)
}
}
}
}
@@ -274,7 +274,7 @@ fun loadIr(
val createFunctionFactoryCallback =
if (loadFunctionInterfacesIntoStdlib) {
{ packageFragmentDescriptor: PackageFragmentDescriptor ->
IrFileImpl(NaiveSourceBasedFileEntryImpl("[K][Suspend]Functions"), packageFragmentDescriptor, stdlibModule)
IrFileImpl(NaiveSourceBasedFileEntryImpl("${packageFragmentDescriptor.fqName}-[K][Suspend]Functions"), packageFragmentDescriptor, stdlibModule)
.also { stdlibModule.files += it }
}
} else {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: UNKNOWN
// SKIP_SOURCEMAP_REMAPPING
fun box(): String {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: COROUTINES
// !LANGUAGE: +SuspendConversion
// FILE: suspendCovnersion.kt
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: CLASS_REFERENCES
class C {
fun OK() {}
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: IGNORED_IN_JS
fun box(): String {
fun OK() {}
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// WASM_MUTE_REASON: STDLIB_SORT
// WITH_RUNTIME
// SKIP_DCE_DRIVEN
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
fun interface Foo {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// FILE: lib.kt
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// WASM_MUTE_REASON: BRIDGE_ISSUES
// CHECK_BYTECODE_TEXT
// 0 java/lang/invoke/LambdaMetafactory
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// WASM_MUTE_REASON: BRIDGE_ISSUES
// CHECK_BYTECODE_TEXT
// 0 java/lang/invoke/LambdaMetafactory
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// WASM_MUTE_REASON: BRIDGE_ISSUES
// CHECK_BYTECODE_TEXT
// 0 java/lang/invoke/LambdaMetafactory
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// WASM_MUTE_REASON: IGNORED_IN_JS
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6
// FILE: test.kt
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// WASM_MUTE_REASON: IGNORED_IN_JS
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6
// FILE: test.kt
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// WASM_MUTE_REASON: IGNORED_IN_JS
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6
// FILE: test.kt
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// WASM_MUTE_REASON: IGNORED_IN_JS
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6
fun checkEqual(x: Any, y: Any) {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument
fun interface MyRunnable {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
fun interface Action {
fun run()
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
fun interface Base {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// IGNORE_BACKEND: JS_IR_ES6
fun interface FunWithReceiver {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// WITH_RUNTIME
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// WASM_MUTE_REASON: IGNORED_IN_JS
// IGNORE_BACKEND: JS, JS_IR
// IGNORE_BACKEND: JS_IR_ES6
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
fun interface A {
fun invoke(s: String)
@@ -1,6 +1,4 @@
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
private fun interface Listener {
fun onChanged(): String
@@ -1,5 +1,4 @@
// WITH_RUNTIME
// IGNORE_BACKEND: WASM
class C : Comparable<C> {
override fun compareTo(other: C): Int = 0
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// MODULE: m1
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// NO_OPTIMIZED_CALLABLE_REFERENCES
fun interface P {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
interface I {
fun inherited(s: String): String = privateInherited(s)
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// WITH_RUNTIME
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// WITH_RUNTIME
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// This test should check argument coercion between the SAM and the lambda.
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
// WITH_RUNTIME
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +FunctionalInterfaceConversion
fun interface S {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
fun interface FunIFace<T, R> {
fun call(ic: T): R
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// WASM_MUTE_REASON: IGNORED_IN_JS
// IGNORE_BACKEND: JS, JS_IR
// IGNORE_BACKEND: JS_IR_ES6
@@ -1,6 +1,5 @@
// !LANGUAGE: +UnrestrictedBuilderInference
// WITH_RUNTIME
// IGNORE_BACKEND: WASM
import kotlin.experimental.ExperimentalTypeInference
@@ -1,5 +1,4 @@
// WITH_RUNTIME
// IGNORE_BACKEND: WASM
// !LANGUAGE: -StrictOnlyInputTypesChecks
import kotlin.experimental.ExperimentalTypeInference
@@ -1,7 +1,6 @@
// WITH_RUNTIME
// SKIP_TXT
// !DIAGNOSTICS: -CAST_NEVER_SUCCEEDS -UNCHECKED_CAST -UNUSED_PARAMETER -UNUSED_VARIABLE -OPT_IN_USAGE_ERROR -UNUSED_EXPRESSION
// IGNORE_BACKEND: WASM
import kotlin.experimental.ExperimentalTypeInference
@@ -1,5 +1,4 @@
// WITH_RUNTIME
// IGNORE_BACKEND: WASM
// !LANGUAGE: -StrictOnlyInputTypesChecks
import kotlin.experimental.ExperimentalTypeInference
@@ -1,5 +1,4 @@
// WITH_RUNTIME
// IGNORE_BACKEND: WASM
import kotlin.experimental.ExperimentalTypeInference
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: COROUTINES
// Issues: KT-33542, KT-33544
// WITH_RUNTIME
// !LANGUAGE: +NewInference
-2
View File
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: COROUTINES
// !LANGUAGE: +NewInference
// !OPT_IN: kotlin.RequiresOptIn
// WITH_RUNTIME
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: COROUTINES
// WITH_RUNTIME
import kotlin.experimental.ExperimentalTypeInference
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: COROUTINES
// WITH_RUNTIME
// !LANGUAGE: +NewInference
@@ -1,5 +1,5 @@
// WITH_RUNTIME
// IGNORE_BACKEND: WASM
inline class Result<T>(val isSuccess: Boolean)
@@ -1,6 +1,5 @@
// WITH_RUNTIME
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
fun interface ResultHandler<T> {
fun onResult(result: Result<T>)
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
// !LANGUAGE: +InlineClasses
inline class A(val value: String)
@@ -1,5 +1,4 @@
// WITH_RUNTIME
// IGNORE_BACKEND: WASM
// IGNORE_BACKEND: JVM
inline class Result<T>(val isSuccess: Boolean)
@@ -1,6 +1,5 @@
// WITH_RUNTIME
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
fun interface ResultHandler<T> {
@Suppress("RESULT_CLASS_IN_RETURN_TYPE")
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: BRIDGE_ISSUES
// !LANGUAGE: +InlineClasses
// WITH_RUNTIME
import kotlin.test.*
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
// MODULE: lib
// FILE: lib.kt
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +InlineClasses
fun <T> underlying(a: IC): T = bar(a) {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +InlineClasses
fun <T> underlying(a: IC): T = bar(a) {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +InlineClasses
fun <T> underlying(a: IC): T = bar(a) {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +InlineClasses
fun <T> underlying(a: IC): T = bar(a) {
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +InlineClasses
// WITH_RUNTIME
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +InlineClasses
fun <T1> underlying(a: IC): T1 = bar(a) { it.value as T1 }
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +InlineClasses
// WITH_RUNTIME
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +InlineClasses
// WITH_RUNTIME
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// !LANGUAGE: +InlineClasses
fun <T> underlying(a: IC): T = bar(a) {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: WASM
interface X
interface Z
@@ -1,5 +1,5 @@
// IGNORE_BACKEND: WASM
// WASM_MUTE_REASON: SAM_CONVERSIONS
// WASM_MUTE_REASON: STDLIB_SORT
// WITH_RUNTIME
// SKIP_DCE_DRIVEN
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
// !LANGUAGE: +SuspendConversion
// !DIAGNOSTICS: -UNUSED_PARAMETER
@@ -1,5 +1,4 @@
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
// !DIAGNOSTICS: -UNUSED_PARAMETER
@@ -1,6 +1,5 @@
// !LANGUAGE: +SuspendConversion
// !DIAGNOSTICS: -UNUSED_PARAMETER
// IGNORE_BACKEND: WASM
fun foo1(f: suspend () -> Unit) {}
fun bar1() {}
@@ -1,7 +1,6 @@
// !LANGUAGE: +SuspendConversion
// !DIAGNOSTICS: -UNUSED_PARAMETER
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
var foo1 = false
var foo2 = false
@@ -2,7 +2,6 @@
// !LANGUAGE: +SuspendConversion
// !DIAGNOSTICS: -UNUSED_PARAMETER
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
fun foo(f: () -> String, g: suspend () -> String, h: suspend () -> String) {}
@@ -1,7 +1,6 @@
// !LANGUAGE: +SuspendConversion
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
// IGNORE_BACKEND_FIR: JVM_IR
fun interface Runnable {
@@ -1,7 +1,6 @@
// !LANGUAGE: +SuspendConversion
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
// WITH_RUNTIME
// IGNORE_BACKEND: WASM
// IGNORE_BACKEND_FIR: JVM_IR
object Test1 {
@@ -2,7 +2,6 @@
// !LANGUAGE: +SuspendConversion
// !DIAGNOSTICS: -UNUSED_PARAMETER
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
// IGNORE_BACKEND_FIR: JVM_IR
fun useSuspendVararg(vararg sfn: suspend () -> Unit) {}
@@ -1,7 +1,6 @@
// FIR_IDENTICAL
// !LANGUAGE: +SuspendConversion
// !DIAGNOSTICS: -UNUSED_PARAMETER
// IGNORE_BACKEND: WASM
fun unitCoercion(f: suspend () -> Unit) {}
fun foo(): Int = 0
@@ -10,7 +10,7 @@ package kotlin.wasm.internal
import kotlin.UnsupportedOperationException
import kotlin.reflect.*
internal open class KProperty0Impl<out R>(override val name: String, override val returnType: KType, val getter: () -> R) : KProperty0<R> {
internal open class KProperty0Impl<out R>(override val name: String, val returnType: KType, val getter: () -> R) : KProperty0<R> {
override fun get(): R {
return getter()
}
@@ -34,7 +34,7 @@ internal open class KProperty0Impl<out R>(override val name: String, override va
}
}
internal open class KProperty1Impl<T, out R>(override val name: String, override val returnType: KType, val getter: (T) -> R) : KProperty1<T, R> {
internal open class KProperty1Impl<T, out R>(override val name: String, val returnType: KType, val getter: (T) -> R) : KProperty1<T, R> {
override fun get(receiver: T): R {
return getter(receiver)
}
@@ -58,7 +58,7 @@ internal open class KProperty1Impl<T, out R>(override val name: String, override
}
}
internal open class KProperty2Impl<T1, T2, out R>(override val name: String, override val returnType: KType, val getter: (T1, T2) -> R) :
internal open class KProperty2Impl<T1, T2, out R>(override val name: String, val returnType: KType, val getter: (T1, T2) -> R) :
KProperty2<T1, T2, R> {
override fun get(receiver1: T1, receiver2: T2): R {
return getter(receiver1, receiver2)
@@ -146,7 +146,7 @@ internal class KMutableProperty2Impl<T1, T2, R>(name: String, returnType: KType,
}
}
internal open class KLocalDelegatedPropertyImpl<out R>(override val name: String, override val returnType: KType) : KProperty0<R> {
internal open class KLocalDelegatedPropertyImpl<out R>(override val name: String, val returnType: KType) : KProperty0<R> {
override fun get(): R {
throw UnsupportedOperationException("Not supported for local property reference.")
}
@@ -20,10 +20,4 @@ public actual interface KCallable<out R> {
* the setter, similarly, will have the name "<set-foo>".
*/
actual public val name: String
/**
* The type of values returned by this callable.
*/
public val returnType: KType
}