JVM_IR: try to fix SyntheticAccessorLowering.isAccessible again

The condition on the relationship between the current class and the type
of the receiver for protected members was the opposite of what the JVMS
says, and yet somehow mostly worked?

 #KT-48331 Fixed
 #KT-20542 Fixed
This commit is contained in:
pyos
2021-08-23 13:48:23 +02:00
committed by TeamCityServer
parent 9a472c418f
commit 7ce5556de3
15 changed files with 231 additions and 102 deletions
@@ -41764,6 +41764,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/syntheticAccessors/kt21258_simple.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/kt21258_simple.kt");
} }
@Test
@TestMetadata("kt48331.kt")
public void testKt48331() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/kt48331.kt");
}
@Test @Test
@TestMetadata("kt9717.kt") @TestMetadata("kt9717.kt")
public void testKt9717() throws Exception { public void testKt9717() throws Exception {
@@ -41788,12 +41794,24 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/syntheticAccessors/kt9958Interface.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/kt9958Interface.kt");
} }
@Test
@TestMetadata("packagePrivate.kt")
public void testPackagePrivate() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/packagePrivate.kt");
}
@Test @Test
@TestMetadata("protectedFromLambda.kt") @TestMetadata("protectedFromLambda.kt")
public void testProtectedFromLambda() throws Exception { public void testProtectedFromLambda() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/protectedFromLambda.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/protectedFromLambda.kt");
} }
@Test
@TestMetadata("protectedSuper.kt")
public void testProtectedSuper() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/protectedSuper.kt");
}
@Test @Test
@TestMetadata("protectedSuperclassCompanionObjectMember.kt") @TestMetadata("protectedSuperclassCompanionObjectMember.kt")
public void testProtectedSuperclassCompanionObjectMember() throws Exception { public void testProtectedSuperclassCompanionObjectMember() throws Exception {
@@ -271,6 +271,9 @@ class JvmCachedDeclarations(
parent = irClass parent = irClass
overriddenSymbols = fakeOverride.overriddenSymbols overriddenSymbols = fakeOverride.overriddenSymbols
copyParameterDeclarationsFrom(fakeOverride) copyParameterDeclarationsFrom(fakeOverride)
// The fake override's dispatch receiver has the same type as the real declaration's,
// i.e. some superclass of the current class. This is not good for accessibility checks.
dispatchReceiverParameter?.type = irClass.defaultType
annotations = fakeOverride.annotations annotations = fakeOverride.annotations
copyCorrespondingPropertyFrom(fakeOverride) copyCorrespondingPropertyFrom(fakeOverride)
} }
@@ -381,7 +381,10 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
internal fun mapToCallableMethod(expression: IrCall, caller: IrFunction?): IrCallableMethod { internal fun mapToCallableMethod(expression: IrCall, caller: IrFunction?): IrCallableMethod {
val callee = expression.symbol.owner val callee = expression.symbol.owner
val calleeParent = expression.superQualifierSymbol?.owner val calleeParent = expression.superQualifierSymbol?.owner
?: expression.dispatchReceiver?.type?.classOrNull?.owner ?: expression.dispatchReceiver?.type?.classOrNull?.owner?.let {
// Calling Object class methods on interfaces is permitted, but they're not interface methods.
if (it.isJvmInterface && callee.isMethodOfAny()) context.irBuiltIns.anyClass.owner else it
}
?: callee.parentAsClass // Static call or type parameter ?: callee.parentAsClass // Static call or type parameter
val owner = typeMapper.mapOwner(calleeParent) val owner = typeMapper.mapOwner(calleeParent)
@@ -140,5 +140,8 @@ fun IrClass.buildAssertionsDisabledField(backendContext: JvmBackendContext, topL
} }
} }
fun IrField.isAssertionsDisabledField(context: JvmBackendContext) =
name.asString() == ASSERTIONS_DISABLED_FIELD_NAME && type == context.irBuiltIns.booleanType && isStatic
fun IrClass.hasAssertionsDisabledField(context: JvmBackendContext) = fun IrClass.hasAssertionsDisabledField(context: JvmBackendContext) =
fields.any { it.name.asString() == ASSERTIONS_DISABLED_FIELD_NAME && it.type == context.irBuiltIns.booleanType && it.isStatic } fields.any { it.isAssertionsDisabledField(context) }
@@ -30,8 +30,6 @@ import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -239,19 +237,7 @@ private class InterfaceObjectCallsLowering(val context: JvmBackendContext) : IrE
if (resolved?.isMethodOfAny() != true) if (resolved?.isMethodOfAny() != true)
return super.visitCall(expression) return super.visitCall(expression)
val newSuperQualifierSymbol = context.irBuiltIns.anyClass.takeIf { expression.superQualifierSymbol != null } val newSuperQualifierSymbol = context.irBuiltIns.anyClass.takeIf { expression.superQualifierSymbol != null }
return super.visitCall(irCall(expression, resolved, newSuperQualifierSymbol = newSuperQualifierSymbol).apply { return super.visitCall(irCall(expression, resolved, newSuperQualifierSymbol = newSuperQualifierSymbol))
dispatchReceiver?.let { receiver ->
val receiverType = resolved.parentAsClass.defaultType
dispatchReceiver = IrTypeOperatorCallImpl(
receiver.startOffset,
receiver.endOffset,
receiverType,
IrTypeOperator.IMPLICIT_CAST,
receiverType,
receiver
)
}
})
} }
} }
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
import org.jetbrains.kotlin.backend.jvm.intrinsics.receiverAndArgs import org.jetbrains.kotlin.backend.jvm.intrinsics.receiverAndArgs
import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.hasMangledParameters import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.hasMangledParameters
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
@@ -34,6 +35,7 @@ import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.org.objectweb.asm.Opcodes
internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass { internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
data class LambdaCallSite(val scope: IrDeclaration, val crossinline: Boolean) data class LambdaCallSite(val scope: IrDeclaration, val crossinline: Boolean)
@@ -232,8 +234,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
// We have a protected member. // We have a protected member.
// It is accessible from a synthetic proxy class (created by LambdaMetafactory) // It is accessible from a synthetic proxy class (created by LambdaMetafactory)
// if it belongs to the current class. // if it belongs to the current class.
val outerClassInfo = getOuterClassInfo() ?: return false return getScopeClassOrPackage() == owner.parentAsClass
return outerClassInfo.outerClass == owner.parentAsClass
} }
override fun visitGetField(expression: IrGetField): IrExpression { override fun visitGetField(expression: IrGetField): IrExpression {
@@ -707,9 +708,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
private fun IrSymbol.isAccessible(withSuper: Boolean, thisObjReference: IrClassSymbol?): Boolean { private fun IrSymbol.isAccessible(withSuper: Boolean, thisObjReference: IrClassSymbol?): Boolean {
/// We assume that IR code that reaches us has been checked for correctness at the frontend. /// We assume that IR code that reaches us has been checked for correctness at the frontend.
/// This function needs to single out those cases where Java accessibility rules differ from Kotlin's. /// This function needs to single out those cases where Java accessibility rules differ from Kotlin's.
val declarationRaw = owner as IrDeclarationWithVisibility
val symbolOwner = owner
val declarationRaw = symbolOwner as IrDeclarationWithVisibility
// There is never a problem with visibility of inline functions, as those don't end up as Java entities // There is never a problem with visibility of inline functions, as those don't end up as Java entities
if (declarationRaw is IrFunction && declarationRaw.isInline) return true if (declarationRaw is IrFunction && declarationRaw.isInline) return true
@@ -717,85 +716,93 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
// Enum entry constructors are generated as package-private and are accessed only from corresponding enum class // Enum entry constructors are generated as package-private and are accessed only from corresponding enum class
if (declarationRaw is IrConstructor && declarationRaw.constructedClass.isEnumEntry) return true if (declarationRaw is IrConstructor && declarationRaw.constructedClass.isEnumEntry) return true
// `internal` maps to public and requires no accessor. // Public declarations are already accessible. However, `super` calls are subclass-only.
if (!withSuper && !declarationRaw.visibility.isPrivate && !declarationRaw.visibility.isProtected) return true val jvmVisibility = AsmUtil.getVisibilityAccessFlag(declarationRaw.visibility.delegate)
if (jvmVisibility == Opcodes.ACC_PUBLIC && !withSuper) return true
// `toArray` is always accessible cause mapped to public functions // `toArray` is always accessible cause mapped to public functions
if (symbolOwner is IrSimpleFunction && (symbolOwner.isNonGenericToArray() || symbolOwner.isGenericToArray(context))) { if (declarationRaw is IrSimpleFunction && (declarationRaw.isNonGenericToArray() || declarationRaw.isGenericToArray(context)) &&
if (symbolOwner.parentAsClass.isCollectionSubClass) { declarationRaw.parentAsClass.isCollectionSubClass
return true ) return true
}
}
// EnumEntry constructors are always accessible (they are only called from the enclosing Enum class) // `$assertionsDisabled` is accessed only from the same class, even in an inline function
if (symbolOwner is IrConstructor && symbolOwner.parentClassOrNull?.isEnumEntry == true) // (the inliner will generate it at the call site if necessary).
return true if (declarationRaw is IrField && declarationRaw.isAssertionsDisabledField(context)) return true
val declaration = when (declarationRaw) { val declaration = when (declarationRaw) {
is IrSimpleFunction -> is IrSimpleFunction -> declarationRaw.resolveFakeOverride(allowAbstract = true)!!
declarationRaw.resolveFakeOverride(allowAbstract = true) is IrField -> declarationRaw.resolveFakeOverride()
?: declarationRaw else -> declarationRaw
is IrField -> {
val correspondingProperty = declarationRaw.correspondingPropertySymbol?.owner
if (correspondingProperty != null && correspondingProperty.isFakeOverride) {
val realProperty = correspondingProperty.resolveFakeOverride()
?: throw AssertionError("No real override for ${correspondingProperty.render()}")
realProperty.backingField
?: throw AssertionError(
"Fake override property ${correspondingProperty.render()} with backing field " +
"overrides a real property with no backing field: ${realProperty.render()}"
)
} else {
declarationRaw
}
}
else ->
declarationRaw
} }
// If local variables are accessible by Kotlin rules, they also are by Java rules. val ownerClass = declaration.parent as? IrClass ?: return true // locals are always accessible
val ownerClass = declaration.parent as? IrClass ?: return true val scopeClassOrPackage = getScopeClassOrPackage() ?: return false
val samePackage = ownerClass.getPackageFragment()?.fqName == scopeClassOrPackage.getPackageFragment()?.fqName
val outerClassInfo = getOuterClassInfo() ?: return false
val outerClass = outerClassInfo.outerClass
val throughCrossinlineLambda = outerClassInfo.throughCrossinlineLambda
val samePackage = ownerClass.getPackageFragment()?.fqName == outerClass.getPackageFragment()?.fqName
val fromSubclassOfReceiversClass = !throughCrossinlineLambda &&
outerClass.isSubclassOf(ownerClass) &&
(thisObjReference == null || outerClass.symbol.isSubtypeOfClass(thisObjReference))
return when { return when {
declaration.visibility.isPrivate && (throughCrossinlineLambda || ownerClass != outerClass) -> false jvmVisibility == 0 /* package only */ -> samePackage
declaration.visibility.isProtected && !samePackage && !fromSubclassOfReceiversClass -> false jvmVisibility == Opcodes.ACC_PRIVATE -> ownerClass == scopeClassOrPackage
withSuper && !fromSubclassOfReceiversClass -> false // JVM `protected`, unlike Kotlin `protected`, permits accesses from the same package.
else -> true !withSuper && samePackage -> true
// Super calls and cross-package protected accesses are both only possible from a subclass of the declaration
// owner. Also, the target of a non-static call must be assignable to the current class. This is a verification
// constraint: https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.10.1.8
else -> (scopeClassOrPackage is IrClass && scopeClassOrPackage.isSubclassOf(ownerClass)) &&
(thisObjReference == null || thisObjReference.owner.isSubclassOf(scopeClassOrPackage))
} }
} }
private class OuterClassInfo(val outerClass: IrClass, val throughCrossinlineLambda: Boolean) // Get the class from which all accesses in the current scope will be done after bytecode generation.
// If the current scope is a crossinline lambda, this is not possible, as the lambda maybe inlined
private fun getOuterClassInfo(): OuterClassInfo? { // into some other class; in that case, get at least the package.
var context = currentScope!!.irElement as IrDeclaration private fun getScopeClassOrPackage(): IrDeclarationContainer? {
var context = currentScope?.irElement
var throughCrossinlineLambda = false var throughCrossinlineLambda = false
while (context !is IrClass) { while (context is IrDeclaration) {
val callSite = inlineLambdaToCallSite[context] val callSite = inlineLambdaToCallSite[context]
if (callSite != null) { when {
// For inline lambdas, we can navigate to the only call site directly. Crossinline lambdas might be inlined // Crossinline lambdas can be inlined into some other class in the same package. However,
// into other classes in the same package, so private/super require accessors anyway. // classes within crossinline lambdas should not be regenerated, so if we've already found
throughCrossinlineLambda = throughCrossinlineLambda || callSite.crossinline // a class *before* reaching this lambda, it's valid:
context = callSite.scope // class C {
} else if (context is IrFunction && context.isInline) { // fun f() {}
// Accesses from inline functions can actually be anywhere; even private inline functions can be // fun g() = inlineFunctionWithCrossinlineArgument {
// inlined into a different class, e.g. a callable reference. For protected inline functions // f() // this call is done in some unknown class within C's package
// calling methods on `super` we also need an accessor to satisfy INVOKESPECIAL constraints. // object { val x = f() } // this call is done in C$g$1$1
// TODO scan nested classes for calls to private inline functions? // }
return null // }
} else { callSite != null -> throughCrossinlineLambda = throughCrossinlineLambda || callSite.crossinline
context = context.parent as? IrDeclaration // Inline functions can be inlined into anywhere. Not even private inline functions are safe:
?: return null // class C {
// fun f() {}
// private inline fun g1() = f() // `f` is called from C?
// fun g2() = { g1() } // ...or from C$g2$1 in the same package?
// inline fun g3() = g1() // ...or from some other package that calls g3?
// }
// TODO: this has some weird effects for inline functions in local classes, e.g. they
// access the capture fields (package-private) through accessors; this may or may not
// be necessary - local types should in theory not be usable outside the current file.
context is IrFunction && context.isInline -> return null
// TODO: if this class is an object local to an inline function, it could be regenerated,
// so the scope depends on the declaration accessed (see KT-48508):
// class C {
// fun f1()
// inline fun inlineFun() = object {
// fun f2() {}
// fun g1() {
// f1() // this access can be anywhere
// f2() // can pretend this access is from C$foo$1
// }
// }
// }
// Further complicating things, the accessor for `f1` cannot be in `C$foo$1`, as otherwise
// the accessor itself will be regenerated (and thus not work) at `inlineFun` call sites.
context is IrClass && !throughCrossinlineLambda -> return context
} }
// Inline lambdas have already been moved out to the containing class, but we still need to check
// the containing function (again, see above), so navigate there instead.
context = callSite?.scope ?: context.parent
} }
return OuterClassInfo(context, throughCrossinlineLambda) return context as? IrPackageFragment
} }
// monitorEnter/monitorExit are the only functions which are accessed "illegally" (see kotlin/util/Synchronized.kt). // monitorEnter/monitorExit are the only functions which are accessed "illegally" (see kotlin/util/Synchronized.kt).
@@ -813,10 +820,18 @@ private fun IrClass.syntheticAccessorToSuperSuffix(): String =
// TODO: change this to `fqNameUnsafe.asString().replace(".", "_")` as soon as we're ready to break compatibility with pre-KT-21178 code // TODO: change this to `fqNameUnsafe.asString().replace(".", "_")` as soon as we're ready to break compatibility with pre-KT-21178 code
name.asString().hashCode().toString() name.asString().hashCode().toString()
val DescriptorVisibility.isPrivate private fun IrField.resolveFakeOverride(): IrField {
get() = DescriptorVisibilities.isPrivate(this) val correspondingProperty = correspondingPropertySymbol?.owner
if (correspondingProperty == null || !correspondingProperty.isFakeOverride)
return this
val realProperty = correspondingProperty.resolveFakeOverride()
?: throw AssertionError("No real override for ${correspondingProperty.render()}")
return realProperty.backingField
?: throw AssertionError(
"Fake override property ${correspondingProperty.render()} with backing field " +
"overrides a real property with no backing field: ${realProperty.render()}"
)
}
val DescriptorVisibility.isProtected private val DescriptorVisibility.isProtected
get() = this == DescriptorVisibilities.PROTECTED || get() = AsmUtil.getVisibilityAccessFlag(delegate) == Opcodes.ACC_PROTECTED
this == JavaDescriptorVisibilities.PROTECTED_AND_PACKAGE ||
this == JavaDescriptorVisibilities.PROTECTED_STATIC_VISIBILITY
@@ -13,8 +13,8 @@ import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
import org.jetbrains.kotlin.backend.jvm.ir.getSingleAbstractMethod import org.jetbrains.kotlin.backend.jvm.ir.getSingleAbstractMethod
import org.jetbrains.kotlin.backend.jvm.ir.isCompiledToJvmDefault import org.jetbrains.kotlin.backend.jvm.ir.isCompiledToJvmDefault
import org.jetbrains.kotlin.backend.jvm.lower.findInterfaceImplementation import org.jetbrains.kotlin.backend.jvm.lower.findInterfaceImplementation
import org.jetbrains.kotlin.backend.jvm.lower.isPrivate
import org.jetbrains.kotlin.builtins.functions.BuiltInFunctionArity import org.jetbrains.kotlin.builtins.functions.BuiltInFunctionArity
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.builders.declarations.buildClass import org.jetbrains.kotlin.ir.builders.declarations.buildClass
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
@@ -91,7 +91,7 @@ internal class LambdaMetafactoryArgumentsBuilder(
if (implFun.isInline) if (implFun.isInline)
return null return null
if (implFun is IrConstructor && implFun.visibility.isPrivate) { if (implFun is IrConstructor && DescriptorVisibilities.isPrivate(implFun.visibility)) {
// Kotlin generates constructor accessors differently from Java. // Kotlin generates constructor accessors differently from Java.
// TODO more precise accessibility check (see SyntheticAccessorLowering::isAccessible) // TODO more precise accessibility check (see SyntheticAccessorLowering::isAccessible)
return null return null
@@ -30,10 +30,6 @@ inline fun inlineMe(crossinline c: suspend () -> Unit) = object : SuspendRunnabl
StateMachineChecker.suspendHere() StateMachineChecker.suspendHere()
StateMachineChecker.suspendHere() StateMachineChecker.suspendHere()
} }
// TODO: call it from run1
inline suspend fun inlineMeCapturing() {
c(); c()
}
} }
inline fun inlineMe2(crossinline c: suspend () -> Unit) = inlineMe { c(); c() } inline fun inlineMe2(crossinline c: suspend () -> Unit) = inlineMe { c(); c() }
@@ -0,0 +1,25 @@
// TARGET_BACKEND: JVM
// FILE: foo.kt
package foo
abstract class Base {
protected abstract fun foo(): String
}
// FILE: bar.kt
import foo.*
abstract class C : Base() {
class A : C() {
override fun foo() = "OK"
}
class B(val x: C) : C() {
// Needs an accessor (`foo` is in another package and `x` is not assignable to `B`)
override fun foo() = x.foo()
fun bar() = foo()
}
}
fun box() = C.B(C.A()).bar()
@@ -0,0 +1,16 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// FILE: x.kt
package x
internal class C {
// `foo$default` generated as package-private (not protected):
private fun foo(result: String = "OK") = result
// this needs an accessor:
internal inline fun bar() = foo()
}
// FILE: y.kt
import x.*
fun box() = C().bar()
@@ -0,0 +1,11 @@
// TARGET_BACKEND: JVM
open class C {
protected open fun foo() = "OK"
}
class D : C() {
// same package, but `super` needs to be related by class hierarchy:
fun bar() = { super.foo() }
}
fun box() = D().bar()()
@@ -1,3 +1,6 @@
// IGNORE_BACKEND: JVM, JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_IR, JVM_MULTI_MODULE_OLD_AGAINST_IR, JVM_MULTI_MODULE_IR_AGAINST_OLD
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -6,10 +9,9 @@ interface I {
} }
inline fun test(crossinline h: () -> String) = object : I { inline fun test(crossinline h: () -> String) = object : I {
// TODO: actually call g() in f() -- currently, the inliner fails to detect // TODO: this does not work because the inliner is not correctly remapping the capture.
// an inlined read of h's field because it uses a copy of `this` override fun f(): String = g()
// as a receiver // TODO: and this does not work in JVM_IR because there is a redundant accessor.
override fun f(): String = h()
inline fun g(): String = h() inline fun g(): String = h()
} }
@@ -41614,6 +41614,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/syntheticAccessors/kt21258_simple.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/kt21258_simple.kt");
} }
@Test
@TestMetadata("kt48331.kt")
public void testKt48331() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/kt48331.kt");
}
@Test @Test
@TestMetadata("kt9717.kt") @TestMetadata("kt9717.kt")
public void testKt9717() throws Exception { public void testKt9717() throws Exception {
@@ -41638,12 +41644,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/syntheticAccessors/kt9958Interface.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/kt9958Interface.kt");
} }
@Test
@TestMetadata("packagePrivate.kt")
public void testPackagePrivate() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/packagePrivate.kt");
}
@Test @Test
@TestMetadata("protectedFromLambda.kt") @TestMetadata("protectedFromLambda.kt")
public void testProtectedFromLambda() throws Exception { public void testProtectedFromLambda() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/protectedFromLambda.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/protectedFromLambda.kt");
} }
@Test
@TestMetadata("protectedSuper.kt")
public void testProtectedSuper() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/protectedSuper.kt");
}
@Test @Test
@TestMetadata("protectedSuperclassCompanionObjectMember.kt") @TestMetadata("protectedSuperclassCompanionObjectMember.kt")
public void testProtectedSuperclassCompanionObjectMember() throws Exception { public void testProtectedSuperclassCompanionObjectMember() throws Exception {
@@ -41764,6 +41764,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/syntheticAccessors/kt21258_simple.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/kt21258_simple.kt");
} }
@Test
@TestMetadata("kt48331.kt")
public void testKt48331() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/kt48331.kt");
}
@Test @Test
@TestMetadata("kt9717.kt") @TestMetadata("kt9717.kt")
public void testKt9717() throws Exception { public void testKt9717() throws Exception {
@@ -41788,12 +41794,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/syntheticAccessors/kt9958Interface.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/kt9958Interface.kt");
} }
@Test
@TestMetadata("packagePrivate.kt")
public void testPackagePrivate() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/packagePrivate.kt");
}
@Test @Test
@TestMetadata("protectedFromLambda.kt") @TestMetadata("protectedFromLambda.kt")
public void testProtectedFromLambda() throws Exception { public void testProtectedFromLambda() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/protectedFromLambda.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/protectedFromLambda.kt");
} }
@Test
@TestMetadata("protectedSuper.kt")
public void testProtectedSuper() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/protectedSuper.kt");
}
@Test @Test
@TestMetadata("protectedSuperclassCompanionObjectMember.kt") @TestMetadata("protectedSuperclassCompanionObjectMember.kt")
public void testProtectedSuperclassCompanionObjectMember() throws Exception { public void testProtectedSuperclassCompanionObjectMember() throws Exception {
@@ -33390,6 +33390,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
public static class SyntheticAccessors extends AbstractLightAnalysisModeTest { public static class SyntheticAccessors extends AbstractLightAnalysisModeTest {
@TestMetadata("packagePrivate.kt")
public void ignorePackagePrivate() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/packagePrivate.kt");
}
@TestMetadata("protectedSuperclassCompanionObjectMember.kt") @TestMetadata("protectedSuperclassCompanionObjectMember.kt")
public void ignoreProtectedSuperclassCompanionObjectMember() throws Exception { public void ignoreProtectedSuperclassCompanionObjectMember() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/protectedSuperclassCompanionObjectMember.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/protectedSuperclassCompanionObjectMember.kt");
@@ -33473,6 +33478,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/syntheticAccessors/kt21258_simple.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/kt21258_simple.kt");
} }
@TestMetadata("kt48331.kt")
public void testKt48331() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/kt48331.kt");
}
@TestMetadata("kt9717.kt") @TestMetadata("kt9717.kt")
public void testKt9717() throws Exception { public void testKt9717() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/kt9717.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/kt9717.kt");
@@ -33498,6 +33508,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/syntheticAccessors/protectedFromLambda.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/protectedFromLambda.kt");
} }
@TestMetadata("protectedSuper.kt")
public void testProtectedSuper() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/protectedSuper.kt");
}
@TestMetadata("superCallFromMultipleSubclasses.kt") @TestMetadata("superCallFromMultipleSubclasses.kt")
public void testSuperCallFromMultipleSubclasses() throws Exception { public void testSuperCallFromMultipleSubclasses() throws Exception {
runTest("compiler/testData/codegen/box/syntheticAccessors/superCallFromMultipleSubclasses.kt"); runTest("compiler/testData/codegen/box/syntheticAccessors/superCallFromMultipleSubclasses.kt");