From 4942ed5e7ae4ad79ff8b596d85952e9f431a4013 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Wed, 19 Sep 2018 15:40:13 +0300 Subject: [PATCH] Clean up backend.common.ir.IrUtils.kt --- .../common/descriptors/WrappedDescriptors.kt | 13 ++-- .../kotlin/backend/common/ir/IrUtils.kt | 71 ++++++++++--------- .../lower/DefaultArgumentStubGenerator.kt | 4 +- .../common/lower/LocalDeclarationsLowering.kt | 11 ++- .../ir/backend/js/JsDeclarationFactory.kt | 7 +- .../backend/js/lower/SecondaryCtorLowering.kt | 8 +-- .../coroutines/SuspendFunctionsLowering.kt | 3 +- .../jvm/lower/SyntheticAccessorLowering.kt | 4 +- .../declarations/lazy/IrLazyFunctionBase.kt | 8 ++- .../org/jetbrains/kotlin/ir/types/irTypes.kt | 8 ++- .../box/syntheticAccessors/jvmField.kt | 1 + 11 files changed, 75 insertions(+), 63 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt index fbf38fdf249..78ceda5fcc5 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/WrappedDescriptors.kt @@ -14,10 +14,12 @@ import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.scopes.LazyScopeAdapter import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.TypeIntersectionScope import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver import org.jetbrains.kotlin.storage.LockBasedStorageManager +import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.types.* @@ -168,15 +170,18 @@ open class WrappedTypeParameterDescriptor( private val _defaultType: SimpleType by lazy { KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( Annotations.EMPTY, typeConstructor, emptyList(), false, - TypeIntersectionScope.create( - "Scope for type parameter " + name.asString(), - upperBounds - ) + LazyScopeAdapter(LockBasedStorageManager.NO_LOCKS.createLazyValue { + TypeIntersectionScope.create( + "Scope for type parameter " + name.asString(), + upperBounds + ) + }) ) } override fun getDefaultType() = _defaultType + override fun getContainingDeclaration() = (owner.parent as IrDeclaration).descriptor override fun accept(visitor: DeclarationDescriptorVisitor?, data: D): R = diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt index 9c01cc22044..72bf49fe4de 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/IrUtils.kt @@ -23,7 +23,6 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl @@ -160,7 +159,7 @@ fun IrValueParameter.copyTo( endOffset: Int = this.endOffset, origin: IrDeclarationOrigin = this.origin, name: Name = this.name, - type: IrType = this.type.maybeReplace(this.parent as IrTypeParametersContainer, irFunction), + type: IrType = this.type.remapTypeParameters(this.parent as IrTypeParametersContainer, irFunction), varargElementType: IrType? = this.varargElementType ): IrValueParameter { val descriptor = WrappedValueParameterDescriptor(symbol.descriptor.annotations, symbol.descriptor.source) @@ -174,17 +173,23 @@ fun IrValueParameter.copyTo( } } -fun IrTypeParameter.copyTo(irFunction: IrFunction, shift: Int = 0): IrTypeParameter { - // TODO: Copy IrTypeParameter with type remapping +fun IrTypeParameter.copyToWithoutSuperTypes( + target: IrTypeParametersContainer, + shift: Int = 0, + origin: IrDeclarationOrigin = this.origin +): IrTypeParameter { + val source = parent as IrTypeParametersContainer val descriptor = WrappedTypeParameterDescriptor(symbol.descriptor.annotations, symbol.descriptor.source) val symbol = IrTypeParameterSymbolImpl(descriptor) - return IrTypeParameterImpl(startOffset, endOffset, origin, symbol, name, shift + index, isReified, variance).also { - descriptor.bind(it) - it.parent = irFunction + return IrTypeParameterImpl(startOffset, endOffset, origin, symbol, name, shift + index, isReified, variance).also { copied -> + descriptor.bind(copied) + copied.parent = target } } fun IrFunction.copyParameterDeclarationsFrom(from: IrFunction) { + assert(typeParameters.isEmpty()) + copyTypeParametersFrom(from) // TODO: should dispatch receiver be copied? dispatchReceiverParameter = from.dispatchReceiverParameter?.let { @@ -196,39 +201,32 @@ fun IrFunction.copyParameterDeclarationsFrom(from: IrFunction) { val shift = valueParameters.size valueParameters += from.valueParameters.map { it.copyTo(this, shift) } - - assert(typeParameters.isEmpty()) - from.typeParameters.mapTo(typeParameters) { it.copyTo(this) } } fun IrTypeParametersContainer.copyTypeParametersFrom( source: IrTypeParametersContainer, - origin: IrDeclarationOrigin + origin: IrDeclarationOrigin? = null ) { val target = this - assert(target.typeParameters.isEmpty()) + val shift = target.typeParameters.size + // Any type parameter can figure in a boundary type for any other parameter. + // Therefore, we first copy the parameters themselves, then set up their supertypes. source.typeParameters.forEachIndexed { i, sourceParameter -> assert(sourceParameter.index == i) - val tpDescriptor = WrappedTypeParameterDescriptor() - target.typeParameters.add( - IrTypeParameterImpl( - UNDEFINED_OFFSET, - UNDEFINED_OFFSET, - origin, - IrTypeParameterSymbolImpl(tpDescriptor), - sourceParameter.name, - sourceParameter.index, - sourceParameter.isReified, - sourceParameter.variance - ).apply { - tpDescriptor.bind(this) - parent = target - sourceParameter.superTypes.forEach { - // Using the already copied portion of target.typeParameters. - superTypes.add(it.maybeReplace(source, target)) - } - } - ) + target.typeParameters.add(sourceParameter.copyToWithoutSuperTypes(target, shift = shift, origin = origin ?: sourceParameter.origin)) + } + source.typeParameters.zip(target.typeParameters.drop(shift)).forEach { (srcParameter, dstParameter) -> + dstParameter.copySuperTypesFrom(srcParameter) + } +} + +private fun IrTypeParameter.copySuperTypesFrom(source: IrTypeParameter) { + val target = this + val sourceParent = source.parent as IrTypeParametersContainer + val targetParent = target.parent as IrTypeParametersContainer + val shift = target.index - source.index + source.superTypes.forEach { + target.superTypes.add(it.remapTypeParameters(sourceParent, targetParent, shift)) } } @@ -275,13 +273,14 @@ fun IrFunction.copyValueParametersToStatic( Type parameters should correspond to the function where they are defined. `source` is where the type is originally taken from. */ -fun IrType.maybeReplace(source: IrTypeParametersContainer, target: IrTypeParametersContainer): IrType = +fun IrType.remapTypeParameters(source: IrTypeParametersContainer, target: IrTypeParametersContainer, shift: Int = 0): IrType = when (this) { is IrSimpleType -> { val classifier = classifier.owner when { classifier is IrTypeParameter && classifier.parent == source -> - target.typeParameters[classifier.index].defaultType + target.typeParameters[classifier.index + shift].defaultType + classifier is IrClass -> IrSimpleTypeImpl( classifier.symbol, @@ -289,7 +288,7 @@ fun IrType.maybeReplace(source: IrTypeParametersContainer, target: IrTypeParamet arguments.map { when (it) { is IrTypeProjection -> makeTypeProjection( - it.type.maybeReplace(source, target), + it.type.remapTypeParameters(source, target, shift), it.variance ) else -> it @@ -297,8 +296,10 @@ fun IrType.maybeReplace(source: IrTypeParametersContainer, target: IrTypeParamet }, annotations ) + else -> this } } else -> this } + diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt index 6c5627f5708..9cfba752a95 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/DefaultArgumentStubGenerator.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDesc import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.IrElement @@ -372,8 +373,8 @@ private fun IrFunction.generateDefaultsFunctionImpl(context: CommonBackendContex ) } + newFunction.copyTypeParametersFrom(this) val newValueParameters = valueParameters.map { it.copyTo(newFunction) } + syntheticParameters - val newTypeParameters = typeParameters.map { it.copyTo(newFunction) } newFunction.returnType = returnType newFunction.dispatchReceiverParameter = dispatchReceiverParameter?.run { @@ -381,7 +382,6 @@ private fun IrFunction.generateDefaultsFunctionImpl(context: CommonBackendContex } newFunction.extensionReceiverParameter = extensionReceiverParameter?.copyTo(newFunction) newFunction.valueParameters += newValueParameters - newFunction.typeParameters += newTypeParameters annotations.mapTo(newFunction.annotations) { it.deepCopyWithSymbols() } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt index 58507f80fc0..ce6eca651a4 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass import org.jetbrains.kotlin.backend.common.descriptors.* import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl @@ -516,15 +517,13 @@ class LocalDeclarationsLowering( newDeclaration.parent = memberOwner newDeclaration.returnType = oldDeclaration.returnType + newDeclaration.copyTypeParametersFrom(oldDeclaration) newDeclaration.dispatchReceiverParameter = newDispatchReceiverParameter newDeclaration.extensionReceiverParameter = oldDeclaration.extensionReceiverParameter?.run { copyTo(newDeclaration).also { newParameterToOld.putAbsentOrSame(it, this) } } - oldDeclaration.typeParameters.mapTo(newDeclaration.typeParameters) { - it.copyTo(newDeclaration).also { p -> p.superTypes += it.superTypes } - } newDeclaration.valueParameters += createTransformedValueParameters(capturedValues, oldDeclaration, newDeclaration) newDeclaration.recordTransformedValueParameters(localFunctionContext) @@ -596,6 +595,8 @@ class LocalDeclarationsLowering( newDeclaration.parent = localClassContext.declaration newDeclaration.returnType = oldDeclaration.returnType + newDeclaration.copyTypeParametersFrom(oldDeclaration) + // TODO: should dispatch receiver be copied? newDeclaration.dispatchReceiverParameter = oldDeclaration.dispatchReceiverParameter?.run { IrValueParameterImpl(startOffset, endOffset, origin, descriptor, type, varargElementType).also { @@ -607,10 +608,6 @@ class LocalDeclarationsLowering( throw AssertionError("constructors can't have extension receiver") } - oldDeclaration.typeParameters.mapTo(newDeclaration.typeParameters) { - it.copyTo(newDeclaration).also { p -> p.superTypes += it.superTypes } - } - newDeclaration.valueParameters += createTransformedValueParameters(capturedValues, oldDeclaration, newDeclaration) newDeclaration.recordTransformedValueParameters(constructorContext) transformedDeclarations[oldDeclaration] = newDeclaration diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDeclarationFactory.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDeclarationFactory.kt index d31707d6c5b..f914a6d6694 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDeclarationFactory.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDeclarationFactory.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.descriptors.WrappedClassConstructorDe import org.jetbrains.kotlin.backend.common.descriptors.WrappedPropertyDescriptor import org.jetbrains.kotlin.backend.common.ir.DeclarationFactory import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibility @@ -103,6 +104,8 @@ class JsDeclarationFactory : DeclarationFactory { it.returnType = oldConstructor.returnType } + newConstructor.copyTypeParametersFrom(oldConstructor) + val outerThisValueParameter = JsIrBuilder.buildValueParameter(Namer.OUTER_NAME, 0, outerThisType).also { it.parent = newConstructor } @@ -112,10 +115,6 @@ class JsDeclarationFactory : DeclarationFactory { newValueParameters += p.copyTo(newConstructor, 1) } - for (p in oldConstructor.typeParameters) { - newConstructor.typeParameters += p.copyTo(newConstructor) - } - newConstructor.valueParameters += newValueParameters return newConstructor diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt index 4a5f952d3b7..fb9142faf78 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/SecondaryCtorLowering.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.IrElement @@ -153,12 +154,11 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) { val retStmt = JsIrBuilder.buildReturn(it.symbol, JsIrBuilder.buildGetValue(thisParam.symbol), context.irBuiltIns.nothingType) val statements = (declaration.body!!.deepCopyWithSymbols(it) as IrStatementContainer).statements + it.copyTypeParametersFrom(declaration) + val newValueParameters = declaration.valueParameters.map { p -> p.copyTo(it) } - it.valueParameters += (newValueParameters + thisParam) - it.typeParameters += declaration.typeParameters.map { p -> p.copyTo(it) } - it.returnType = type it.parent = declaration.parent @@ -187,8 +187,8 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) { declaration.isInline, declaration.isExternal ).also { + it.copyTypeParametersFrom(declaration) it.valueParameters += declaration.valueParameters.map { p -> p.copyTo(it) } - it.typeParameters += declaration.typeParameters.map { p -> p.copyTo(it) } it.parent = declaration.parent it.returnType = type diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt index 8df27b67517..abbb7aa09d5 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendFunctionsLowering.kt @@ -447,13 +447,14 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo irFunction.isSuspend, IrDeclarationOrigin.FAKE_OVERRIDE ).apply { + parent = this@setSuperSymbolsAndAddFakeOverrides returnType = irFunction.returnType overriddenSymbols += irFunction.symbol copyParameterDeclarationsFrom(irFunction) } for (sm in unoverriddenSuperMembers) { - val fakeOverride = createFakeOverride(sm).also { it.parent = this } + val fakeOverride = createFakeOverride(sm) declarations += fakeOverride } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt index 3501d9347b6..c0240c235f4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt @@ -110,7 +110,7 @@ class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTrans accessor.copyTypeParametersFrom(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR) accessor.copyValueParametersToStatic(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR) - accessor.returnType = source.returnType.maybeReplace(source, accessor) + accessor.returnType = source.returnType.remapTypeParameters(source, accessor) val markerParameterDescriptor = WrappedValueParameterDescriptor() val markerParameter = IrValueParameterImpl( @@ -166,7 +166,7 @@ class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTrans accessor.copyTypeParametersFrom(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR) accessor.copyValueParametersToStatic(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR) - accessor.returnType = source.returnType.maybeReplace(source, accessor) + accessor.returnType = source.returnType.remapTypeParameters(source, accessor) accessor.body = IrExpressionBodyImpl( UNDEFINED_OFFSET, UNDEFINED_OFFSET, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunctionBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunctionBase.kt index 0aeacee4238..19147cc23cf 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunctionBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunctionBase.kt @@ -36,18 +36,20 @@ abstract class IrLazyFunctionBase( override var dispatchReceiverParameter: IrValueParameter? by lazyVar { typeTranslator.buildWithScope(this) { - descriptor.dispatchReceiverParameter?.generateReceiverParameterStub() + descriptor.dispatchReceiverParameter?.generateReceiverParameterStub()?.also { it.parent = this@IrLazyFunctionBase } } } override var extensionReceiverParameter: IrValueParameter? by lazyVar { typeTranslator.buildWithScope(this) { - descriptor.extensionReceiverParameter?.generateReceiverParameterStub() + descriptor.extensionReceiverParameter?.generateReceiverParameterStub()?.also { it.parent = this@IrLazyFunctionBase } } } override val valueParameters: MutableList by lazy { typeTranslator.buildWithScope(this) { - descriptor.valueParameters.mapTo(arrayListOf()) { stubGenerator.generateValueParameterStub(it) } + descriptor.valueParameters.mapTo(arrayListOf()) { + stubGenerator.generateValueParameterStub(it).apply { parent = this@IrLazyFunctionBase } + } } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt index abd365f4a15..1b954b18ba7 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypes.kt @@ -110,7 +110,13 @@ fun ClassifierDescriptor.toIrType(hasQuestionMark: Boolean = false, symbolTable: return IrSimpleTypeImpl(defaultType, symbol, hasQuestionMark, listOf(), listOf()) } -val IrTypeParameter.defaultType: IrType get() = symbol.owner.defaultType +val IrTypeParameter.defaultType: IrType + get() = IrSimpleTypeImpl( + symbol, + hasQuestionMark = false, + arguments = emptyList(), + annotations = emptyList() + ) fun IrClassifierSymbol.typeWith(vararg arguments: IrType): IrSimpleType = typeWith(arguments.toList()) diff --git a/compiler/testData/codegen/box/syntheticAccessors/jvmField.kt b/compiler/testData/codegen/box/syntheticAccessors/jvmField.kt index 02880f60e6e..76c38ef8d7e 100644 --- a/compiler/testData/codegen/box/syntheticAccessors/jvmField.kt +++ b/compiler/testData/codegen/box/syntheticAccessors/jvmField.kt @@ -1,4 +1,5 @@ // TARGET_BACKEND: JVM +// WITH_RUNTIME // FILE: A.kt package a