JVM IR: add InventNamesForLocalClasses pass
This commit is contained in:
@@ -12,9 +12,7 @@ import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDeclarationFactory
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager
|
||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
import org.jetbrains.kotlin.codegen.coroutines.coroutinesJvmInternalPackageFqName
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.coroutinesPackageFqName
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -24,8 +22,6 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||
|
||||
class JvmBackendContext(
|
||||
@@ -46,6 +42,18 @@ class JvmBackendContext(
|
||||
|
||||
val irIntrinsics = IrIntrinsicMethods(irBuiltIns, ir.symbols)
|
||||
|
||||
// TODO: also store info for EnclosingMethod
|
||||
internal class LocalClassInfo(val internalName: String)
|
||||
|
||||
private val localClassInfo = mutableMapOf<IrAttributeContainer, LocalClassInfo>()
|
||||
|
||||
internal fun getLocalClassInfo(container: IrAttributeContainer): LocalClassInfo? =
|
||||
localClassInfo[container.attributeOwnerId]
|
||||
|
||||
internal fun putLocalClassInfo(container: IrAttributeContainer, value: LocalClassInfo) {
|
||||
localClassInfo[container.attributeOwnerId] = value
|
||||
}
|
||||
|
||||
override var inVerbosePhase: Boolean = false
|
||||
|
||||
override val configuration get() = state.configuration
|
||||
|
||||
@@ -95,6 +95,7 @@ val jvmPhases = namedIrFilePhase<JvmBackendContext>(
|
||||
description = "IR lowering",
|
||||
lower = expectDeclarationsRemovingPhase then
|
||||
fileClassPhase then
|
||||
inventNamesForLocalClassesPhase then
|
||||
kCallableNamePropertyPhase then
|
||||
arrayConstructorPhase then
|
||||
|
||||
@@ -154,6 +155,8 @@ val jvmPhases = namedIrFilePhase<JvmBackendContext>(
|
||||
jvmBuiltinOptimizationLoweringPhase then
|
||||
additionalClassAnnotationPhase then
|
||||
|
||||
recordNamesForKotlinTypeMapperPhase then
|
||||
|
||||
// should be last transformation
|
||||
removeDeclarationsThatWouldBeInlined then
|
||||
makePatchParentsPhase(3)
|
||||
|
||||
+10
-3
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.backend.common.descriptors.isFunctionOrKFunctionType
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyTo
|
||||
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isInlineParameter
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
||||
@@ -31,15 +30,22 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineFunctionCall
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isInlineParameter
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||
import org.jetbrains.kotlin.codegen.PropertyReferenceCodegen
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addField
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
@@ -193,6 +199,7 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
|
||||
parent = referenceParent
|
||||
superTypes += functionReferenceOrLambda.owner.defaultType
|
||||
createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||
copyAttributes(irFunctionReference)
|
||||
}
|
||||
|
||||
private val argumentToFieldMap = boundCalleeParameters.associate {
|
||||
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.util.isAnonymousObject
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
|
||||
val inventNamesForLocalClassesPhase = makeIrFilePhase<JvmBackendContext>(
|
||||
{ context -> InventNamesForLocalClasses(context) },
|
||||
name = "InventNamesForLocalClasses",
|
||||
description = "Invent names for local classes and anonymous objects"
|
||||
)
|
||||
|
||||
class InventNamesForLocalClasses(private val context: JvmBackendContext) : FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.accept(NameInventor(), Data(null, false))
|
||||
}
|
||||
|
||||
/**
|
||||
* @property enclosingName JVM internal name of the enclosing class (including anonymous classes, local objects and callable references)
|
||||
* @property isLocal true if the next declaration to be encountered in the IR tree is local
|
||||
*/
|
||||
private class Data(val enclosingName: String?, val isLocal: Boolean) {
|
||||
fun withName(newName: String): Data =
|
||||
Data(newName, isLocal)
|
||||
|
||||
fun makeLocal(): Data =
|
||||
if (isLocal) this else Data(enclosingName, true)
|
||||
}
|
||||
|
||||
private inner class NameInventor : IrElementVisitor<Unit, Data> {
|
||||
private val anonymousClassesCount = mutableMapOf<String, Int>()
|
||||
private val localFunctionNames = mutableMapOf<IrFunctionSymbol, String>()
|
||||
|
||||
override fun visitClass(declaration: IrClass, data: Data) {
|
||||
if (!data.isLocal) {
|
||||
// This is not a local class, so we need not invent a name for it, the type mapper will correctly compute it
|
||||
// by navigating through its containers.
|
||||
|
||||
val internalName = data.enclosingName?.let { enclosingName ->
|
||||
"$enclosingName$${declaration.name.asString()}"
|
||||
} ?: (declaration.parent as IrFile).let { file ->
|
||||
JvmClassName.byFqNameWithoutInnerClasses(file.fqName.child(declaration.name)).internalName
|
||||
}
|
||||
|
||||
declaration.acceptChildren(this, data.withName(internalName))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
val internalName = inventName(declaration.name, data)
|
||||
context.putLocalClassInfo(declaration, JvmBackendContext.LocalClassInfo(internalName))
|
||||
|
||||
val newData = data.withName(internalName)
|
||||
|
||||
// Old backend doesn't add the anonymous object name to the stack when traversing its super constructor arguments.
|
||||
// E.g. a lambda in the super call of an object literal "foo$1" will get the name "foo$2", not "foo$1$1".
|
||||
val newDataForConstructor =
|
||||
if (declaration.isAnonymousObject) data else newData
|
||||
|
||||
for (child in declaration.declarations) {
|
||||
child.accept(this, if (child is IrConstructor) newDataForConstructor else newData)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor, data: Data) {
|
||||
// Constructor is a special case because its name "<init>" doesn't participate when creating names for local classes inside.
|
||||
declaration.acceptChildren(this, data.makeLocal())
|
||||
}
|
||||
|
||||
override fun visitDeclaration(declaration: IrDeclaration, data: Data) {
|
||||
if (declaration !is IrDeclarationWithName) {
|
||||
declaration.acceptChildren(this, data)
|
||||
return
|
||||
}
|
||||
|
||||
val enclosingName = data.enclosingName
|
||||
val simpleName = declaration.name.asString()
|
||||
|
||||
val internalName = when {
|
||||
declaration.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA -> {
|
||||
inventName(null, data).also { name ->
|
||||
// We save the name of the lambda to reuse it in the reference to it (produced by the closure conversion) later.
|
||||
localFunctionNames[(declaration as IrFunction).symbol] = name
|
||||
}
|
||||
}
|
||||
enclosingName != null -> "$enclosingName$$simpleName"
|
||||
else -> simpleName
|
||||
}
|
||||
|
||||
val newData = data.withName(internalName).makeLocal()
|
||||
if (declaration is IrProperty && declaration.isDelegated) {
|
||||
// Old backend currently reserves a name here, in case a property reference-like anonymous object will need
|
||||
// to be generated in the codegen later, which is now happening for local delegated properties in inline functions.
|
||||
// See CodegenAnnotatingVisitor.visitProperty and ExpressionCodegen.initializePropertyMetadata.
|
||||
inventName(null, newData)
|
||||
}
|
||||
|
||||
declaration.acceptChildren(this, newData)
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference, data: Data) {
|
||||
val internalName = localFunctionNames[expression.symbol] ?: inventName(null, data)
|
||||
context.putLocalClassInfo(expression, JvmBackendContext.LocalClassInfo(internalName))
|
||||
|
||||
expression.acceptChildren(this, data)
|
||||
}
|
||||
|
||||
override fun visitPropertyReference(expression: IrPropertyReference, data: Data) {
|
||||
val internalName = inventName(null, data)
|
||||
context.putLocalClassInfo(expression, JvmBackendContext.LocalClassInfo(internalName))
|
||||
|
||||
expression.acceptChildren(this, data)
|
||||
}
|
||||
|
||||
override fun visitEnumEntry(declaration: IrEnumEntry, data: Data) {
|
||||
// Although IrEnumEntry is an IrDeclaration, its name shouldn't be added to nameStack. This is because each IrEnumEntry has
|
||||
// an IrClass with the same name underneath it, and that class should obtain the name of the form "Enum$Entry",
|
||||
// not "Enum$Entry$Entry".
|
||||
declaration.acceptChildren(this, data.makeLocal())
|
||||
}
|
||||
|
||||
override fun visitValueParameter(declaration: IrValueParameter, data: Data) {
|
||||
// We skip value parameters when constructing names to replicate behavior of the old backend, but this can be safely changed.
|
||||
declaration.acceptChildren(this, data.makeLocal())
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(declaration: IrSimpleFunction, data: Data) {
|
||||
if (declaration.correspondingPropertySymbol != null) {
|
||||
// Skip adding property accessors to the name stack because the name of the property (which is a parent) is already there.
|
||||
declaration.acceptChildren(this, data.makeLocal())
|
||||
return
|
||||
}
|
||||
|
||||
super.visitSimpleFunction(declaration, data)
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField, data: Data) {
|
||||
// Skip field name because the name of the property is already there.
|
||||
declaration.acceptChildren(this, data.makeLocal())
|
||||
}
|
||||
|
||||
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer, data: Data) {
|
||||
// IrAnonymousInitializer is not an IrDeclaration, so we need to manually make all its children aware that they're local
|
||||
// and might need new invented names.
|
||||
declaration.acceptChildren(this, data.makeLocal())
|
||||
}
|
||||
|
||||
override fun visitElement(element: IrElement, data: Data) {
|
||||
element.acceptChildren(this, data)
|
||||
}
|
||||
|
||||
private fun inventName(sourceName: Name?, data: Data): String {
|
||||
val enclosingName = data.enclosingName
|
||||
check(enclosingName != null) { "There should be at least one name in the stack for every local declaration that needs a name" }
|
||||
|
||||
val simpleName = if (sourceName == null || sourceName.isSpecial) {
|
||||
val count = (anonymousClassesCount[enclosingName] ?: 0) + 1
|
||||
anonymousClassesCount[enclosingName] = count
|
||||
count.toString()
|
||||
} else {
|
||||
sourceName
|
||||
}
|
||||
|
||||
return JvmCodegenUtil.sanitizeNameIfNeeded("$enclosingName$$simpleName", context.state.languageVersionSettings)
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-7
@@ -16,12 +16,17 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildField
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.createType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
@@ -194,7 +199,7 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
||||
override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression =
|
||||
cachedKProperty(expression)
|
||||
|
||||
private fun cachedKProperty(expression: IrMemberAccessExpression): IrExpression {
|
||||
private fun cachedKProperty(expression: IrCallableReference): IrExpression {
|
||||
// Reflected implementation does not support partial application; also, cannot cache instances with arguments.
|
||||
if (expression.dispatchReceiver != null || expression.extensionReceiver != null)
|
||||
return createSpecializedKProperty(expression)
|
||||
@@ -220,7 +225,7 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
||||
// Create an instance of KProperty that uses Java reflection to locate the getter and the setter. This kind of reference
|
||||
// does not support local variables or bound receivers (e.g. `Class()::field`) and is slower, but takes up less space.
|
||||
// Example: `C::property` -> `Reflection.property1(PropertyReference1Impl(C::class, "property", "getProperty()LType;"))`.
|
||||
private fun createReflectedKProperty(expression: IrMemberAccessExpression): IrExpression {
|
||||
private fun createReflectedKProperty(expression: IrCallableReference): IrExpression {
|
||||
val referenceKind = propertyReferenceKindFor(expression)
|
||||
return context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset).run {
|
||||
irCall(referenceKind.wrapper).apply {
|
||||
@@ -247,7 +252,7 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
||||
//
|
||||
// and then `C()::property` -> `C$property$0(C())`.
|
||||
//
|
||||
private fun createSpecializedKProperty(expression: IrMemberAccessExpression): IrExpression {
|
||||
private fun createSpecializedKProperty(expression: IrCallableReference): IrExpression {
|
||||
val bound = expression.dispatchReceiver != null || expression.extensionReceiver != null
|
||||
val referenceClass = kPropertyClasses.getOrPut(PropertyClassCacheKey(expression.symbol, bound)) {
|
||||
createKPropertySubclass(expression)
|
||||
@@ -261,7 +266,7 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
||||
}
|
||||
}
|
||||
|
||||
private fun createKPropertySubclass(expression: IrMemberAccessExpression): IrClass {
|
||||
private fun createKPropertySubclass(expression: IrCallableReference): IrClass {
|
||||
val superClass = propertyReferenceKindFor(expression).interfaceSymbol.owner
|
||||
val referenceClass = buildClass {
|
||||
setSourceRange(expression)
|
||||
@@ -271,7 +276,7 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
||||
parent = irClass
|
||||
superTypes += IrSimpleTypeImpl(superClass.symbol, false, listOf(), listOf())
|
||||
createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||
}
|
||||
}.copyAttributes(expression)
|
||||
|
||||
// See propertyReferenceKindFor -- only one of them could ever be present.
|
||||
val numOfSuperArgs = if (expression.dispatchReceiver != null || expression.extensionReceiver != null) 1 else 0
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
val recordNamesForKotlinTypeMapperPhase = makeIrFilePhase<JvmBackendContext>(
|
||||
{ context -> RecordNamesForKotlinTypeMapper(context) },
|
||||
name = "RecordNamesForKotlinTypeMapper",
|
||||
description = "Record local class and anonymous object names for KotlinTypeMapper to work correctly"
|
||||
)
|
||||
|
||||
class RecordNamesForKotlinTypeMapper(private val context: JvmBackendContext) : FileLoweringPass, IrElementVisitorVoid {
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.acceptVoid(this)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
val internalName = context.getLocalClassInfo(declaration)?.internalName
|
||||
if (internalName != null) {
|
||||
// If this line fails, it means that the name invented by the JVM IR backend in InventNamesForLocalClasses is not equal
|
||||
// to the name invented by the old backend in CodegenAnnotatingVisitor. The former should likely be fixed.
|
||||
context.state.bindingTrace.record(CodegenBinding.ASM_TYPE, declaration.symbol.descriptor, Type.getObjectType(internalName))
|
||||
}
|
||||
super.visitClass(declaration)
|
||||
}
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -16,7 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.declarations
|
||||
|
||||
interface IrDeclarationParent
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
|
||||
interface IrDeclarationParent : IrElement
|
||||
|
||||
interface IrDeclarationContainer : IrDeclarationParent {
|
||||
val declarations: MutableList<IrDeclaration>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
fun foo() {
|
||||
var a = {
|
||||
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
class A {
|
||||
fun foo() {}
|
||||
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
class A {
|
||||
val foo = ""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user