when calling extension function, correctly put receiver on top of stack if it was generated before the extension function object (KT-1918)
This commit is contained in:
@@ -61,6 +61,18 @@ public abstract class StackValue {
|
||||
|
||||
public abstract void put(Type type, InstructionAdapter v);
|
||||
|
||||
/**
|
||||
* This method is called to put the value on the top of the JVM stack if <code>depth</code> other values have been put on the
|
||||
* JVM stack after this value was generated.
|
||||
*
|
||||
* @param type the type as which the value should be put
|
||||
* @param v the visitor used to generate the instructions
|
||||
* @param depth the number of new values put onto the stack
|
||||
*/
|
||||
public void moveToTopOfStack(Type type, InstructionAdapter v, int depth) {
|
||||
put(type, v);
|
||||
}
|
||||
|
||||
public void store(InstructionAdapter v) {
|
||||
throw new UnsupportedOperationException("cannot store to value " + this);
|
||||
}
|
||||
@@ -341,6 +353,22 @@ public abstract class StackValue {
|
||||
coerce(type, v);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveToTopOfStack(Type type, InstructionAdapter v, int depth) {
|
||||
if (depth == 0) {
|
||||
put(type, v);
|
||||
}
|
||||
else if (depth == 1) {
|
||||
if (type.getSize() != 1) {
|
||||
throw new UnsupportedOperationException("don't know how to move type " + type + " to top of stack");
|
||||
}
|
||||
v.swap();
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("unsupported move-to-top depth " + depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Constant extends StackValue {
|
||||
@@ -1132,20 +1160,21 @@ public abstract class StackValue {
|
||||
else {
|
||||
codegen.generateFromResolvedCall(thisObject, codegen.typeMapper.mapType(descriptor.getExpectedThisObject().getType(), MapTypeMode.VALUE));
|
||||
}
|
||||
genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter());
|
||||
genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter(), 1);
|
||||
}
|
||||
else {
|
||||
genReceiver(v, thisObject, type, null);
|
||||
genReceiver(v, thisObject, type, null, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (receiverArgument.exists()) {
|
||||
genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter());
|
||||
genReceiver(v, receiverArgument, type, descriptor.getReceiverParameter(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void genReceiver(InstructionAdapter v, ReceiverDescriptor receiverArgument, Type type, ReceiverDescriptor receiverParameter) {
|
||||
private void genReceiver(InstructionAdapter v, ReceiverDescriptor receiverArgument, Type type,
|
||||
@Nullable ReceiverDescriptor receiverParameter, int depth) {
|
||||
if(receiver == StackValue.none()) {
|
||||
if(receiverParameter != null) {
|
||||
Type receiverType = codegen.typeMapper.mapType(receiverParameter.getType(), MapTypeMode.VALUE);
|
||||
@@ -1157,7 +1186,7 @@ public abstract class StackValue {
|
||||
}
|
||||
}
|
||||
else {
|
||||
receiver.put(type, v);
|
||||
receiver.moveToTopOfStack(type, v, depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
class Bar {
|
||||
}
|
||||
|
||||
trait Foo {
|
||||
fun xyzzy(x: Any?): String
|
||||
}
|
||||
|
||||
fun buildFoo(bar: Bar.() -> Unit): Foo {
|
||||
return object : Foo {
|
||||
override fun xyzzy(x: Any?): String {
|
||||
(x as? Bar)?.bar()
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val foo = buildFoo({})
|
||||
return foo.xyzzy(Bar())
|
||||
}
|
||||
@@ -386,4 +386,9 @@ public class ClassGenTest extends CodegenTestCase {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(CompilerSpecialMode.JDK_HEADERS);
|
||||
blackBoxFile("classes/resolveOrder.jet");
|
||||
}
|
||||
|
||||
public void testKt1918() throws Exception {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(CompilerSpecialMode.JDK_HEADERS);
|
||||
blackBoxFile("regressions/kt1918.kt");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user