JVM_IR: fix accesses from crossinline lambdas in other packages again
This commit is contained in:
+25
-23
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.codegen.syntheticAccessorToSuperSuffix
|
|||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||||
@@ -544,20 +543,6 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
|||||||
this == JavaVisibilities.PROTECTED_AND_PACKAGE ||
|
this == JavaVisibilities.PROTECTED_AND_PACKAGE ||
|
||||||
this == JavaVisibilities.PROTECTED_STATIC_VISIBILITY
|
this == JavaVisibilities.PROTECTED_STATIC_VISIBILITY
|
||||||
|
|
||||||
private fun IrDeclaration.getAccessContext(allowSamePackage: Boolean): IrDeclarationContainer? = when {
|
|
||||||
this is IrDeclarationContainer -> this
|
|
||||||
// For inline lambdas, we can navigate to the only call site directly. Crossinline lambdas might be inlined
|
|
||||||
// into other classes in the same package, so private/super require accessors anyway.
|
|
||||||
this in inlineLambdaToCallSite ->
|
|
||||||
inlineLambdaToCallSite[this]!!.takeIf { allowSamePackage || !it.crossinline }?.scope?.getAccessContext(allowSamePackage)
|
|
||||||
// Accesses from inline functions can actually be anywhere; even private inline functions can be
|
|
||||||
// inlined into a different class, e.g. a callable reference. For protected inline functions
|
|
||||||
// calling methods on `super` we also need an accessor to satisfy INVOKESPECIAL constraints.
|
|
||||||
// TODO scan nested classes for calls to private inline functions?
|
|
||||||
this is IrFunction && isInline -> null
|
|
||||||
else -> (parent as? IrDeclaration)?.getAccessContext(allowSamePackage)
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
||||||
@@ -582,18 +567,35 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If local variables are accessible by Kotlin rules, they also are by Java rules.
|
// If local variables are accessible by Kotlin rules, they also are by Java rules.
|
||||||
val symbolDeclarationContainer = (declaration.parent as? IrDeclarationContainer) as? IrElement ?: return true
|
val ownerClass = declaration.parent as? IrClass ?: return true
|
||||||
val contextDeclarationContainer =
|
|
||||||
(currentScope!!.irElement as IrDeclaration).getAccessContext(declaration.visibility.isProtected && !withSuper) ?: return false
|
|
||||||
|
|
||||||
val samePackage = declaration.getPackageFragment()?.fqName == contextDeclarationContainer.getPackageFragment()?.fqName
|
var context = currentScope!!.irElement as IrDeclaration
|
||||||
val fromSubclassOfReceiversClass = contextDeclarationContainer is IrClass && symbolDeclarationContainer is IrClass &&
|
var throughCrossinlineLambda = false
|
||||||
((thisObjReference == null || contextDeclarationContainer.symbol.isSubtypeOfClass(thisObjReference)) &&
|
while (context !is IrClass) {
|
||||||
(contextDeclarationContainer.isSubclassOf(symbolDeclarationContainer)))
|
val callSite = inlineLambdaToCallSite[context]
|
||||||
|
if (callSite != null) {
|
||||||
|
// For inline lambdas, we can navigate to the only call site directly. Crossinline lambdas might be inlined
|
||||||
|
// into other classes in the same package, so private/super require accessors anyway.
|
||||||
|
throughCrossinlineLambda = throughCrossinlineLambda || callSite.crossinline
|
||||||
|
context = callSite.scope
|
||||||
|
} else if (context is IrFunction && context.isInline) {
|
||||||
|
// Accesses from inline functions can actually be anywhere; even private inline functions can be
|
||||||
|
// inlined into a different class, e.g. a callable reference. For protected inline functions
|
||||||
|
// calling methods on `super` we also need an accessor to satisfy INVOKESPECIAL constraints.
|
||||||
|
// TODO scan nested classes for calls to private inline functions?
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
context = context.parent as? IrDeclaration ?: return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val samePackage = ownerClass.getPackageFragment()?.fqName == context.getPackageFragment()?.fqName
|
||||||
|
val fromSubclassOfReceiversClass = !throughCrossinlineLambda &&
|
||||||
|
context.isSubclassOf(ownerClass) && (thisObjReference == null || context.symbol.isSubtypeOfClass(thisObjReference))
|
||||||
return when {
|
return when {
|
||||||
// private suspend functions are generated as synthetic package private
|
// private suspend functions are generated as synthetic package private
|
||||||
declaration is IrFunction && declaration.isSuspend && declaration.visibility.isPrivate && samePackage -> true
|
declaration is IrFunction && declaration.isSuspend && declaration.visibility.isPrivate && samePackage -> true
|
||||||
declaration.visibility.isPrivate && symbolDeclarationContainer != contextDeclarationContainer -> false
|
declaration.visibility.isPrivate && (throughCrossinlineLambda || ownerClass != context) -> false
|
||||||
declaration.visibility.isProtected && !samePackage && !fromSubclassOfReceiversClass -> false
|
declaration.visibility.isProtected && !samePackage && !fromSubclassOfReceiversClass -> false
|
||||||
withSuper && !fromSubclassOfReceiversClass -> false
|
withSuper && !fromSubclassOfReceiversClass -> false
|
||||||
else -> true
|
else -> true
|
||||||
|
|||||||
Vendored
+19
@@ -0,0 +1,19 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
package test
|
||||||
|
|
||||||
|
open class A {
|
||||||
|
protected fun f() = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <R> runInObject(crossinline block: () -> R): R = object {
|
||||||
|
fun run() = block()
|
||||||
|
}.run()
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
fun g() = runInObject { f() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String = B().g()
|
||||||
+5
@@ -4390,6 +4390,11 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/privateInCrossInline.kt");
|
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/privateInCrossInline.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("protectedInCrossinline.kt")
|
||||||
|
public void testProtectedInCrossinline() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/protectedInCrossinline.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("protectedMembersFromSuper.kt")
|
@TestMetadata("protectedMembersFromSuper.kt")
|
||||||
public void testProtectedMembersFromSuper() throws Exception {
|
public void testProtectedMembersFromSuper() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/protectedMembersFromSuper.kt");
|
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/protectedMembersFromSuper.kt");
|
||||||
|
|||||||
Generated
+5
@@ -4390,6 +4390,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/privateInCrossInline.kt");
|
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/privateInCrossInline.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("protectedInCrossinline.kt")
|
||||||
|
public void testProtectedInCrossinline() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/protectedInCrossinline.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("protectedMembersFromSuper.kt")
|
@TestMetadata("protectedMembersFromSuper.kt")
|
||||||
public void testProtectedMembersFromSuper() throws Exception {
|
public void testProtectedMembersFromSuper() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/protectedMembersFromSuper.kt");
|
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/protectedMembersFromSuper.kt");
|
||||||
|
|||||||
+5
@@ -4125,6 +4125,11 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
|
|||||||
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/privateInCrossInline.kt");
|
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/privateInCrossInline.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("protectedInCrossinline.kt")
|
||||||
|
public void testProtectedInCrossinline() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/protectedInCrossinline.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("protectedMembersFromSuper.kt")
|
@TestMetadata("protectedMembersFromSuper.kt")
|
||||||
public void testProtectedMembersFromSuper() throws Exception {
|
public void testProtectedMembersFromSuper() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/protectedMembersFromSuper.kt");
|
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/protectedMembersFromSuper.kt");
|
||||||
|
|||||||
Generated
+5
@@ -4125,6 +4125,11 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
|
|||||||
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/privateInCrossInline.kt");
|
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/privateInCrossInline.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("protectedInCrossinline.kt")
|
||||||
|
public void testProtectedInCrossinline() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/protectedInCrossinline.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("protectedMembersFromSuper.kt")
|
@TestMetadata("protectedMembersFromSuper.kt")
|
||||||
public void testProtectedMembersFromSuper() throws Exception {
|
public void testProtectedMembersFromSuper() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/protectedMembersFromSuper.kt");
|
runTest("compiler/testData/codegen/boxInline/syntheticAccessors/withinInlineLambda/protectedMembersFromSuper.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user