diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AccessorForFunctionDescriptor.java b/compiler/backend/src/org/jetbrains/jet/codegen/AccessorForFunctionDescriptor.java index 1f7160d83cf..544e3e78620 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AccessorForFunctionDescriptor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AccessorForFunctionDescriptor.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.codegen; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import java.util.Collections; @@ -28,13 +29,13 @@ import java.util.Collections; public class AccessorForFunctionDescriptor extends SimpleFunctionDescriptorImpl { public AccessorForFunctionDescriptor(DeclarationDescriptor descriptor, DeclarationDescriptor containingDeclaration, int index) { super(containingDeclaration, Collections.emptyList(), - Name.identifier(descriptor.getName() + "$b$" + index), + Name.identifier((descriptor instanceof ConstructorDescriptor ? "$init" : descriptor.getName())+ "$b$" + index), Kind.DECLARATION); - FunctionDescriptor fd = (SimpleFunctionDescriptor) descriptor; + FunctionDescriptor fd = (FunctionDescriptor) descriptor; initialize(fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null, - fd.getExpectedThisObject(), + descriptor instanceof ConstructorDescriptor ? ReceiverDescriptor.NO_RECEIVER : fd.getExpectedThisObject(), Collections.emptyList(), fd.getValueParameters(), fd.getReturnType(), diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 7acda0055ad..cb49db99d81 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1086,9 +1086,7 @@ public class ExpressionCodegen extends JetVisitor implem .getConstructorReferenceExpression()); assert superConstructor != null; //noinspection SuspiciousMethodCalls - CallableMethod superCallable = typeMapper - .mapToCallableMethod(superConstructor, - bindingContext.get(CLOSURE, superConstructor.getContainingDeclaration())); + CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor); Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes(); ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, superCall.getCalleeExpression()); assert resolvedCall != null; @@ -1631,14 +1629,20 @@ public class ExpressionCodegen extends JetVisitor implem throw new CompilationException("Cannot resolve: " + callee.getText(), null, expression); } + DeclarationDescriptor funDescriptor = resolvedCall.getResultingDescriptor(); + if (!(funDescriptor instanceof FunctionDescriptor)) { + throw new UnsupportedOperationException("unknown type of callee descriptor: " + funDescriptor); + } + + funDescriptor = accessableFunctionDescriptor((FunctionDescriptor) funDescriptor); + if (funDescriptor instanceof ConstructorDescriptor) { receiver = StackValue.receiver(resolvedCall, receiver, this, null); return generateConstructorCall(expression, (JetSimpleNameExpression) callee, receiver); } - - if (funDescriptor instanceof FunctionDescriptor) { + else { Call call = bindingContext.get(CALL, expression.getCalleeExpression()); if (resolvedCall instanceof VariableAsFunctionResolvedCall) { VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall; @@ -1649,9 +1653,6 @@ public class ExpressionCodegen extends JetVisitor implem return invokeFunction(call, receiver, resolvedCall); } } - else { - throw new UnsupportedOperationException("unknown type of callee descriptor: " + funDescriptor); - } } private PropertyDescriptor accessablePropertyDescriptor(PropertyDescriptor propertyDescriptor) { @@ -2920,9 +2921,7 @@ public class ExpressionCodegen extends JetVisitor implem final ClassDescriptor classDescriptor = ((ConstructorDescriptor) constructorDescriptor).getContainingDeclaration(); - CallableMethod method = typeMapper - .mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, - bindingContext.get(CLOSURE, classDescriptor)); + CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor); receiver.put(receiver.type, v); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index dfac1355298..300071c9632 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -446,7 +446,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { FunctionDescriptor original = (FunctionDescriptor) entry.getKey(); Method method = typeMapper.mapSignature(bridge.getName(), bridge).getAsmMethod(); - Method originalMethod = typeMapper.mapSignature(original.getName(), original).getAsmMethod(); + final boolean isConstructor = original instanceof ConstructorDescriptor; + Method originalMethod = isConstructor ? + typeMapper.mapToCallableMethod((ConstructorDescriptor) original).getSignature().getAsmMethod() : + typeMapper.mapSignature(original.getName(), original).getAsmMethod(); Type[] argTypes = method.getArgumentTypes(); String owner = typeMapper.getOwner(original, OwnerKind.IMPLEMENTATION).getInternalName(); @@ -460,8 +463,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { InstructionAdapter iv = new InstructionAdapter(mv); - iv.load(0, OBJECT_TYPE); - for (int i = 1, reg = 1; i < argTypes.length; i++) { + if (isConstructor) { + iv.anew(method.getReturnType()); + iv.dup(); + } + else { + // todo: note that for now we never have access bridges for namespace methods, if at some point we do... + iv.load(0, OBJECT_TYPE); + } + + for (int i = isConstructor ? 0 : 1, reg = isConstructor ? 0 : 1; i < argTypes.length; i++) { Type argType = argTypes[i]; iv.load(reg, argType); //noinspection AssignmentToForLoopParameter @@ -1108,8 +1119,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { //noinspection SuspiciousMethodCalls final CalculatedClosure closureForSuper = bindingContext.get(CLOSURE, superConstructor.getContainingDeclaration()); - CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, - closureForSuper); + CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, closureForSuper); if (closureForSuper != null && closureForSuper.getCaptureThis() != null) { iv.load(frameMap.getOuterThisIndex(), OBJECT_TYPE); @@ -1214,8 +1224,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { .get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression()); assert constructorDescriptor != null; //noinspection SuspiciousMethodCalls - CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, bindingContext - .get(CLOSURE, constructorDescriptor.getContainingDeclaration())); + CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor); codegen.invokeMethodWithArguments(method, superCall, StackValue.none()); } else { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java index 64eece2a5c2..2c9d7ec8653 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/context/CodegenContext.java @@ -227,14 +227,14 @@ public abstract class CodegenContext { return accessor; } - if (descriptor instanceof SimpleFunctionDescriptor) { + if (descriptor instanceof SimpleFunctionDescriptor || descriptor instanceof ConstructorDescriptor) { accessor = new AccessorForFunctionDescriptor(descriptor, contextDescriptor, accessors.size()); } else if (descriptor instanceof PropertyDescriptor) { accessor = new AccessorForPropertyDescriptor((PropertyDescriptor) descriptor, contextDescriptor, accessors.size()); } else { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException("Do not know how to create accessor for descriptor " + descriptor); } accessors.put(descriptor, accessor); return accessor; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java index 3581d2b0f4a..9b62b9b7103 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java @@ -23,6 +23,7 @@ import org.jetbrains.asm4.Type; import org.jetbrains.jet.codegen.*; import org.jetbrains.jet.codegen.binding.BindingTraceAware; import org.jetbrains.jet.codegen.binding.CalculatedClosure; +import org.jetbrains.jet.codegen.binding.CodegenBinding; import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor; import org.jetbrains.jet.codegen.signature.*; import org.jetbrains.jet.lang.descriptors.*; @@ -474,11 +475,7 @@ public class JetTypeMapper extends BindingTraceAware { signatureVisitor.writeParametersStart(); - if (isAccessor(f)) { - signatureVisitor.writeParameterType(JvmMethodParameterKind.THIS); - mapType(((ClassifierDescriptor) f.getContainingDeclaration()).getDefaultType(), signatureVisitor, JetTypeMapperMode.VALUE); - signatureVisitor.writeParameterTypeEnd(); - } + writeThisForAccessorIfNeeded(f, signatureVisitor); if (kind == OwnerKind.TRAIT_IMPL) { ClassDescriptor containingDeclaration = (ClassDescriptor) f.getContainingDeclaration(); @@ -501,9 +498,7 @@ public class JetTypeMapper extends BindingTraceAware { } for (ValueParameterDescriptor parameter : parameters) { - signatureVisitor.writeParameterType(JvmMethodParameterKind.VALUE); - mapType(parameter.getType(), signatureVisitor, JetTypeMapperMode.VALUE); - signatureVisitor.writeParameterTypeEnd(); + writeParameter(signatureVisitor, parameter.getType()); } signatureVisitor.writeParametersEnd(); @@ -521,6 +516,14 @@ public class JetTypeMapper extends BindingTraceAware { return signatureVisitor.makeJvmMethodSignature(f.getName().getName()); } + private void writeThisForAccessorIfNeeded(FunctionDescriptor f, BothSignatureWriter signatureVisitor) { + if (isAccessor(f) && f.getExpectedThisObject().exists()) { + signatureVisitor.writeParameterType(JvmMethodParameterKind.THIS); + mapType(((ClassifierDescriptor) f.getContainingDeclaration()).getDefaultType(), signatureVisitor, JetTypeMapperMode.VALUE); + signatureVisitor.writeParameterTypeEnd(); + } + } + public void writeFormalTypeParameters(List typeParameters, BothSignatureWriter signatureVisitor) { if (signatureVisitor == null) { @@ -585,22 +588,12 @@ public class JetTypeMapper extends BindingTraceAware { signatureWriter.writeParametersStart(); - if (isAccessor(f)) { - signatureWriter.writeParameterType(JvmMethodParameterKind.THIS); - mapType(((ClassifierDescriptor) f.getContainingDeclaration()).getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE); - signatureWriter.writeParameterTypeEnd(); - } + writeThisForAccessorIfNeeded(f, signatureWriter); final List parameters = f.getValueParameters(); - if (receiver.exists()) { - signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER); - mapType(receiver.getType(), signatureWriter, JetTypeMapperMode.VALUE); - signatureWriter.writeParameterTypeEnd(); - } + writeReceiverIfNeeded(receiver, signatureWriter); for (ValueParameterDescriptor parameter : parameters) { - signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE); - mapType(parameter.getType(), signatureWriter, JetTypeMapperMode.VALUE); - signatureWriter.writeParameterTypeEnd(); + writeParameter(signatureWriter, parameter.getType()); } signatureWriter.writeParametersEnd(); @@ -614,6 +607,14 @@ public class JetTypeMapper extends BindingTraceAware { return signatureWriter.makeJvmMethodSignature(name.getName()); } + private void writeReceiverIfNeeded(ReceiverDescriptor receiver, BothSignatureWriter signatureWriter) { + if (receiver.exists()) { + signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER); + mapType(receiver.getType(), signatureWriter, JetTypeMapperMode.VALUE); + signatureWriter.writeParameterTypeEnd(); + } + } + public JvmPropertyAccessorSignature mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) { final DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration(); @@ -643,11 +644,7 @@ public class JetTypeMapper extends BindingTraceAware { } } - if (descriptor.getReceiverParameter().exists()) { - signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER); - mapType(descriptor.getReceiverParameter().getType(), signatureWriter, JetTypeMapperMode.VALUE); - signatureWriter.writeParameterTypeEnd(); - } + writeReceiverIfNeeded(descriptor.getReceiverParameter(), signatureWriter); signatureWriter.writeParametersEnd(); @@ -689,15 +686,9 @@ public class JetTypeMapper extends BindingTraceAware { } } - if (descriptor.getReceiverParameter().exists()) { - signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER); - mapType(descriptor.getReceiverParameter().getType(), signatureWriter, JetTypeMapperMode.VALUE); - signatureWriter.writeParameterTypeEnd(); - } + writeReceiverIfNeeded(descriptor.getReceiverParameter(), signatureWriter); - signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE); - mapType(outType, signatureWriter, JetTypeMapperMode.VALUE); - signatureWriter.writeParameterTypeEnd(); + writeParameter(signatureWriter, outType); signatureWriter.writeParametersEnd(); @@ -708,6 +699,12 @@ public class JetTypeMapper extends BindingTraceAware { jvmMethodSignature.getKotlinParameterType(jvmMethodSignature.getParameterCount() - 1)); } + private void writeParameter(BothSignatureWriter signatureWriter, JetType outType) { + signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE); + mapType(outType, signatureWriter, JetTypeMapperMode.VALUE); + signatureWriter.writeParameterTypeEnd(); + } + private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, CalculatedClosure closure) { BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true); @@ -766,9 +763,7 @@ public class JetTypeMapper extends BindingTraceAware { if (isObjectLiteral(bindingContext, descriptor.getContainingDeclaration())) { //noinspection SuspiciousMethodCalls - CallableMethod superCallable = mapToCallableMethod(superConstructor, - bindingContext.get(CLOSURE, - superConstructor.getContainingDeclaration())); + CallableMethod superCallable = mapToCallableMethod(superConstructor); final List types = superCallable.getSignature().getKotlinParameterTypes(); if (types != null) { for (JvmMethodParameterSignature type : types) { @@ -783,9 +778,7 @@ public class JetTypeMapper extends BindingTraceAware { } for (ValueParameterDescriptor parameter : descriptor.getOriginal().getValueParameters()) { - signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE); - mapType(parameter.getType(), signatureWriter, JetTypeMapperMode.VALUE); - signatureWriter.writeParameterTypeEnd(); + writeParameter(signatureWriter, parameter.getType()); } signatureWriter.writeParametersEnd(); @@ -812,9 +805,7 @@ public class JetTypeMapper extends BindingTraceAware { } for (ValueParameterDescriptor valueParameter : script.getValueParameters()) { - signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE); - mapType(valueParameter.getType(), signatureWriter, JetTypeMapperMode.VALUE); - signatureWriter.writeParameterTypeEnd(); + writeParameter(signatureWriter, valueParameter.getType()); } signatureWriter.writeParametersEnd(); @@ -824,6 +815,10 @@ public class JetTypeMapper extends BindingTraceAware { return signatureWriter.makeJvmMethodSignature(""); } + public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor) { + return mapToCallableMethod(descriptor, bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration())); + } + public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, CalculatedClosure closure) { final JvmMethodSignature method = mapConstructorSignature(descriptor, closure); JetType defaultType = descriptor.getContainingDeclaration().getDefaultType(); diff --git a/compiler/testData/codegen/regressions/kt2716.kt b/compiler/testData/codegen/regressions/kt2716.kt new file mode 100644 index 00000000000..cb89f62430e --- /dev/null +++ b/compiler/testData/codegen/regressions/kt2716.kt @@ -0,0 +1,11 @@ +package someTest + +public class Some private(val v: String) { + class object { + public fun init(v: String): Some { + return Some(v) + } + } +} + +fun box() = Some.init("OK").v diff --git a/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java index d46c2e15c8d..3e42a77dc5f 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java @@ -32,6 +32,11 @@ public class FunctionGenTest extends CodegenTestCase { createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); } + public void testKt2716() throws Exception { + blackBoxFile("regressions/kt2716.kt"); + // System.out.println(generateToText()); + } + public void testDefaultArgs() throws Exception { blackBoxFile("functions/defaultargs.jet"); // System.out.println(generateToText());