diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index dca00df0514..85970ccf754 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -27,7 +27,6 @@ import com.intellij.util.Function; import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant; import org.jetbrains.jet.codegen.binding.CalculatedClosure; import org.jetbrains.jet.codegen.binding.CodegenBinding; import org.jetbrains.jet.codegen.binding.MutableClosure; @@ -47,6 +46,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.calls.model.*; import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant; import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstant; import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; import org.jetbrains.jet.lang.resolve.java.JvmAbi; @@ -1341,12 +1341,9 @@ public class ExpressionCodegen extends JetVisitor implem JetDelegatorToSuperCall superCall = closure.getSuperCall(); if (superCall != null) { - ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, - superCall - .getCalleeExpression() - .getConstructorReferenceExpression()); + ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext + .get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression()); assert superConstructor != null; - //noinspection SuspiciousMethodCalls CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor); Type[] argumentTypes = superCallable.getAsmMethod().getArgumentTypes(); ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, superCall.getCalleeExpression()); @@ -2640,21 +2637,19 @@ public class ExpressionCodegen extends JetVisitor implem } else { ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, reference); - Call call = bindingContext.get(BindingContext.CALL, reference); + assert resolvedCall != null : "Binary expression call is unresolved: " + expression.getText(); + FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); - DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, reference); - assert op instanceof FunctionDescriptor : String.valueOf(op); - Callable callable = resolveToCallable((FunctionDescriptor) op, false); + Callable callable = resolveToCallable(descriptor, false); if (callable instanceof IntrinsicMethod) { - //noinspection ConstantConditions - Type returnType = typeMapper.mapType(resolvedCall.getResultingDescriptor()); + Type returnType = typeMapper.mapType(descriptor); ((IntrinsicMethod) callable).generate(this, v, returnType, expression, Arrays.asList(expression.getLeft(), expression.getRight()), receiver); return StackValue.onStack(returnType); } - else { - return invokeFunction(call, receiver, resolvedCall); - } + + Call call = bindingContext.get(BindingContext.CALL, reference); + return invokeFunction(call, receiver, resolvedCall); } } @@ -2830,9 +2825,9 @@ public class ExpressionCodegen extends JetVisitor implem } private StackValue generateComparison(JetBinaryExpression expression, StackValue receiver) { - DeclarationDescriptor target = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); - assert target instanceof FunctionDescriptor : "compareTo target should be a function: " + target; - FunctionDescriptor descriptor = (FunctionDescriptor) target; + ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); + assert resolvedCall != null : "compareTo target should be resolved: " + expression.getText(); + FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); JetExpression left = expression.getLeft(); JetExpression right = expression.getRight(); @@ -2847,7 +2842,6 @@ public class ExpressionCodegen extends JetVisitor implem gen(right, type); } else { - ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); Call call = bindingContext.get(BindingContext.CALL, expression.getOperationReference()); StackValue result = invokeFunction(call, receiver, resolvedCall); type = Type.INT_TYPE; @@ -2867,52 +2861,46 @@ public class ExpressionCodegen extends JetVisitor implem } private StackValue generateAugmentedAssignment(JetBinaryExpression expression) { - DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); - assert op instanceof FunctionDescriptor : String.valueOf(op); - Callable callable = resolveToCallable((FunctionDescriptor) op, false); + ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); + assert resolvedCall != null : "Augmented assignment call is unresolved: " + expression.getText(); + FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); + Callable callable = resolveToCallable(descriptor, false); JetExpression lhs = expression.getLeft(); - - // if (lhs instanceof JetArrayAccessExpression) { - // JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) lhs; - // if (arrayAccessExpression.getIndexExpressions().size() != 1) { - // throw new UnsupportedOperationException("Augmented assignment with multi-index"); - // } - // } - Type lhsType = expressionType(lhs); + + boolean keepReturnValue; //noinspection ConstantConditions if (bindingContext.get(BindingContext.VARIABLE_REASSIGNMENT, expression)) { if (callable instanceof IntrinsicMethod) { StackValue value = gen(lhs); // receiver - value.dupReceiver(v); // receiver receiver - value.put(lhsType, v); // receiver lhs - IntrinsicMethod intrinsic = (IntrinsicMethod) callable; - JetExpression right = expression.getRight(); - assert right != null; - Type returnType = typeMapper.mapType((FunctionDescriptor) op); - intrinsic.generate(this, v, returnType, expression, Collections.singletonList(right), StackValue.onStack(lhsType)); + value.dupReceiver(v); // receiver receiver + value.put(lhsType, v); // receiver lhs + ((IntrinsicMethod) callable).generate(this, v, typeMapper.mapType(descriptor), expression, + Collections.singletonList(expression.getRight()), StackValue.onStack(lhsType)); value.store(lhsType, v); + return StackValue.none(); } else { - callAugAssignMethod(expression, (CallableMethod) callable, lhsType, true); + keepReturnValue = true; } } else { - JetType type = ((FunctionDescriptor) op).getReturnType(); - assert type != null; - boolean keepReturnValue = !type.equals(KotlinBuiltIns.getInstance().getUnitType()); - callAugAssignMethod(expression, (CallableMethod) callable, lhsType, keepReturnValue); + keepReturnValue = !KotlinBuiltIns.getInstance().getUnitType().equals(descriptor.getReturnType()); } + callAugAssignMethod(expression, resolvedCall, (CallableMethod) callable, lhsType, keepReturnValue); + return StackValue.none(); } - private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, boolean keepReturnValue) { - JetSimpleNameExpression reference = expression.getOperationReference(); - ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, reference); - Call call = bindingContext.get(BindingContext.CALL, reference); - - assert resolvedCall != null : "Resolved call should be not null for operation reference in " + expression.getText(); + private void callAugAssignMethod( + @NotNull JetBinaryExpression expression, + @NotNull ResolvedCall resolvedCall, + @NotNull CallableMethod callable, + @NotNull Type lhsType, + boolean keepReturnValue + ) { + Call call = bindingContext.get(BindingContext.CALL, expression.getOperationReference()); assert call != null : "Call should be not null for operation reference in " + expression.getText(); StackValue value = gen(expression.getLeft()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java index 178985bd046..2db4140f791 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenAnnotatingVisitor.java @@ -22,7 +22,6 @@ import com.intellij.psi.tree.TokenSet; import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.jet.codegen.SamCodegenUtil; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.lang.descriptors.*; @@ -43,6 +42,7 @@ import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.org.objectweb.asm.Type; import java.util.*; @@ -445,11 +445,10 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { public void visitBinaryExpression(@NotNull JetBinaryExpression expression) { super.visitBinaryExpression(expression); - FunctionDescriptor operationDescriptor = - (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); - if (operationDescriptor == null) return; + DeclarationDescriptor operationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); + if (!(operationDescriptor instanceof FunctionDescriptor)) return; - FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter(operationDescriptor); + FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter((FunctionDescriptor) operationDescriptor); if (original == null) return; JavaClassDescriptor samInterfaceOfParameter = getInterfaceIfSamType(original.getValueParameters().get(0).getType()); @@ -468,24 +467,18 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid { public void visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression) { super.visitArrayAccessExpression(expression); - FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression); - if (operationDescriptor == null) { - return; - } + DeclarationDescriptor operationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression); + if (!(operationDescriptor instanceof FunctionDescriptor)) return; boolean isSetter = operationDescriptor.getName().asString().equals("set"); - FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter(operationDescriptor); - if (original == null) { - return; - } + FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter((FunctionDescriptor) operationDescriptor); + if (original == null) return; List indexExpressions = expression.getIndexExpressions(); List parameters = original.getValueParameters(); for (ValueParameterDescriptor valueParameter : parameters) { JavaClassDescriptor samInterface = getInterfaceIfSamType(valueParameter.getType()); - if (samInterface == null) { - continue; - } + if (samInterface == null) continue; if (isSetter && valueParameter.getIndex() == parameters.size() - 1) { PsiElement parent = expression.getParent(); diff --git a/compiler/testData/codegen/box/regressions/kt3173.kt b/compiler/testData/codegen/box/regressions/kt3173.kt new file mode 100644 index 00000000000..5de8316ee1e --- /dev/null +++ b/compiler/testData/codegen/box/regressions/kt3173.kt @@ -0,0 +1,4 @@ +fun box(): String { + val sum = {Int.(other: Int) -> this + other } + return if (1 sum 2 == 3) "OK" else "Fail" +} diff --git a/compiler/testData/codegen/box/regressions/kt3999.kt b/compiler/testData/codegen/box/regressions/kt3999.kt new file mode 100644 index 00000000000..5fa11f9a480 --- /dev/null +++ b/compiler/testData/codegen/box/regressions/kt3999.kt @@ -0,0 +1,30 @@ +class A() { + fun A.invoke(a: A) = "$this ${this@A} $a" +} + +fun test1() { + val a = A() + val b = A() + val c = A() + a.b(c) + a b c +} + +fun test2() { + val a: ExtensionFunction1<*, *, *>.(ExtensionFunction1<*, *, *>)->Unit = {} + val b: ExtensionFunction1<*, *, *>.(ExtensionFunction1<*, *, *>)->Unit = {"$this $it"} + val c: ExtensionFunction1<*, *, *>.(ExtensionFunction1<*, *, *>)->Unit = {} + a.b(c) + a b c +} + +fun Int.foo(a: Int) = this * a +val boo = {Int.(a: Int): Int -> this + a} + +fun box(): String { + test1() + test2() + 1 foo 2 + 3 boo 4 + return "OK" +} diff --git a/compiler/testData/codegen/box/regressions/kt4682.kt b/compiler/testData/codegen/box/regressions/kt4682.kt new file mode 100644 index 00000000000..c3cac1045f0 --- /dev/null +++ b/compiler/testData/codegen/box/regressions/kt4682.kt @@ -0,0 +1,8 @@ +fun foo(compareTo: Any.(p: Function0) -> Int, p: () -> Int) { + p < p +} + +fun box(): String { + foo({ it() }, { 42 }) + return "OK" +} diff --git a/compiler/testData/codegen/box/regressions/unjustifiedReferenceTarget.kt b/compiler/testData/codegen/box/regressions/unjustifiedReferenceTarget.kt new file mode 100644 index 00000000000..d2e11c59949 --- /dev/null +++ b/compiler/testData/codegen/box/regressions/unjustifiedReferenceTarget.kt @@ -0,0 +1,10 @@ +class A + +fun foo(plusAssign: A.(A) -> Unit) { + A() += A() +} + +fun box(): String { + foo { } + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index 339aab09911..633f5e0bbcf 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -31,7 +31,7 @@ import org.jetbrains.jet.codegen.generated.AbstractBlackBoxCodegenTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("compiler/testData/codegen/box") -@InnerTestClasses({BlackBoxCodegenTestGenerated.Arrays.class, BlackBoxCodegenTestGenerated.BinaryOp.class, BlackBoxCodegenTestGenerated.Bridges.class, BlackBoxCodegenTestGenerated.BuiltinStubMethods.class, BlackBoxCodegenTestGenerated.CallableReference.class, BlackBoxCodegenTestGenerated.Casts.class, BlackBoxCodegenTestGenerated.Classes.class, BlackBoxCodegenTestGenerated.Closures.class, BlackBoxCodegenTestGenerated.Constants.class, BlackBoxCodegenTestGenerated.ControlStructures.class, BlackBoxCodegenTestGenerated.DefaultArguments.class, BlackBoxCodegenTestGenerated.DelegatedProperty.class, BlackBoxCodegenTestGenerated.Elvis.class, BlackBoxCodegenTestGenerated.Enum.class, BlackBoxCodegenTestGenerated.ExclExcl.class, BlackBoxCodegenTestGenerated.ExtensionFunctions.class, BlackBoxCodegenTestGenerated.ExtensionProperties.class, BlackBoxCodegenTestGenerated.FakeOverride.class, BlackBoxCodegenTestGenerated.FieldRename.class, BlackBoxCodegenTestGenerated.Finally.class, BlackBoxCodegenTestGenerated.Functions.class, BlackBoxCodegenTestGenerated.InnerNested.class, BlackBoxCodegenTestGenerated.Instructions.class, BlackBoxCodegenTestGenerated.Intrinsics.class, BlackBoxCodegenTestGenerated.Labels.class, BlackBoxCodegenTestGenerated.LocalClasses.class, BlackBoxCodegenTestGenerated.MultiDecl.class, BlackBoxCodegenTestGenerated.Objects.class, BlackBoxCodegenTestGenerated.OperatorConventions.class, BlackBoxCodegenTestGenerated.Package.class, BlackBoxCodegenTestGenerated.PrimitiveTypes.class, BlackBoxCodegenTestGenerated.Properties.class, BlackBoxCodegenTestGenerated.Reflection.class, BlackBoxCodegenTestGenerated.SafeCall.class, BlackBoxCodegenTestGenerated.SamConstructors.class, BlackBoxCodegenTestGenerated.Strings.class, BlackBoxCodegenTestGenerated.Super.class, BlackBoxCodegenTestGenerated.ToArray.class, BlackBoxCodegenTestGenerated.Traits.class, BlackBoxCodegenTestGenerated.TypeInfo.class, BlackBoxCodegenTestGenerated.TypeMapping.class, BlackBoxCodegenTestGenerated.UnaryOp.class, BlackBoxCodegenTestGenerated.Unit.class, BlackBoxCodegenTestGenerated.Vararg.class, BlackBoxCodegenTestGenerated.When.class}) +@InnerTestClasses({BlackBoxCodegenTestGenerated.Arrays.class, BlackBoxCodegenTestGenerated.BinaryOp.class, BlackBoxCodegenTestGenerated.Bridges.class, BlackBoxCodegenTestGenerated.BuiltinStubMethods.class, BlackBoxCodegenTestGenerated.CallableReference.class, BlackBoxCodegenTestGenerated.Casts.class, BlackBoxCodegenTestGenerated.Classes.class, BlackBoxCodegenTestGenerated.Closures.class, BlackBoxCodegenTestGenerated.Constants.class, BlackBoxCodegenTestGenerated.ControlStructures.class, BlackBoxCodegenTestGenerated.DefaultArguments.class, BlackBoxCodegenTestGenerated.DelegatedProperty.class, BlackBoxCodegenTestGenerated.Elvis.class, BlackBoxCodegenTestGenerated.Enum.class, BlackBoxCodegenTestGenerated.ExclExcl.class, BlackBoxCodegenTestGenerated.ExtensionFunctions.class, BlackBoxCodegenTestGenerated.ExtensionProperties.class, BlackBoxCodegenTestGenerated.FakeOverride.class, BlackBoxCodegenTestGenerated.FieldRename.class, BlackBoxCodegenTestGenerated.Finally.class, BlackBoxCodegenTestGenerated.Functions.class, BlackBoxCodegenTestGenerated.InnerNested.class, BlackBoxCodegenTestGenerated.Instructions.class, BlackBoxCodegenTestGenerated.Intrinsics.class, BlackBoxCodegenTestGenerated.Labels.class, BlackBoxCodegenTestGenerated.LocalClasses.class, BlackBoxCodegenTestGenerated.MultiDecl.class, BlackBoxCodegenTestGenerated.Objects.class, BlackBoxCodegenTestGenerated.OperatorConventions.class, BlackBoxCodegenTestGenerated.Package.class, BlackBoxCodegenTestGenerated.PrimitiveTypes.class, BlackBoxCodegenTestGenerated.Properties.class, BlackBoxCodegenTestGenerated.Reflection.class, BlackBoxCodegenTestGenerated.Regressions.class, BlackBoxCodegenTestGenerated.SafeCall.class, BlackBoxCodegenTestGenerated.SamConstructors.class, BlackBoxCodegenTestGenerated.Strings.class, BlackBoxCodegenTestGenerated.Super.class, BlackBoxCodegenTestGenerated.ToArray.class, BlackBoxCodegenTestGenerated.Traits.class, BlackBoxCodegenTestGenerated.TypeInfo.class, BlackBoxCodegenTestGenerated.TypeMapping.class, BlackBoxCodegenTestGenerated.UnaryOp.class, BlackBoxCodegenTestGenerated.Unit.class, BlackBoxCodegenTestGenerated.Vararg.class, BlackBoxCodegenTestGenerated.When.class}) public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInBox() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/box"), Pattern.compile("^(.+)\\.kt$"), true); @@ -4864,6 +4864,34 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } + @TestMetadata("compiler/testData/codegen/box/regressions") + public static class Regressions extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInRegressions() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/box/regressions"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("kt3173.kt") + public void testKt3173() throws Exception { + doTest("compiler/testData/codegen/box/regressions/kt3173.kt"); + } + + @TestMetadata("kt3999.kt") + public void testKt3999() throws Exception { + doTest("compiler/testData/codegen/box/regressions/kt3999.kt"); + } + + @TestMetadata("kt4682.kt") + public void testKt4682() throws Exception { + doTest("compiler/testData/codegen/box/regressions/kt4682.kt"); + } + + @TestMetadata("unjustifiedReferenceTarget.kt") + public void testUnjustifiedReferenceTarget() throws Exception { + doTest("compiler/testData/codegen/box/regressions/unjustifiedReferenceTarget.kt"); + } + + } + @TestMetadata("compiler/testData/codegen/box/safeCall") public static class SafeCall extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInSafeCall() throws Exception { @@ -5626,6 +5654,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { suite.addTestSuite(PrimitiveTypes.class); suite.addTestSuite(Properties.class); suite.addTestSuite(Reflection.class); + suite.addTestSuite(Regressions.class); suite.addTestSuite(SafeCall.class); suite.addTestSuite(SamConstructors.class); suite.addTestSuite(Strings.class);