From 15043b3c6d2146f52e929a726804bc6f1437c23d Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Fri, 3 Oct 2014 14:36:13 +0400 Subject: [PATCH] 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 --- .../jet/codegen/ExpressionCodegen.java | 30 +++++++++++-------- .../box/functions/localFunctions/kt4989.kt | 24 +++++++++++++++ .../codegen/box/operatorConventions/kt4987.kt | 6 ++++ .../codegen/box/operatorConventions/kt4991.kt | 24 +++++++++++++++ .../BlackBoxCodegenTestGenerated.java | 18 +++++++++++ 5 files changed, 89 insertions(+), 13 deletions(-) create mode 100644 compiler/testData/codegen/box/functions/localFunctions/kt4989.kt create mode 100644 compiler/testData/codegen/box/operatorConventions/kt4987.kt create mode 100644 compiler/testData/codegen/box/operatorConventions/kt4991.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index e84cac2d840..8f6517755b5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -3069,24 +3069,25 @@ public class ExpressionCodegen extends JetVisitor 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 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 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 implem storeType = type; } else { - ResolvedCall resolvedCall = getResolvedCallWithAssert(expression, bindingContext); Callable callable = resolveToCallable((FunctionDescriptor) op, false); invokeFunction(resolvedCall, StackValue.onStack(type)); CallableMethod callableMethod = (CallableMethod) callable; diff --git a/compiler/testData/codegen/box/functions/localFunctions/kt4989.kt b/compiler/testData/codegen/box/functions/localFunctions/kt4989.kt new file mode 100644 index 00000000000..6f71e73c9b9 --- /dev/null +++ b/compiler/testData/codegen/box/functions/localFunctions/kt4989.kt @@ -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" +} diff --git a/compiler/testData/codegen/box/operatorConventions/kt4987.kt b/compiler/testData/codegen/box/operatorConventions/kt4987.kt new file mode 100644 index 00000000000..3b850a340da --- /dev/null +++ b/compiler/testData/codegen/box/operatorConventions/kt4987.kt @@ -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" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/operatorConventions/kt4991.kt b/compiler/testData/codegen/box/operatorConventions/kt4991.kt new file mode 100644 index 00000000000..86aa5d06081 --- /dev/null +++ b/compiler/testData/codegen/box/operatorConventions/kt4991.kt @@ -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" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index 201f48c9a39..cd31d7f57c8 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -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)