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:
Dmitry Petrov
2019-04-04 16:56:19 +03:00
parent e1915ec99e
commit bbeb65905e
9 changed files with 67 additions and 12 deletions
@@ -30,6 +30,14 @@ public class ClassContext extends FieldOwnerContext<ClassDescriptor> {
super(contextDescriptor, contextKind, parentContext, typeMapper.getBindingContext().get(CLOSURE, contextDescriptor), super(contextDescriptor, contextKind, parentContext, typeMapper.getBindingContext().get(CLOSURE, contextDescriptor),
contextDescriptor, localLookup); 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; this.typeMapper = typeMapper;
} }
@@ -393,13 +393,13 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
public CodegenContext findParentContextWithDescriptor(DeclarationDescriptor descriptor) { public CodegenContext findParentContextWithDescriptor(DeclarationDescriptor descriptor) {
CodegenContext c = this; CodegenContext c = this;
while (c != null) { while (c != null) {
if (!c.shouldSkipThisContextInHierarchy() && c.getContextDescriptor() == descriptor) break; if (!c.isShadowedByParentContext() && c.getContextDescriptor() == descriptor) break;
c = c.getParentContext(); c = c.getParentContext();
} }
return c; return c;
} }
private boolean shouldSkipThisContextInHierarchy() { private boolean isShadowedByParentContext() {
return getContextKind() == OwnerKind.ERASED_INLINE_CLASS; return getContextKind() == OwnerKind.ERASED_INLINE_CLASS;
} }
@@ -429,7 +429,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
} }
val container = descriptor.containingDeclaration ?: error("No container for descriptor: $descriptor") val container = descriptor.containingDeclaration ?: error("No container for descriptor: $descriptor")
val parent = getContext( val containerContext = getContext(
container, container,
descriptor, descriptor,
state, state,
@@ -440,7 +440,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
return when (descriptor) { return when (descriptor) {
is ScriptDescriptor -> { is ScriptDescriptor -> {
val earlierScripts = state.replSpecific.earlierScriptsForReplInterpreter val earlierScripts = state.replSpecific.earlierScriptsForReplInterpreter
parent.intoScript( containerContext.intoScript(
descriptor, descriptor,
earlierScripts ?: emptyList(), earlierScripts ?: emptyList(),
descriptor as ClassDescriptor, state.typeMapper descriptor as ClassDescriptor, state.typeMapper
@@ -449,21 +449,27 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
is ClassDescriptor -> { is ClassDescriptor -> {
val kind = val kind =
when { when {
DescriptorUtils.isInterface(descriptor) && innerDescriptor !is ClassDescriptor && DescriptorUtils.isInterface(descriptor) &&
!innerDescriptor.isCallableMemberWithJvmDefaultAnnotation() -> OwnerKind.DEFAULT_IMPLS innerDescriptor !is ClassDescriptor &&
!innerDescriptor.isCallableMemberWithJvmDefaultAnnotation() ->
descriptor.isInlineClass() -> OwnerKind.ERASED_INLINE_CLASS OwnerKind.DEFAULT_IMPLS
else ->
else -> OwnerKind.IMPLEMENTATION OwnerKind.IMPLEMENTATION
} }
additionalInners.addIfNotNull( additionalInners.addIfNotNull(
InnerClassConsumer.classForInnerClassRecord(descriptor, kind == OwnerKind.DEFAULT_IMPLS) 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 -> { is FunctionDescriptor -> {
parent.intoFunction(descriptor) containerContext.intoFunction(descriptor)
} }
else -> { else -> {
throw IllegalStateException("Couldn't build context for $descriptor") 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()
@@ -12693,6 +12693,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt27513.kt"); 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") @TestMetadata("lambdaInInlineClassFun.kt")
public void testLambdaInInlineClassFun() throws Exception { public void testLambdaInInlineClassFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt");
@@ -12693,6 +12693,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt27513.kt"); 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") @TestMetadata("lambdaInInlineClassFun.kt")
public void testLambdaInInlineClassFun() throws Exception { public void testLambdaInInlineClassFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt");
@@ -12698,6 +12698,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt27513.kt"); 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") @TestMetadata("lambdaInInlineClassFun.kt")
public void testLambdaInInlineClassFun() throws Exception { public void testLambdaInInlineClassFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt");
@@ -10128,6 +10128,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt27513.kt"); 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") @TestMetadata("lambdaInInlineClassFun.kt")
public void testLambdaInInlineClassFun() throws Exception { public void testLambdaInInlineClassFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt");
@@ -11298,6 +11298,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/kt27513.kt"); 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") @TestMetadata("lambdaInInlineClassFun.kt")
public void testLambdaInInlineClassFun() throws Exception { public void testLambdaInInlineClassFun() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt"); runTest("compiler/testData/codegen/box/inlineClasses/contextsAndAccessors/lambdaInInlineClassFun.kt");