Change logic of constructor delegation call resolution
- If class has type arguments (A<T1,..>) then resolve it's delegation call to `this` as for expression A<T1, ..>() like type arguments are explicitly specified. - Same logic works for `super` delegation calls. - It could be just enough to substitute all candidates before resolve but diagnostic messages looks more correct when substitution is performed within CandidateResolver.performResolutionForCandidateCall because it works the same way as when resolving A<T1, ..>(). #KT-6992 Fixed #KT-6993 Fixed #KT-6994 Fixed
This commit is contained in:
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.types.JetType;
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
|
||||
|
||||
@@ -296,12 +297,10 @@ public class CallResolver {
|
||||
// when super call should be conventional enum constructor and super call should be empty
|
||||
if (call == null) return null;
|
||||
|
||||
JetType superClassType = DescriptorUtils.getSuperClassType(constructorDescriptor.getContainingDeclaration());
|
||||
|
||||
BasicCallResolutionContext context = BasicCallResolutionContext.create(
|
||||
trace, scope,
|
||||
CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call),
|
||||
superClassType != null ? superClassType : NO_EXPECTED_TYPE,
|
||||
NO_EXPECTED_TYPE,
|
||||
dataFlowInfo, ContextDependency.INDEPENDENT, CheckValueArgumentsMode.ENABLED,
|
||||
expressionTypingServices.getCallChecker(), expressionTypingServices.getAdditionalTypeChecker(), false);
|
||||
|
||||
@@ -353,11 +352,16 @@ public class CallResolver {
|
||||
((ClassDescriptor) delegateClassDescriptor.getContainingDeclaration()).
|
||||
getThisAsReceiverParameter().getValue();
|
||||
|
||||
JetType expectedType = isThisCall ?
|
||||
calleeConstructor.getContainingDeclaration().getDefaultType() :
|
||||
DescriptorUtils.getSuperClassType(currentClassDescriptor);
|
||||
|
||||
TypeSubstitutor knownTypeParametersSubstitutor = TypeSubstitutor.create(expectedType);
|
||||
for (CallableDescriptor descriptor : constructors) {
|
||||
candidates.add(ResolutionCandidate.create(
|
||||
context.call, descriptor, constructorDispatchReceiver, ReceiverValue.NO_RECEIVER,
|
||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
|
||||
));
|
||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER,
|
||||
knownTypeParametersSubstitutor));
|
||||
}
|
||||
|
||||
return computeTasksFromCandidatesAndResolvedCall(context, calleeExpression, candidates, CallTransformer.FUNCTION_CALL_TRANSFORMER);
|
||||
|
||||
@@ -114,8 +114,8 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
|
||||
candidate.getDescriptor(),
|
||||
candidate.getDispatchReceiver(),
|
||||
candidate.getExtensionReceiver(),
|
||||
candidate.getExplicitReceiverKind()
|
||||
);
|
||||
candidate.getExplicitReceiverKind(),
|
||||
null);
|
||||
if (!hasReceiver) {
|
||||
CallCandidateResolutionContext<CallableDescriptor> context = CallCandidateResolutionContext.create(
|
||||
ResolvedCallImpl.create(variableCandidate, candidateTrace, task.tracing, task.dataFlowInfoForArguments),
|
||||
@@ -131,7 +131,7 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
|
||||
candidate.getDescriptor(),
|
||||
candidate.getDispatchReceiver(),
|
||||
ReceiverValue.NO_RECEIVER,
|
||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER);
|
||||
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, null);
|
||||
|
||||
CallCandidateResolutionContext<CallableDescriptor> contextWithoutReceiver = createContextWithChainedTrace(
|
||||
candidateWithoutReceiver, variableCallWithoutReceiver, candidateTrace, task, variableCall.getExplicitReceiver());
|
||||
|
||||
@@ -153,8 +153,13 @@ public class CandidateResolver {
|
||||
|
||||
candidateCall.setResultingSubstitutor(substitutor);
|
||||
}
|
||||
else if (candidateCall.getKnownTypeParametersSubstitutor() != null) {
|
||||
candidateCall.setResultingSubstitutor(candidateCall.getKnownTypeParametersSubstitutor());
|
||||
}
|
||||
|
||||
if (jetTypeArguments.isEmpty() && !candidate.getTypeParameters().isEmpty()) {
|
||||
if (jetTypeArguments.isEmpty() &&
|
||||
!candidate.getTypeParameters().isEmpty() &&
|
||||
candidateCall.getKnownTypeParametersSubstitutor() == null) {
|
||||
candidateCall.addStatus(inferTypeArguments(context));
|
||||
}
|
||||
else {
|
||||
|
||||
+3
@@ -56,6 +56,9 @@ public interface MutableResolvedCall<D extends CallableDescriptor> extends Resol
|
||||
|
||||
void setResultingSubstitutor(@NotNull TypeSubstitutor substitutor);
|
||||
|
||||
@Nullable
|
||||
TypeSubstitutor getKnownTypeParametersSubstitutor();
|
||||
|
||||
//todo remove: use value to parameter map status
|
||||
boolean hasInferredReturnType();
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
private final ReceiverValue dispatchReceiver; // receiver object of a method
|
||||
private final ReceiverValue extensionReceiver; // receiver of an extension function
|
||||
private final ExplicitReceiverKind explicitReceiverKind;
|
||||
private final TypeSubstitutor knownTypeParametersSubstitutor;
|
||||
|
||||
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
|
||||
private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments = Maps.newLinkedHashMap();
|
||||
@@ -101,6 +102,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
this.dispatchReceiver = candidate.getDispatchReceiver();
|
||||
this.extensionReceiver = candidate.getExtensionReceiver();
|
||||
this.explicitReceiverKind = candidate.getExplicitReceiverKind();
|
||||
this.knownTypeParametersSubstitutor = candidate.getKnownTypeParametersResultingSubstitutor();
|
||||
this.trace = trace;
|
||||
this.tracing = tracing;
|
||||
this.dataFlowInfoForArguments = dataFlowInfoForArguments;
|
||||
@@ -323,4 +325,10 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
private void assertNotCompleted(String elementName) {
|
||||
assert !completed: elementName + " is erased after resolution completion.";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public TypeSubstitutor getKnownTypeParametersSubstitutor() {
|
||||
return knownTypeParametersSubstitutor;
|
||||
}
|
||||
}
|
||||
|
||||
+16
-8
@@ -16,46 +16,49 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tasks;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.kotlin.psi.Call;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
|
||||
|
||||
public class ResolutionCandidate<D extends CallableDescriptor> {
|
||||
private final Call call;
|
||||
private final D candidateDescriptor;
|
||||
private final TypeSubstitutor knownTypeParametersResultingSubstitutor;
|
||||
private ReceiverValue dispatchReceiver; // receiver object of a method
|
||||
private ReceiverValue extensionReceiver; // receiver of an extension function
|
||||
private ExplicitReceiverKind explicitReceiverKind;
|
||||
|
||||
private ResolutionCandidate(
|
||||
@NotNull Call call, @NotNull D descriptor, @NotNull ReceiverValue dispatchReceiver,
|
||||
@NotNull ReceiverValue extensionReceiver, @NotNull ExplicitReceiverKind explicitReceiverKind
|
||||
@NotNull ReceiverValue extensionReceiver, @NotNull ExplicitReceiverKind explicitReceiverKind,
|
||||
@Nullable TypeSubstitutor knownTypeParametersResultingSubstitutor
|
||||
) {
|
||||
this.call = call;
|
||||
this.candidateDescriptor = descriptor;
|
||||
this.dispatchReceiver = dispatchReceiver;
|
||||
this.extensionReceiver = extensionReceiver;
|
||||
this.explicitReceiverKind = explicitReceiverKind;
|
||||
this.knownTypeParametersResultingSubstitutor = knownTypeParametersResultingSubstitutor;
|
||||
}
|
||||
|
||||
public static <D extends CallableDescriptor> ResolutionCandidate<D> create(
|
||||
@NotNull Call call, @NotNull D descriptor
|
||||
) {
|
||||
return new ResolutionCandidate<D>(call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER);
|
||||
return new ResolutionCandidate<D>(call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, null);
|
||||
}
|
||||
|
||||
public static <D extends CallableDescriptor> ResolutionCandidate<D> create(
|
||||
@NotNull Call call, @NotNull D descriptor, @NotNull ReceiverValue dispatchReceiver,
|
||||
@NotNull ReceiverValue receiverArgument, @NotNull ExplicitReceiverKind explicitReceiverKind
|
||||
@NotNull ReceiverValue receiverArgument, @NotNull ExplicitReceiverKind explicitReceiverKind,
|
||||
@Nullable TypeSubstitutor knownTypeParametersResultingSubstitutor
|
||||
) {
|
||||
return new ResolutionCandidate<D>(call, descriptor, dispatchReceiver, receiverArgument, explicitReceiverKind);
|
||||
return new ResolutionCandidate<D>(call, descriptor, dispatchReceiver, receiverArgument, explicitReceiverKind,
|
||||
knownTypeParametersResultingSubstitutor);
|
||||
}
|
||||
|
||||
public void setDispatchReceiver(@NotNull ReceiverValue dispatchReceiver) {
|
||||
@@ -95,6 +98,11 @@ public class ResolutionCandidate<D extends CallableDescriptor> {
|
||||
return explicitReceiverKind;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TypeSubstitutor getKnownTypeParametersResultingSubstitutor() {
|
||||
return knownTypeParametersResultingSubstitutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return candidateDescriptor.toString();
|
||||
|
||||
+1
-1
@@ -424,7 +424,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
Call call = CallMaker.makeCall(expression, NO_RECEIVER, null, expression, Collections.<ValueArgument>emptyList());
|
||||
ResolutionCandidate<ReceiverParameterDescriptor> resolutionCandidate =
|
||||
ResolutionCandidate.create(
|
||||
call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER);
|
||||
call, descriptor, NO_RECEIVER, NO_RECEIVER, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, null);
|
||||
|
||||
ResolvedCallImpl<ReceiverParameterDescriptor> resolvedCall =
|
||||
ResolvedCallImpl.create(resolutionCandidate,
|
||||
|
||||
Reference in New Issue
Block a user