Fixes for KT-4991: Prefix/postfix expressions resolved to local extensions are not supported in codegen;
KT-4989: Verify error on local functions and extensions; KT-4987: NegativeArraySizeException on local extension convention function on nullable Int #KT-4991 Fixed #KT-4989 Fixed #KT-4987 Fixed
This commit is contained in:
@@ -3069,24 +3069,25 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue visitPrefixExpression(@NotNull JetPrefixExpression expression, StackValue receiver) {
|
public StackValue visitPrefixExpression(@NotNull JetPrefixExpression expression, StackValue receiver) {
|
||||||
DeclarationDescriptor op = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference());
|
DeclarationDescriptor originalOperation = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference());
|
||||||
assert op instanceof FunctionDescriptor : String.valueOf(op);
|
ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression, bindingContext);
|
||||||
|
CallableDescriptor op = resolvedCall.getResultingDescriptor();
|
||||||
|
|
||||||
|
assert op instanceof FunctionDescriptor || originalOperation == null : String.valueOf(op);
|
||||||
Callable callable = resolveToCallable((FunctionDescriptor) op, false);
|
Callable callable = resolveToCallable((FunctionDescriptor) op, false);
|
||||||
if (callable instanceof IntrinsicMethod) {
|
if (callable instanceof IntrinsicMethod) {
|
||||||
Type returnType = typeMapper.mapType((FunctionDescriptor) op);
|
Type returnType = typeMapper.mapType(op);
|
||||||
((IntrinsicMethod) callable).generate(this, v, returnType, expression,
|
((IntrinsicMethod) callable).generate(this, v, returnType, expression,
|
||||||
Collections.singletonList(expression.getBaseExpression()), receiver);
|
Collections.singletonList(expression.getBaseExpression()), receiver);
|
||||||
return StackValue.onStack(returnType);
|
return StackValue.onStack(returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclarationDescriptor cls = op.getContainingDeclaration();
|
DeclarationDescriptor cls = op.getContainingDeclaration();
|
||||||
ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression, bindingContext);
|
|
||||||
|
|
||||||
if (isPrimitiveNumberClassDescriptor(cls) || !(op.getName().asString().equals("inc") || op.getName().asString().equals("dec"))) {
|
if (isPrimitiveNumberClassDescriptor(cls) || !(originalOperation.getName().asString().equals("inc") || originalOperation.getName().asString().equals("dec"))) {
|
||||||
return invokeFunction(resolvedCall, receiver);
|
return invokeFunction(resolvedCall, receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
CallableMethod callableMethod = (CallableMethod) callable;
|
|
||||||
|
|
||||||
StackValue value = gen(expression.getBaseExpression());
|
StackValue value = gen(expression.getBaseExpression());
|
||||||
value.dupReceiver(v);
|
value.dupReceiver(v);
|
||||||
@@ -3096,6 +3097,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
value.put(type, v);
|
value.put(type, v);
|
||||||
invokeFunction(resolvedCall, StackValue.onStack(type));
|
invokeFunction(resolvedCall, StackValue.onStack(type));
|
||||||
|
|
||||||
|
CallableMethod callableMethod = (CallableMethod) callable;
|
||||||
value.store(callableMethod.getReturnType(), v);
|
value.store(callableMethod.getReturnType(), v);
|
||||||
value.put(type, v);
|
value.put(type, v);
|
||||||
return StackValue.onStack(type);
|
return StackValue.onStack(type);
|
||||||
@@ -3117,23 +3119,26 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
return StackValue.onStack(base.type);
|
return StackValue.onStack(base.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclarationDescriptor op = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference());
|
DeclarationDescriptor originalOperation = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference());
|
||||||
if (!(op instanceof FunctionDescriptor)) {
|
String originalOperationName = originalOperation != null ? originalOperation.getName().asString() : null;
|
||||||
throw new UnsupportedOperationException("Don't know how to generate this postfix expression: " + op);
|
ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression, bindingContext);
|
||||||
|
DeclarationDescriptor op = resolvedCall.getResultingDescriptor();
|
||||||
|
if (!(op instanceof FunctionDescriptor) || originalOperation == null) {
|
||||||
|
throw new UnsupportedOperationException("Don't know how to generate this postfix expression: " + originalOperationName + " " + op);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type asmType = expressionType(expression);
|
Type asmType = expressionType(expression);
|
||||||
DeclarationDescriptor cls = op.getContainingDeclaration();
|
DeclarationDescriptor cls = op.getContainingDeclaration();
|
||||||
|
|
||||||
int increment;
|
int increment;
|
||||||
if (op.getName().asString().equals("inc")) {
|
if (originalOperationName.equals("inc")) {
|
||||||
increment = 1;
|
increment = 1;
|
||||||
}
|
}
|
||||||
else if (op.getName().asString().equals("dec")) {
|
else if (originalOperationName.equals("dec")) {
|
||||||
increment = -1;
|
increment = -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("Unsupported postfix operation: " + op);
|
throw new UnsupportedOperationException("Unsupported postfix operation: " + originalOperationName + " " + op);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isPrimitiveNumberClassDescriptor = isPrimitiveNumberClassDescriptor(cls);
|
boolean isPrimitiveNumberClassDescriptor = isPrimitiveNumberClassDescriptor(cls);
|
||||||
@@ -3161,7 +3166,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
storeType = type;
|
storeType = type;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression, bindingContext);
|
|
||||||
Callable callable = resolveToCallable((FunctionDescriptor) op, false);
|
Callable callable = resolveToCallable((FunctionDescriptor) op, false);
|
||||||
invokeFunction(resolvedCall, StackValue.onStack(type));
|
invokeFunction(resolvedCall, StackValue.onStack(type));
|
||||||
CallableMethod callableMethod = (CallableMethod) callable;
|
CallableMethod callableMethod = (CallableMethod) callable;
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
class It(val id: String)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val projectId = "projectId"
|
||||||
|
val it = It("it")
|
||||||
|
|
||||||
|
|
||||||
|
fun selectMetaRunnerId(): String {
|
||||||
|
fun Int?.inc() = (this ?: 0) + 1
|
||||||
|
var counter: Int? = null
|
||||||
|
fun path(metaRunnerId: String) = counter != 2
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
val name = projectId + "_" + it.id + (if (counter == null) "" else "_$counter")
|
||||||
|
if (!path(name)) {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val X = selectMetaRunnerId()
|
||||||
|
if (X != projectId + "_" + it.id + "_2") return "fail: $X"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
fun box(): String {
|
||||||
|
fun Int?.inc() = (this ?: 0) + 1
|
||||||
|
var counter: Int? = null
|
||||||
|
counter++
|
||||||
|
return if (counter == 1) "OK" else "fail: $counter"
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
var a = A()
|
||||||
|
var b = A()
|
||||||
|
|
||||||
|
class A(var value: Int = 0)
|
||||||
|
|
||||||
|
fun prefix(inc: A.() -> A) {
|
||||||
|
++a
|
||||||
|
}
|
||||||
|
|
||||||
|
fun postfix(inc: A.() -> A) {
|
||||||
|
b++
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
prefix { ++value; this }
|
||||||
|
|
||||||
|
if (a.value != 1) return "fail 1"
|
||||||
|
|
||||||
|
postfix { value++; this }
|
||||||
|
|
||||||
|
if (b.value != 1) return "fail 2"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -3511,6 +3511,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt4989.kt")
|
||||||
|
public void testKt4989() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/localFunctions/kt4989.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("localExtensionOnNullableParameter.kt")
|
@TestMetadata("localExtensionOnNullableParameter.kt")
|
||||||
public void testLocalExtensionOnNullableParameter() throws Exception {
|
public void testLocalExtensionOnNullableParameter() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/localFunctions/localExtensionOnNullableParameter.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/localFunctions/localExtensionOnNullableParameter.kt");
|
||||||
@@ -5012,6 +5018,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt4987.kt")
|
||||||
|
public void testKt4987() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/operatorConventions/kt4987.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt4991.kt")
|
||||||
|
public void testKt4991() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/operatorConventions/kt4991.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/operatorConventions/compareTo")
|
@TestMetadata("compiler/testData/codegen/box/operatorConventions/compareTo")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
|
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user