Get rid of superCall fields in class/closure codegen
Because their semantics looks wrong in case of secondary constructors. Use resolved delegation call instead.
This commit is contained in:
@@ -64,6 +64,7 @@ import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject;
|
|||||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant;
|
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant;
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.EvaluatePackage;
|
import org.jetbrains.kotlin.resolve.constants.evaluate.EvaluatePackage;
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
|
||||||
import org.jetbrains.kotlin.types.Approximation;
|
import org.jetbrains.kotlin.types.Approximation;
|
||||||
@@ -1428,7 +1429,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
pushClosureOnStack(classDescriptor, true, defaultCallGenerator);
|
pushClosureOnStack(classDescriptor, true, defaultCallGenerator);
|
||||||
|
|
||||||
ResolvedCall<ConstructorDescriptor> superCall = bindingContext.get(CLOSURE, classDescriptor).getSuperCall();
|
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||||
|
assert primaryConstructor != null : "There should be primary constructor for object literal";
|
||||||
|
ResolvedCall<ConstructorDescriptor> superCall = getDelegationConstructorCall(bindingContext, primaryConstructor);
|
||||||
if (superCall != null) {
|
if (superCall != null) {
|
||||||
// For an anonymous object, we should also generate all non-default arguments that it captures for its super call
|
// For an anonymous object, we should also generate all non-default arguments that it captures for its super call
|
||||||
ConstructorDescriptor superConstructor = superCall.getResultingDescriptor();
|
ConstructorDescriptor superConstructor = superCall.getResultingDescriptor();
|
||||||
@@ -1496,10 +1499,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
callGenerator.putCapturedValueOnStack(capturedVar, sharedVarType, paramIndex++);
|
callGenerator.putCapturedValueOnStack(capturedVar, sharedVarType, paramIndex++);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResolvedCall<ConstructorDescriptor> superCall = closure.getSuperCall();
|
|
||||||
if (superCall != null) {
|
ClassDescriptor superClass = DescriptorUtilPackage.getSuperClassNotAny(classDescriptor);
|
||||||
|
if (superClass != null) {
|
||||||
pushClosureOnStack(
|
pushClosureOnStack(
|
||||||
superCall.getResultingDescriptor().getContainingDeclaration(),
|
superClass,
|
||||||
putThis && closure.getCaptureThis() == null,
|
putThis && closure.getCaptureThis() == null,
|
||||||
callGenerator
|
callGenerator
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument;
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
|
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument;
|
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument;
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||||
@@ -85,7 +86,6 @@ import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
|||||||
|
|
||||||
public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||||
private static final String ENUM_VALUES_FIELD_NAME = "$VALUES";
|
private static final String ENUM_VALUES_FIELD_NAME = "$VALUES";
|
||||||
private JetDelegatorToSuperCall superCall;
|
|
||||||
private Type superClassAsmType;
|
private Type superClassAsmType;
|
||||||
@Nullable // null means java/lang/Object
|
@Nullable // null means java/lang/Object
|
||||||
private JetType superClassType;
|
private JetType superClassType;
|
||||||
@@ -346,7 +346,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
if (!isInterface(superClassDescriptor)) {
|
if (!isInterface(superClassDescriptor)) {
|
||||||
superClassType = superType;
|
superClassType = superType;
|
||||||
superClassAsmType = typeMapper.mapClass(superClassDescriptor);
|
superClassAsmType = typeMapper.mapClass(superClassDescriptor);
|
||||||
superCall = (JetDelegatorToSuperCall) specifier;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1117,12 +1116,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (superCall == null) {
|
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor);
|
||||||
genSimpleSuperCall(iv);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNonDefaultObject(descriptor)) {
|
if (isNonDefaultObject(descriptor)) {
|
||||||
StackValue.singleton(descriptor, typeMapper).store(StackValue.LOCAL_0, iv);
|
StackValue.singleton(descriptor, typeMapper).store(StackValue.LOCAL_0, iv);
|
||||||
@@ -1329,15 +1323,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (superCall != null) {
|
ClassDescriptor superClass = DescriptorUtilPackage.getSuperClassNotAny(descriptor);
|
||||||
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCallWithAssert(superCall, bindingContext);
|
if (superClass != null) {
|
||||||
ClassDescriptor superClass = ((ConstructorDescriptor) resolvedCall.getResultingDescriptor()).getContainingDeclaration();
|
|
||||||
if (superClass.isInner()) {
|
if (superClass.isInner()) {
|
||||||
constructorContext.lookupInContext(superClass.getContainingDeclaration(), StackValue.LOCAL_0, state, true);
|
constructorContext.lookupInContext(superClass.getContainingDeclaration(), StackValue.LOCAL_0, state, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAnonymousObject(descriptor)) {
|
if (!isAnonymousObject(descriptor)) {
|
||||||
JetValueArgumentList argumentList = superCall.getValueArgumentList();
|
ResolvedCall<ConstructorDescriptor> delegationCall =
|
||||||
|
getDelegationConstructorCall(bindingContext, descriptor.getUnsubstitutedPrimaryConstructor());
|
||||||
|
JetValueArgumentList argumentList = delegationCall != null ? delegationCall.getCall().getValueArgumentList() : null;
|
||||||
if (argumentList != null) {
|
if (argumentList != null) {
|
||||||
argumentList.accept(visitor);
|
argumentList.accept(visitor);
|
||||||
}
|
}
|
||||||
@@ -1419,9 +1414,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
@NotNull ExpressionCodegen codegen,
|
@NotNull ExpressionCodegen codegen,
|
||||||
@NotNull ConstructorDescriptor constructorDescriptor
|
@NotNull ConstructorDescriptor constructorDescriptor
|
||||||
) {
|
) {
|
||||||
|
ResolvedCall<?> resolvedCall = getDelegationConstructorCall(bindingContext, constructorDescriptor);
|
||||||
|
if (resolvedCall == null) {
|
||||||
|
genSimpleSuperCall(iv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
iv.load(0, OBJECT_TYPE);
|
iv.load(0, OBJECT_TYPE);
|
||||||
|
|
||||||
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCallWithAssert(superCall, bindingContext);
|
|
||||||
ConstructorDescriptor superConstructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
|
ConstructorDescriptor superConstructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
|
||||||
|
|
||||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor);
|
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.BindingContext;
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.InlineDescriptorUtils;
|
import org.jetbrains.kotlin.resolve.InlineDescriptorUtils;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
|
|
||||||
@@ -236,4 +237,12 @@ public class JvmCodegenUtil {
|
|||||||
declaration.getParent() instanceof JetFunctionLiteralExpression &&
|
declaration.getParent() instanceof JetFunctionLiteralExpression &&
|
||||||
InlineDescriptorUtils.isInlineLambda((JetFunctionLiteralExpression) declaration.getParent(), bindingContext, false);
|
InlineDescriptorUtils.isInlineLambda((JetFunctionLiteralExpression) declaration.getParent(), bindingContext, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static ResolvedCall<ConstructorDescriptor> getDelegationConstructorCall(
|
||||||
|
@NotNull BindingContext bindingContext,
|
||||||
|
@NotNull ConstructorDescriptor constructorDescriptor
|
||||||
|
) {
|
||||||
|
return bindingContext.get(BindingContext.CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructorDescriptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,9 +31,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public interface CalculatedClosure {
|
public interface CalculatedClosure {
|
||||||
@Nullable
|
|
||||||
ResolvedCall<ConstructorDescriptor> getSuperCall();
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
ClassDescriptor getCaptureThis();
|
ClassDescriptor getCaptureThis();
|
||||||
|
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ public class CodegenBinding {
|
|||||||
JetElement element = (JetElement) descriptorToDeclaration(classDescriptor);
|
JetElement element = (JetElement) descriptorToDeclaration(classDescriptor);
|
||||||
assert element != null : "No source element for " + classDescriptor;
|
assert element != null : "No source element for " + classDescriptor;
|
||||||
|
|
||||||
MutableClosure closure = new MutableClosure(classDescriptor, findSuperCall(trace.getBindingContext(), element), enclosing);
|
MutableClosure closure = new MutableClosure(classDescriptor, enclosing);
|
||||||
|
|
||||||
if (classDescriptor.isInner()) {
|
if (classDescriptor.isInner()) {
|
||||||
closure.setCaptureThis();
|
closure.setCaptureThis();
|
||||||
@@ -271,31 +271,6 @@ public class CodegenBinding {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private static ResolvedCall<ConstructorDescriptor> findSuperCall(
|
|
||||||
@NotNull BindingContext bindingContext,
|
|
||||||
@NotNull JetElement classOrObject
|
|
||||||
) {
|
|
||||||
if (!(classOrObject instanceof JetClassOrObject)) return null;
|
|
||||||
|
|
||||||
if (classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait()) return null;
|
|
||||||
|
|
||||||
for (JetDelegationSpecifier specifier : ((JetClassOrObject) classOrObject).getDelegationSpecifiers()) {
|
|
||||||
if (!(specifier instanceof JetDelegatorToSuperCall)) continue;
|
|
||||||
|
|
||||||
ResolvedCall<?> resolvedCall = getResolvedCall(specifier, bindingContext);
|
|
||||||
if (resolvedCall == null) continue;
|
|
||||||
|
|
||||||
CallableDescriptor constructor = resolvedCall.getResultingDescriptor();
|
|
||||||
if (constructor instanceof ConstructorDescriptor && !isInterface(constructor.getContainingDeclaration())) {
|
|
||||||
//noinspection unchecked
|
|
||||||
return (ResolvedCall<ConstructorDescriptor>) resolvedCall;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Collection<ClassDescriptor> getAllInnerClasses(
|
public static Collection<ClassDescriptor> getAllInnerClasses(
|
||||||
@NotNull BindingContext bindingContext, @NotNull ClassDescriptor outermostClass
|
@NotNull BindingContext bindingContext, @NotNull ClassDescriptor outermostClass
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ import java.util.*;
|
|||||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.getDirectMember;
|
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.getDirectMember;
|
||||||
|
|
||||||
public final class MutableClosure implements CalculatedClosure {
|
public final class MutableClosure implements CalculatedClosure {
|
||||||
private final ResolvedCall<ConstructorDescriptor> superCall;
|
|
||||||
|
|
||||||
private final ClassDescriptor enclosingClass;
|
private final ClassDescriptor enclosingClass;
|
||||||
private final CallableDescriptor enclosingFunWithReceiverDescriptor;
|
private final CallableDescriptor enclosingFunWithReceiverDescriptor;
|
||||||
|
|
||||||
@@ -41,13 +39,8 @@ public final class MutableClosure implements CalculatedClosure {
|
|||||||
private Map<DeclarationDescriptor, EnclosedValueDescriptor> captureVariables;
|
private Map<DeclarationDescriptor, EnclosedValueDescriptor> captureVariables;
|
||||||
private List<Pair<String, Type>> recordedFields;
|
private List<Pair<String, Type>> recordedFields;
|
||||||
|
|
||||||
MutableClosure(
|
MutableClosure(@NotNull ClassDescriptor classDescriptor, @Nullable ClassDescriptor enclosingClass) {
|
||||||
@NotNull ClassDescriptor classDescriptor,
|
|
||||||
@Nullable ResolvedCall<ConstructorDescriptor> superCall,
|
|
||||||
@Nullable ClassDescriptor enclosingClass
|
|
||||||
) {
|
|
||||||
this.enclosingClass = enclosingClass;
|
this.enclosingClass = enclosingClass;
|
||||||
this.superCall = superCall;
|
|
||||||
this.enclosingFunWithReceiverDescriptor = enclosingExtensionMemberForClass(classDescriptor);
|
this.enclosingFunWithReceiverDescriptor = enclosingExtensionMemberForClass(classDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,11 +61,6 @@ public final class MutableClosure implements CalculatedClosure {
|
|||||||
return enclosingClass;
|
return enclosingClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResolvedCall<ConstructorDescriptor> getSuperCall() {
|
|
||||||
return superCall;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClassDescriptor getCaptureThis() {
|
public ClassDescriptor getCaptureThis() {
|
||||||
return captureThis ? enclosingClass : null;
|
return captureThis ? enclosingClass : null;
|
||||||
|
|||||||
@@ -896,7 +896,7 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ResolvedCall<ConstructorDescriptor> superCall = closure.getSuperCall();
|
ResolvedCall<ConstructorDescriptor> superCall = getDelegationConstructorCall(bindingContext, descriptor);
|
||||||
// We may generate a slightly wrong signature for a local class / anonymous object in light classes mode but we don't care,
|
// We may generate a slightly wrong signature for a local class / anonymous object in light classes mode but we don't care,
|
||||||
// because such classes are not accessible from the outside world
|
// because such classes are not accessible from the outside world
|
||||||
if (superCall != null && classBuilderMode == ClassBuilderMode.FULL) {
|
if (superCall != null && classBuilderMode == ClassBuilderMode.FULL) {
|
||||||
|
|||||||
Reference in New Issue
Block a user