crazy bug with constructing object of the same class as calling class

This commit is contained in:
Alex Tkachman
2012-01-24 13:30:38 +02:00
parent 5613cb90f9
commit e61a9f62ba
9 changed files with 111 additions and 27 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
<component name="libraryTable">
<library name="idea-full">
<CLASSES>
<root url="file://$PROJECT_DIR$/ideaSDK/lib" />
<root url="file://$PROJECT_DIR$/IdeaSDK/lib" />
</CLASSES>
<JAVADOC />
<SOURCES />
+1 -1
View File
@@ -1,7 +1,7 @@
<component name="libraryTable">
<library name="intellij-core">
<CLASSES>
<root url="file://$PROJECT_DIR$/ideaSDK/core" />
<root url="file://$PROJECT_DIR$/IdeaSDK/core" />
</CLASSES>
<JAVADOC />
<SOURCES />
@@ -36,7 +36,7 @@ public class CompilationException extends RuntimeException {
col = -1;
}
return "Internal error: (" + (line+1) + "," + col + ") " + (getCause().getMessage() != null ? getCause().getMessage() : getCause().toString());
return "Internal error: (" + (line+1) + "," + col + ") " + (getCause().getMessage() != null ? getCause().getMessage() : getCause().toString()) + "\n@" + getCause().getStackTrace()[0].getFileName() + ":" + getCause().getStackTrace()[0].getLineNumber();
}
@Override
@@ -782,6 +782,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
if(closureCodegen.superCall != null) {
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) closureCodegen.superCall).getCalleeExpression().getConstructorReferenceExpression());
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes();
Collections.addAll(consArgTypes, argumentTypes);
ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, closureCodegen.superCall.getCalleeExpression());
pushMethodArguments(resolvedCall, Arrays.asList(argumentTypes));
}
Method cons = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
v.invokespecial(closure.getClassname(), "<init>", cons.getDescriptor());
return StackValue.onStack(Type.getObjectType(closure.getClassname()));
@@ -21,6 +21,8 @@ import org.objectweb.asm.commons.Method;
import java.util.*;
import static org.jetbrains.jet.codegen.JetTypeMapper.TYPE_OBJECT;
/**
* @author max
* @author yole
@@ -212,6 +214,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
try {
generatePrimaryConstructor();
}
catch (CompilationException e) {
throw e;
}
catch(RuntimeException e) {
throw new RuntimeException("Error generating primary constructor of class " + myClass.getName() + " with kind " + kind, e);
}
@@ -396,6 +401,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
ObjectOrClosureCodegen closure = context.closure;
int firstSuperArgument = -1;
if(closure != null) {
final LinkedList<JvmMethodParameterSignature> consArgTypes = new LinkedList<JvmMethodParameterSignature>(constructorMethod.getKotlinParameterTypes());
@@ -424,6 +430,18 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
if(myClass instanceof JetObjectDeclaration) {
if(superCall instanceof JetDelegatorToSuperCall) {
closure.superCall = (JetDelegatorToSuperCall) superCall;
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
firstSuperArgument = insert;
for(Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
consArgTypes.add(insert++, new JvmMethodParameterSignature(t, "", JvmMethodParameterKind.SHARED_VAR));
}
}
}
constructorMethod = JvmMethodSignature.simple("<init>", Type.VOID_TYPE, consArgTypes);
}
@@ -488,32 +506,31 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
if (superCall == null || superCall instanceof JetDelegatorToSuperClass) {
if (superCall == null) {
iv.load(0, Type.getType("L" + superClass + ";"));
if(superCall == null) {
iv.invokespecial(superClass, "<init>", "()V");
iv.invokespecial(superClass, "<init>", "()V");
}
else if (superCall instanceof JetDelegatorToSuperClass) {
iv.load(0, Type.getType("L" + superClass + ";"));
JetType superType = bindingContext.get(BindingContext.TYPE, superCall.getTypeReference());
List<Type> parameterTypes = new ArrayList<Type>();
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
if (CodegenUtil.hasThis0(superClassDescriptor)) {
iv.load(1, JetTypeMapper.TYPE_OBJECT);
parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
}
else {
JetType superType = bindingContext.get(BindingContext.TYPE, superCall.getTypeReference());
List<Type> parameterTypes = new ArrayList<Type>();
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
if (CodegenUtil.hasThis0(superClassDescriptor)) {
iv.load(1, JetTypeMapper.TYPE_OBJECT);
parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
}
for(TypeProjection typeParameterDescriptor : superType.getArguments()) {
codegen.generateTypeInfo(typeParameterDescriptor.getType(), null);
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
}
Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
iv.invokespecial(typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "<init>", superCallMethod.getDescriptor());
for(TypeProjection typeParameterDescriptor : superType.getArguments()) {
codegen.generateTypeInfo(typeParameterDescriptor.getType(), null);
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
}
Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
iv.invokespecial(typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "<init>", superCallMethod.getDescriptor());
}
else {
iv.load(0, classType);
ConstructorDescriptor constructorDescriptor1 = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) superCall, constructorDescriptor1, frameMap);
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) superCall, constructorDescriptor1, frameMap, firstSuperArgument);
}
int n = 0;
@@ -685,10 +702,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void generateDelegatorToConstructorCall(InstructionAdapter iv, ExpressionCodegen codegen, JetCallElement constructorCall,
ConstructorDescriptor constructorDescriptor,
ConstructorFrameMap frameMap) {
ConstructorFrameMap frameMap, int firstSuperArgument) {
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
Type type;
type = typeMapper.mapType(classDecl.getDefaultType(), OwnerKind.IMPLEMENTATION);
Type type = typeMapper.mapType(classDecl.getDefaultType(), OwnerKind.IMPLEMENTATION);
iv.load(0, type);
@@ -697,7 +713,20 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
codegen.invokeMethodWithArguments(method, constructorCall, StackValue.none());
if(myClass instanceof JetObjectDeclaration && superCall instanceof JetDelegatorToSuperCall) {
iv.load(0, TYPE_OBJECT);
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
int nextVar = firstSuperArgument+1;
for(Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
iv.load(nextVar, t);
nextVar += t.getSize();
}
method.invoke(codegen.v);
}
else {
codegen.invokeMethodWithArguments(method, constructorCall, StackValue.none());
}
}
@Override
@@ -785,7 +814,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (!(thisDescriptor instanceof ConstructorDescriptor)) {
throw new UnsupportedOperationException("expected 'this' delegator to resolve to constructor");
}
generateDelegatorToConstructorCall(iv, codegen, thisCall, (ConstructorDescriptor) thisDescriptor, frameMap);
generateDelegatorToConstructorCall(iv, codegen, thisCall, (ConstructorDescriptor) thisDescriptor, frameMap, flags);
}
else {
throw new UnsupportedOperationException("unknown initializer type");
@@ -1,6 +1,7 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
@@ -20,6 +21,7 @@ public class ObjectOrClosureCodegen {
protected ClassBuilder cv = null;
public String name = null;
protected Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
public JetDelegatorToSuperCall superCall;
public ObjectOrClosureCodegen(ExpressionCodegen exprContext, CodegenContext context, GenerationState state) {
this.exprContext = exprContext;
@@ -0,0 +1,10 @@
class B () {}
open class A(val b : B) {
fun a() = object: A(b) {}
}
fun box() : String {
A(B()).a()
return "OK"
}
@@ -0,0 +1,24 @@
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.List
public object RefreshQueue {
private val queue = ConcurrentLinkedQueue<List<String>>
private val workerThread = Thread(object : Runnable {
override fun run() {
while (!workerThread.isInterrupted()) {
try {
// synchronized(queue) {
// queue.wait()
// }
} catch (e : InterruptedException) {
}
}
}
})
}
fun box() : String {
val t = RefreshQueue.workerThread
return "OK"
}
@@ -243,4 +243,14 @@ public class ClassGenTest extends CodegenTestCase {
public void testKt1018 () throws Exception {
blackBoxFile("regressions/kt1018.kt");
}
public void testKt1120 () throws Exception {
// createEnvironmentWithFullJdk();
// blackBoxFile("regressions/kt1120.kt");
}
public void testSelfCreate() throws Exception {
createEnvironmentWithFullJdk();
blackBoxFile("classes/selfcreate.kt");
}
}