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:
Michael Bogdanov
2014-10-03 14:36:13 +04:00
parent 0c11ca680e
commit 15043b3c6d
5 changed files with 89 additions and 13 deletions
@@ -3069,24 +3069,25 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@Override
public StackValue visitPrefixExpression(@NotNull JetPrefixExpression expression, StackValue receiver) {
DeclarationDescriptor op = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference());
assert op instanceof FunctionDescriptor : String.valueOf(op);
DeclarationDescriptor originalOperation = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference());
ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression, bindingContext);
CallableDescriptor op = resolvedCall.getResultingDescriptor();
assert op instanceof FunctionDescriptor || originalOperation == null : String.valueOf(op);
Callable callable = resolveToCallable((FunctionDescriptor) op, false);
if (callable instanceof IntrinsicMethod) {
Type returnType = typeMapper.mapType((FunctionDescriptor) op);
Type returnType = typeMapper.mapType(op);
((IntrinsicMethod) callable).generate(this, v, returnType, expression,
Collections.singletonList(expression.getBaseExpression()), receiver);
return StackValue.onStack(returnType);
}
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);
}
CallableMethod callableMethod = (CallableMethod) callable;
StackValue value = gen(expression.getBaseExpression());
value.dupReceiver(v);
@@ -3096,6 +3097,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
value.put(type, v);
invokeFunction(resolvedCall, StackValue.onStack(type));
CallableMethod callableMethod = (CallableMethod) callable;
value.store(callableMethod.getReturnType(), v);
value.put(type, v);
return StackValue.onStack(type);
@@ -3117,23 +3119,26 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return StackValue.onStack(base.type);
}
DeclarationDescriptor op = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference());
if (!(op instanceof FunctionDescriptor)) {
throw new UnsupportedOperationException("Don't know how to generate this postfix expression: " + op);
DeclarationDescriptor originalOperation = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference());
String originalOperationName = originalOperation != null ? originalOperation.getName().asString() : null;
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);
DeclarationDescriptor cls = op.getContainingDeclaration();
int increment;
if (op.getName().asString().equals("inc")) {
if (originalOperationName.equals("inc")) {
increment = 1;
}
else if (op.getName().asString().equals("dec")) {
else if (originalOperationName.equals("dec")) {
increment = -1;
}
else {
throw new UnsupportedOperationException("Unsupported postfix operation: " + op);
throw new UnsupportedOperationException("Unsupported postfix operation: " + originalOperationName + " " + op);
}
boolean isPrimitiveNumberClassDescriptor = isPrimitiveNumberClassDescriptor(cls);
@@ -3161,7 +3166,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
storeType = type;
}
else {
ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression, bindingContext);
Callable callable = resolveToCallable((FunctionDescriptor) op, false);
invokeFunction(resolvedCall, StackValue.onStack(type));
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);
}
@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")
public void testLocalExtensionOnNullableParameter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/localFunctions/localExtensionOnNullableParameter.kt");
@@ -5012,6 +5018,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
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")
@TestDataPath("$PROJECT_ROOT")
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)