KT-30780 Fix erased inline class context in class context hierarchy
In SourceCompilerForInline we could enter ERASED_INLINE_CLASS context from containing declaration context. That broke codegen context hierarchy invariants assumed in accessor generation.
This commit is contained in:
@@ -30,6 +30,14 @@ public class ClassContext extends FieldOwnerContext<ClassDescriptor> {
|
||||
super(contextDescriptor, contextKind, parentContext, typeMapper.getBindingContext().get(CLOSURE, contextDescriptor),
|
||||
contextDescriptor, localLookup);
|
||||
|
||||
if (contextKind == OwnerKind.ERASED_INLINE_CLASS) {
|
||||
assert parentContext instanceof ClassContext &&
|
||||
parentContext.getContextKind() == OwnerKind.IMPLEMENTATION &&
|
||||
parentContext.getContextDescriptor() == contextDescriptor:
|
||||
"Erased inline class context should be created inside implementation context for the same class:" + contextDescriptor +
|
||||
"parent: " + parentContext;
|
||||
}
|
||||
|
||||
this.typeMapper = typeMapper;
|
||||
}
|
||||
|
||||
|
||||
@@ -393,13 +393,13 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
public CodegenContext findParentContextWithDescriptor(DeclarationDescriptor descriptor) {
|
||||
CodegenContext c = this;
|
||||
while (c != null) {
|
||||
if (!c.shouldSkipThisContextInHierarchy() && c.getContextDescriptor() == descriptor) break;
|
||||
if (!c.isShadowedByParentContext() && c.getContextDescriptor() == descriptor) break;
|
||||
c = c.getParentContext();
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private boolean shouldSkipThisContextInHierarchy() {
|
||||
private boolean isShadowedByParentContext() {
|
||||
return getContextKind() == OwnerKind.ERASED_INLINE_CLASS;
|
||||
}
|
||||
|
||||
|
||||
+16
-10
@@ -429,7 +429,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
}
|
||||
|
||||
val container = descriptor.containingDeclaration ?: error("No container for descriptor: $descriptor")
|
||||
val parent = getContext(
|
||||
val containerContext = getContext(
|
||||
container,
|
||||
descriptor,
|
||||
state,
|
||||
@@ -440,7 +440,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
return when (descriptor) {
|
||||
is ScriptDescriptor -> {
|
||||
val earlierScripts = state.replSpecific.earlierScriptsForReplInterpreter
|
||||
parent.intoScript(
|
||||
containerContext.intoScript(
|
||||
descriptor,
|
||||
earlierScripts ?: emptyList(),
|
||||
descriptor as ClassDescriptor, state.typeMapper
|
||||
@@ -449,21 +449,27 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
is ClassDescriptor -> {
|
||||
val kind =
|
||||
when {
|
||||
DescriptorUtils.isInterface(descriptor) && innerDescriptor !is ClassDescriptor &&
|
||||
!innerDescriptor.isCallableMemberWithJvmDefaultAnnotation() -> OwnerKind.DEFAULT_IMPLS
|
||||
|
||||
descriptor.isInlineClass() -> OwnerKind.ERASED_INLINE_CLASS
|
||||
|
||||
else -> OwnerKind.IMPLEMENTATION
|
||||
DescriptorUtils.isInterface(descriptor) &&
|
||||
innerDescriptor !is ClassDescriptor &&
|
||||
!innerDescriptor.isCallableMemberWithJvmDefaultAnnotation() ->
|
||||
OwnerKind.DEFAULT_IMPLS
|
||||
else ->
|
||||
OwnerKind.IMPLEMENTATION
|
||||
}
|
||||
|
||||
additionalInners.addIfNotNull(
|
||||
InnerClassConsumer.classForInnerClassRecord(descriptor, kind == OwnerKind.DEFAULT_IMPLS)
|
||||
)
|
||||
parent.intoClass(descriptor, kind, state)
|
||||
|
||||
if (descriptor.isInlineClass()) {
|
||||
containerContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state)
|
||||
.intoClass(descriptor, OwnerKind.ERASED_INLINE_CLASS, state)
|
||||
} else {
|
||||
containerContext.intoClass(descriptor, kind, state)
|
||||
}
|
||||
}
|
||||
is FunctionDescriptor -> {
|
||||
parent.intoFunction(descriptor)
|
||||
containerContext.intoFunction(descriptor)
|
||||
}
|
||||
else -> {
|
||||
throw IllegalStateException("Couldn't build context for $descriptor")
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
inline class Test(val x: Int) {
|
||||
private companion object {
|
||||
private const val CONSTANT = "OK"
|
||||
}
|
||||
|
||||
fun crash() = getInlineConstant()
|
||||
|
||||
private inline fun getInlineConstant(): String {
|
||||
return CONSTANT
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = Test(1).crash()
|
||||
+5
@@ -12693,6 +12693,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt27513.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt30780.kt")
|
||||
public void testKt30780() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt30780.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaInInlineClassFun.kt")
|
||||
public void testLambdaInInlineClassFun() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt");
|
||||
|
||||
+5
@@ -12693,6 +12693,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt27513.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt30780.kt")
|
||||
public void testKt30780() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt30780.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaInInlineClassFun.kt")
|
||||
public void testLambdaInInlineClassFun() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt");
|
||||
|
||||
+5
@@ -12698,6 +12698,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt27513.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt30780.kt")
|
||||
public void testKt30780() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt30780.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaInInlineClassFun.kt")
|
||||
public void testLambdaInInlineClassFun() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt");
|
||||
|
||||
Generated
+5
@@ -10128,6 +10128,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt27513.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt30780.kt")
|
||||
public void testKt30780() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt30780.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaInInlineClassFun.kt")
|
||||
public void testLambdaInInlineClassFun() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt");
|
||||
|
||||
+5
@@ -11298,6 +11298,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt27513.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt30780.kt")
|
||||
public void testKt30780() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt30780.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaInInlineClassFun.kt")
|
||||
public void testLambdaInInlineClassFun() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt");
|
||||
|
||||
Reference in New Issue
Block a user