[JVM IR] ProperVisibilityForCompanionObjectInstanceField

- Uncomment tests
- Add proper visibility to companion field
  + Make exception for interfaces -> they need to respect language versions 1.8
    before they can put private members there.
- Adjust synthetic accessor lowering to look for enclosing classes with access
  via companion object.
This commit is contained in:
Kristoffer Andersen
2020-01-29 11:57:59 +01:00
committed by Dmitry Petrov
parent a67d97bdf8
commit f782ea075b
6 changed files with 30 additions and 9 deletions
@@ -69,7 +69,7 @@ class JvmBackendContext(
val typeMapper = IrTypeMapper(this) val typeMapper = IrTypeMapper(this)
val methodSignatureMapper = MethodSignatureMapper(this) val methodSignatureMapper = MethodSignatureMapper(this)
override val declarationFactory: JvmDeclarationFactory = JvmDeclarationFactory(methodSignatureMapper) override val declarationFactory: JvmDeclarationFactory = JvmDeclarationFactory(methodSignatureMapper, state.languageVersionSettings)
override val sharedVariablesManager = JvmSharedVariablesManager(state.module, builtIns, irBuiltIns) override val sharedVariablesManager = JvmSharedVariablesManager(state.module, builtIns, irBuiltIns)
override val mapping: Mapping = DefaultMapping() override val mapping: Mapping = DefaultMapping()
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
import org.jetbrains.kotlin.backend.jvm.ir.replaceThisByStaticReference import org.jetbrains.kotlin.backend.jvm.ir.replaceThisByStaticReference
import org.jetbrains.kotlin.builtins.CompanionObjectMapping.isMappedIntrinsicCompanionObject import org.jetbrains.kotlin.builtins.CompanionObjectMapping.isMappedIntrinsicCompanionObject
import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
@@ -33,7 +35,8 @@ import org.jetbrains.kotlin.name.Name
import java.util.* import java.util.*
class JvmDeclarationFactory( class JvmDeclarationFactory(
private val methodSignatureMapper: MethodSignatureMapper private val methodSignatureMapper: MethodSignatureMapper,
private val languageVersionSettings: LanguageVersionSettings
) : DeclarationFactory { ) : DeclarationFactory {
private val singletonFieldDeclarations = HashMap<IrSymbolOwner, IrField>() private val singletonFieldDeclarations = HashMap<IrSymbolOwner, IrField>()
private val interfaceCompanionFieldDeclarations = HashMap<IrSymbolOwner, IrField>() private val interfaceCompanionFieldDeclarations = HashMap<IrSymbolOwner, IrField>()
@@ -137,12 +140,21 @@ class JvmDeclarationFactory(
override fun getFieldForObjectInstance(singleton: IrClass): IrField = override fun getFieldForObjectInstance(singleton: IrClass): IrField =
singletonFieldDeclarations.getOrPut(singleton) { singletonFieldDeclarations.getOrPut(singleton) {
val isNotMappedCompanion = singleton.isCompanion && !isMappedIntrinsicCompanionObject(singleton.descriptor) val isNotMappedCompanion = singleton.isCompanion && !isMappedIntrinsicCompanionObject(singleton.descriptor)
val useProperVisibilityForCompanion =
languageVersionSettings.supportsFeature(LanguageFeature.ProperVisibilityForCompanionObjectInstanceField)
&& singleton.isCompanion
&& !singleton.parentAsClass.isInterface
buildField { buildField {
name = if (isNotMappedCompanion) singleton.name else Name.identifier(JvmAbi.INSTANCE_FIELD) name = if (isNotMappedCompanion) singleton.name else Name.identifier(JvmAbi.INSTANCE_FIELD)
type = singleton.defaultType type = singleton.defaultType
origin = IrDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE origin = IrDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE
isFinal = true isFinal = true
isStatic = true isStatic = true
visibility = when {
!useProperVisibilityForCompanion -> Visibilities.PUBLIC
singleton.visibility == Visibilities.PROTECTED -> JavaVisibilities.PROTECTED_STATIC_VISIBILITY
else -> singleton.visibility
}
}.apply { }.apply {
parent = if (isNotMappedCompanion) singleton.parent else singleton parent = if (isNotMappedCompanion) singleton.parent else singleton
} }
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.synthetic.isVisibleOutside
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass { internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
@@ -48,7 +49,12 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
irFile.accept(object : IrInlineReferenceLocator(context) { irFile.accept(object : IrInlineReferenceLocator(context) {
override fun visitInlineLambda(argument: IrFunctionReference, callee: IrFunction, parameter: IrValueParameter, scope: IrDeclaration) { override fun visitInlineLambda(
argument: IrFunctionReference,
callee: IrFunction,
parameter: IrValueParameter,
scope: IrDeclaration
) {
inlineLambdaToCallSite[argument.symbol.owner] = LambdaCallSite(scope, parameter.isCrossinline) inlineLambdaToCallSite[argument.symbol.owner] = LambdaCallSite(scope, parameter.isCrossinline)
} }
}, null) }, null)
@@ -167,7 +173,11 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
private fun IrDeclarationWithVisibility.accessorParent(parent: IrDeclarationParent = this.parent) = private fun IrDeclarationWithVisibility.accessorParent(parent: IrDeclarationParent = this.parent) =
if (visibility == JavaVisibilities.PROTECTED_STATIC_VISIBILITY) { if (visibility == JavaVisibilities.PROTECTED_STATIC_VISIBILITY) {
val classes = allScopes.map { it.irElement }.filterIsInstance<IrClass>() val classes = allScopes.map { it.irElement }.filterIsInstance<IrClass>()
classes.lastOrNull { parent is IrClass && it.isSubclassOf(parent) } ?: classes.last() val companions = classes.mapNotNull { it.companionObject() }.filterIsInstance<IrClass>()
val objectsInScope =
classes.flatMap { it.declarations.filter(IrDeclaration::isAnonymousObject).filterIsInstance<IrClass>() }
val candidates = objectsInScope + companions + classes
candidates.lastOrNull { parent is IrClass && it.isSubclassOf(parent) } ?: classes.last()
} else parent } else parent
private fun IrConstructor.makeConstructorAccessor(): IrConstructorImpl { private fun IrConstructor.makeConstructorAccessor(): IrConstructorImpl {
@@ -185,7 +195,9 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
accessor.returnType = source.returnType.remapTypeParameters(source, accessor) accessor.returnType = source.returnType.remapTypeParameters(source, accessor)
accessor.addValueParameter( accessor.addValueParameter(
"constructor_marker".synthesizedString, context.ir.symbols.defaultConstructorMarker.defaultType, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR "constructor_marker".synthesizedString,
context.ir.symbols.defaultConstructorMarker.defaultType,
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
) )
accessor.body = IrExpressionBodyImpl( accessor.body = IrExpressionBodyImpl(
@@ -1,6 +1,4 @@
// !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField // !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField
// IGNORE_BACKEND: JVM_IR
// ^ TODO implement ProperVisibilityForCompanionObjectInstanceField feature support in JMV_IR
class Host { class Host {
private companion object { private companion object {
@@ -1,6 +1,4 @@
// !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField // !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField
// IGNORE_BACKEND: JVM_IR
// ^ TODO implement ProperVisibilityForCompanionObjectInstanceField feature support in JMV_IR
// FILE: Base.kt // FILE: Base.kt
package a package a
@@ -6670,6 +6670,7 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/inlineSuspendFinally.kt", "kotlin.coroutines"); runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/featureIntersection/inlineSuspendFinally.kt", "kotlin.coroutines");
} }
@TestMetadata("interfaceMethodWithBody.kt") @TestMetadata("interfaceMethodWithBody.kt")
public void testInterfaceMethodWithBody() throws Exception { public void testInterfaceMethodWithBody() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/interfaceMethodWithBody.kt"); runTest("compiler/testData/codegen/box/coroutines/featureIntersection/interfaceMethodWithBody.kt");