KT-8011 Compiler crashes on attempt to create local class inside lambda
- use StackValue from upper-level context if local lookup fails #KT-8011 Fixed
This commit is contained in:
@@ -2022,6 +2022,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
return stackValueForLocal(descriptor, index);
|
return stackValueForLocal(descriptor, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return findCapturedValue(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public StackValue findCapturedValue(@NotNull DeclarationDescriptor descriptor) {
|
||||||
if (context instanceof ConstructorContext) {
|
if (context instanceof ConstructorContext) {
|
||||||
return lookupCapturedValueInConstructorParameters(descriptor);
|
return lookupCapturedValueInConstructorParameters(descriptor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,10 +159,17 @@ public interface LocalLookup {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public StackValue outerValue(@NotNull EnclosedValueDescriptor d, @NotNull ExpressionCodegen codegen) {
|
public StackValue outerValue(@NotNull EnclosedValueDescriptor d, @NotNull ExpressionCodegen codegen) {
|
||||||
int idx = codegen.lookupLocalIndex(d.getDescriptor());
|
DeclarationDescriptor declarationDescriptor = d.getDescriptor();
|
||||||
assert idx != -1;
|
int idx = codegen.lookupLocalIndex(declarationDescriptor);
|
||||||
|
if (idx >= 0) {
|
||||||
return StackValue.local(idx, d.getType());
|
return StackValue.local(idx, d.getType());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert declarationDescriptor != null : "No declaration descriptor for " + d;
|
||||||
|
StackValue capturedValue = codegen.findCapturedValue(declarationDescriptor);
|
||||||
|
assert capturedValue != null : "Unresolved captured value for " + d;
|
||||||
|
return capturedValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
fun testFun1(str: String): String {
|
||||||
|
val capture = str
|
||||||
|
|
||||||
|
class A {
|
||||||
|
val x = capture
|
||||||
|
}
|
||||||
|
|
||||||
|
return A().x
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun testFun2(str: String): String {
|
||||||
|
class A {
|
||||||
|
val x = str
|
||||||
|
}
|
||||||
|
fun bar() = A()
|
||||||
|
return bar().x
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestClass(val str: String) {
|
||||||
|
var xx: String? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
class A {
|
||||||
|
val x = str
|
||||||
|
}
|
||||||
|
|
||||||
|
xx = A().x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testFun3(str: String): String = TestClass(str).xx!!
|
||||||
|
|
||||||
|
|
||||||
|
fun String.testFun4(): String {
|
||||||
|
class A {
|
||||||
|
val x = this@testFun4
|
||||||
|
}
|
||||||
|
return A().x
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return when {
|
||||||
|
testFun1("test1") != "test1" -> "Fail #1 (local class with capture)"
|
||||||
|
testFun2("test2") != "test2" -> "Fail #2 (local class with capture ctor in another context)"
|
||||||
|
testFun3("test3") != "test3" -> "Fail #3 (local class with capture ctor in init{ ... })"
|
||||||
|
"test4".testFun4() != "test4" -> "Fail #4 (local class with extension receiver)"
|
||||||
|
else -> "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
fun testFun1(str: String): String {
|
||||||
|
val local = str
|
||||||
|
|
||||||
|
class Local {
|
||||||
|
fun foo() = str
|
||||||
|
}
|
||||||
|
|
||||||
|
val list = listOf(0).map { Local() }
|
||||||
|
return list[0].foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return when {
|
||||||
|
testFun1("test1") != "test1" -> "Fail #1"
|
||||||
|
else -> "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -1414,6 +1414,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt8011a.kt")
|
||||||
|
public void testKt8011a() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/kt8011a.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt903.kt")
|
@TestMetadata("kt903.kt")
|
||||||
public void testKt903() throws Exception {
|
public void testKt903() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/kt903.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/kt903.kt");
|
||||||
|
|||||||
+6
@@ -909,6 +909,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/classes/kt633.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/classes/kt633.kt");
|
||||||
doTestWithStdlib(fileName);
|
doTestWithStdlib(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt8011.kt")
|
||||||
|
public void testKt8011() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/classes/kt8011.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/dataClasses")
|
@TestMetadata("compiler/testData/codegen/boxWithStdlib/dataClasses")
|
||||||
|
|||||||
Reference in New Issue
Block a user