diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index ea0c74197d1..b9dd5c12a0a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -21,7 +21,6 @@ import com.google.common.collect.Maps; import com.intellij.openapi.editor.Document; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiMethod; import com.intellij.psi.tree.IElementType; import com.intellij.util.Function; import com.intellij.util.containers.Stack; @@ -45,7 +44,6 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastReceiver; import org.jetbrains.jet.lang.resolve.calls.model.*; @@ -1745,7 +1743,6 @@ public class ExpressionCodegen extends JetVisitor implem throw new CompilationException("Cannot resolve: " + callee.getText(), null, expression); } - DeclarationDescriptor funDescriptor = resolvedCall.getResultingDescriptor(); if (!(funDescriptor instanceof FunctionDescriptor)) { @@ -1755,28 +1752,26 @@ public class ExpressionCodegen extends JetVisitor implem funDescriptor = accessableFunctionDescriptor((FunctionDescriptor) funDescriptor); if (funDescriptor instanceof ConstructorDescriptor) { - receiver = StackValue.receiver(resolvedCall, receiver, this, null); - return generateConstructorCall(expression, (JetSimpleNameExpression) callee, receiver); + return generateNewCall(expression, resolvedCall, receiver); } - else { - Call call = bindingContext.get(CALL, expression.getCalleeExpression()); - if (resolvedCall instanceof VariableAsFunctionResolvedCall) { - VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall; - ResolvedCallWithTrace functionCall = variableAsFunctionResolvedCall.getFunctionCall(); - return invokeFunction(call, receiver, functionCall); - } - else { - if (funDescriptor instanceof SimpleFunctionDescriptor) { - ClassDescriptor samInterface = bindingContext.get( - BindingContext.SAM_CONSTRUCTOR_TO_INTERFACE, ((SimpleFunctionDescriptor) funDescriptor).getOriginal()); - if (samInterface != null) { - return invokeSamConstructor(expression, resolvedCall, (SimpleFunctionDescriptor) funDescriptor, samInterface); - } - } - return invokeFunction(call, receiver, resolvedCall); + Call call = bindingContext.get(CALL, expression.getCalleeExpression()); + if (resolvedCall instanceof VariableAsFunctionResolvedCall) { + VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall; + ResolvedCallWithTrace functionCall = variableAsFunctionResolvedCall.getFunctionCall(); + return invokeFunction(call, receiver, functionCall); + } + + if (funDescriptor instanceof SimpleFunctionDescriptor) { + ClassDescriptor samInterface = bindingContext.get( + BindingContext.SAM_CONSTRUCTOR_TO_INTERFACE, ((SimpleFunctionDescriptor) funDescriptor).getOriginal()); + + if (samInterface != null) { + return invokeSamConstructor(expression, resolvedCall, (SimpleFunctionDescriptor) funDescriptor, samInterface); } } + + return invokeFunction(call, receiver, resolvedCall); } @Nullable @@ -1992,27 +1987,18 @@ public class ExpressionCodegen extends JetVisitor implem } } - public void invokeMethodWithArguments(CallableMethod callableMethod, JetCallElement expression, StackValue receiver) { - JetExpression calleeExpression = expression.getCalleeExpression(); - Call call = bindingContext.get(CALL, calleeExpression); - ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, calleeExpression); - assert resolvedCall != null; - assert call != null; - invokeMethodWithArguments(callableMethod, resolvedCall, call, receiver); - } - - - private void invokeMethodWithArguments( + public void invokeMethodWithArguments( @NotNull CallableMethod callableMethod, @NotNull ResolvedCall resolvedCall, - @NotNull Call call, + @Nullable Call callToGenerateCallee, @NotNull StackValue receiver ) { Type calleeType = callableMethod.getGenerateCalleeType(); if (calleeType != null) { assert !callableMethod.isNeedsThis(); - gen(call.getCalleeExpression(), calleeType); + assert callToGenerateCallee != null : "Call can't be null when generating callee: " + resolvedCall.getResultingDescriptor(); + gen(callToGenerateCallee.getCalleeExpression(), calleeType); } if (resolvedCall instanceof VariableAsFunctionResolvedCall) { @@ -2984,76 +2970,56 @@ public class ExpressionCodegen extends JetVisitor implem } } - private StackValue generateConstructorCall( - JetCallExpression expression, - JetSimpleNameExpression constructorReference, - StackValue receiver + @NotNull + private StackValue generateNewCall( + @NotNull JetCallExpression expression, + @NotNull ResolvedCall resolvedCall, + @NotNull StackValue receiver ) { - DeclarationDescriptor constructorDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, constructorReference); - assert constructorDescriptor != null; - PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, constructorDescriptor); - Type type; - if (declaration instanceof PsiMethod) { - type = generateJavaConstructorCall(expression); + Type type = expressionType(expression); + if (type.getSort() == Type.ARRAY) { + generateNewArray(expression); + return StackValue.onStack(type); } - else if (constructorDescriptor instanceof ConstructorDescriptor) { - //noinspection ConstantConditions - JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); - assert expressionType != null; - type = typeMapper.mapType(expressionType); - if (type.getSort() == Type.ARRAY) { - generateNewArray(expression, expressionType); - } - else { - v.anew(type); - v.dup(); - ClassDescriptor classDescriptor = ((ConstructorDescriptor) constructorDescriptor).getContainingDeclaration(); + return generateConstructorCall(resolvedCall, receiver, type); + } - CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor); + @NotNull + private StackValue generateConstructorCall( + @NotNull ResolvedCall resolvedCall, + @NotNull StackValue receiver, + @NotNull Type type + ) { + v.anew(type); + v.dup(); - receiver.put(receiver.type, v); + receiver = StackValue.receiver(resolvedCall, receiver, this, null); + receiver.put(receiver.type, v); - MutableClosure closure = bindingContext.get(CLOSURE, classDescriptor); + ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); + MutableClosure closure = bindingContext.get(CLOSURE, constructorDescriptor.getContainingDeclaration()); - if(receiver.type.getSort() != Type.VOID && (closure == null || closure.getCaptureThis() == null)) { - v.pop(); - } - - pushClosureOnStack(closure, true); - invokeMethodWithArguments(method, expression, StackValue.none()); - } - } - else { - throw new UnsupportedOperationException("don't know how to generate this new expression"); + if (receiver.type.getSort() != Type.VOID && (closure == null || closure.getCaptureThis() == null)) { + v.pop(); } + + pushClosureOnStack(closure, true); + + CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor); + invokeMethodWithArguments(method, resolvedCall, null, StackValue.none()); + return StackValue.onStack(type); } - private Type generateJavaConstructorCall(JetCallExpression expression) { - JetExpression callee = expression.getCalleeExpression(); - ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, callee); - if (resolvedCall == null) { - assert callee != null; - throw new CompilationException("Cannot resolve: " + callee.getText(), null, expression); - } + public void generateNewArray(@NotNull JetCallExpression expression) { + JetType arrayType = bindingContext.get(EXPRESSION_TYPE, expression); + assert arrayType != null : "Array instantiation isn't type checked: " + expression.getText(); - FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); - ClassDescriptor javaClass = (ClassDescriptor) descriptor.getContainingDeclaration(); - Type type = asmType(javaClass.getDefaultType()); - v.anew(type); - v.dup(); - CallableMethod callableMethod = typeMapper.mapToCallableMethod( - descriptor, - false, - isCallInsideSameClassAsDeclared(descriptor, context), - isCallInsideSameModuleAsDeclared(descriptor, context), - OwnerKind.IMPLEMENTATION); - invokeMethodWithArguments(callableMethod, expression, StackValue.none()); - return type; + generateNewArray(expression, arrayType); } - public void generateNewArray(JetCallExpression expression, JetType arrayType) { + private void generateNewArray(@NotNull JetCallExpression expression, @NotNull JetType arrayType) { List args = new ArrayList(); for (ValueArgument va : expression.getValueArguments()) { args.add(va.getArgumentExpression()); @@ -3061,15 +3027,8 @@ public class ExpressionCodegen extends JetVisitor implem args.addAll(expression.getFunctionLiteralArguments()); boolean isArray = KotlinBuiltIns.getInstance().isArray(arrayType); - if (isArray) { - // if (args.size() != 2 && !arrayType.getArguments().get(0).getType().isNullable()) { - // throw new CompilationException("array constructor of non-nullable type requires two arguments"); - // } - } - else { - if (args.size() != 1) { - throw new CompilationException("primitive array constructor requires one argument", null, expression); - } + if (!isArray && args.size() != 1) { + throw new CompilationException("primitive array constructor requires one argument", null, expression); } if (isArray) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index adf679d7b34..6f50f4277a8 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -1488,7 +1488,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { superCallable.invokeWithNotNullAssertion(codegen.v, state, resolvedCall); } else { - codegen.invokeMethodWithArguments(superCallable, (JetCallElement) superCall, StackValue.none()); + codegen.invokeMethodWithArguments(superCallable, resolvedCall, null, StackValue.none()); } } @@ -1571,13 +1571,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(state.getBindingContext(), enumConstant)) { JetDelegationSpecifier specifier = delegationSpecifiers.get(0); if (specifier instanceof JetDelegatorToSuperCall) { - JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier; - ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) bindingContext - .get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression()); - assert constructorDescriptor != null; - //noinspection SuspiciousMethodCalls + ResolvedCall resolvedCall = + bindingContext.get(BindingContext.RESOLVED_CALL, ((JetDelegatorToSuperCall) specifier).getCalleeExpression()); + assert resolvedCall != null : "Enum entry delegation specifier is unresolved: " + specifier.getText(); + + ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor); - codegen.invokeMethodWithArguments(method, superCall, StackValue.none()); + + codegen.invokeMethodWithArguments(method, resolvedCall, null, StackValue.none()); } else { throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/NewArray.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/NewArray.java index ce2ea878772..61a1e442f62 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/NewArray.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/NewArray.java @@ -25,7 +25,6 @@ import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.lang.psi.JetCallExpression; import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.resolve.BindingContext; import java.util.List; @@ -40,8 +39,7 @@ public class NewArray implements IntrinsicMethod { StackValue receiver, @NotNull GenerationState state ) { - codegen.generateNewArray((JetCallExpression) element, - codegen.getBindingContext().get(BindingContext.EXPRESSION_TYPE, (JetExpression) element)); + codegen.generateNewArray((JetCallExpression) element); return StackValue.onStack(expectedType); } } diff --git a/compiler/testData/codegen/boxWithJava/functions/constructor.java b/compiler/testData/codegen/boxWithJava/functions/constructor.java new file mode 100644 index 00000000000..ec67d65e061 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/functions/constructor.java @@ -0,0 +1,7 @@ +class A { + public A() {} + + public A(String x) {} + + public A(long l, double z) {} +} diff --git a/compiler/testData/codegen/boxWithJava/functions/constructor.kt b/compiler/testData/codegen/boxWithJava/functions/constructor.kt new file mode 100644 index 00000000000..73e131eb60a --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/functions/constructor.kt @@ -0,0 +1,6 @@ +fun box(): String { + A() + A("") + A(0.toLong(), 0.0) + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java index 45faca6cf12..d6eee2471d7 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java @@ -81,6 +81,11 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/boxWithJava/functions"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("constructor.kt") + public void testConstructor() throws Exception { + doTestWithJava("compiler/testData/codegen/boxWithJava/functions/constructor.kt"); + } + @TestMetadata("referencesStaticInnerClassMethod.kt") public void testReferencesStaticInnerClassMethod() throws Exception { doTestWithJava("compiler/testData/codegen/boxWithJava/functions/referencesStaticInnerClassMethod.kt");