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);
|
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) {
|
public void store(InstructionAdapter v) {
|
||||||
throw new UnsupportedOperationException("cannot store to value " + this);
|
throw new UnsupportedOperationException("cannot store to value " + this);
|
||||||
}
|
}
|
||||||
@@ -341,6 +353,22 @@ public abstract class StackValue {
|
|||||||
coerce(type, v);
|
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 {
|
public static class Constant extends StackValue {
|
||||||
@@ -1132,20 +1160,21 @@ public abstract class StackValue {
|
|||||||
else {
|
else {
|
||||||
codegen.generateFromResolvedCall(thisObject, codegen.typeMapper.mapType(descriptor.getExpectedThisObject().getType(), MapTypeMode.VALUE));
|
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 {
|
else {
|
||||||
genReceiver(v, thisObject, type, null);
|
genReceiver(v, thisObject, type, null, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (receiverArgument.exists()) {
|
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(receiver == StackValue.none()) {
|
||||||
if(receiverParameter != null) {
|
if(receiverParameter != null) {
|
||||||
Type receiverType = codegen.typeMapper.mapType(receiverParameter.getType(), MapTypeMode.VALUE);
|
Type receiverType = codegen.typeMapper.mapType(receiverParameter.getType(), MapTypeMode.VALUE);
|
||||||
@@ -1157,7 +1186,7 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
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);
|
createEnvironmentWithMockJdkAndIdeaAnnotations(CompilerSpecialMode.JDK_HEADERS);
|
||||||
blackBoxFile("classes/resolveOrder.jet");
|
blackBoxFile("classes/resolveOrder.jet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testKt1918() throws Exception {
|
||||||
|
createEnvironmentWithMockJdkAndIdeaAnnotations(CompilerSpecialMode.JDK_HEADERS);
|
||||||
|
blackBoxFile("regressions/kt1918.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user