This commit is contained in:
Svetlana Isakova
2012-07-11 17:07:01 +04:00
parent 3933af9964
commit 622e01b87b
8 changed files with 109 additions and 108 deletions
@@ -168,17 +168,17 @@ public class Renderers {
public static TabledDescriptorRenderer renderConflictingSubstitutionsInferenceError(InferenceErrorData inferenceErrorData, public static TabledDescriptorRenderer renderConflictingSubstitutionsInferenceError(InferenceErrorData inferenceErrorData,
TabledDescriptorRenderer result) { TabledDescriptorRenderer result) {
assert inferenceErrorData.constraintsBuilder.hasConflictingParameters(); assert inferenceErrorData.constraintsSystem.hasConflictingParameters();
Collection<CallableDescriptor> substitutedDescriptors = Lists.newArrayList(); Collection<CallableDescriptor> substitutedDescriptors = Lists.newArrayList();
Collection<TypeSubstitutor> substitutors = ConstraintsUtil.getSubstitutorsForConflictingParameters( Collection<TypeSubstitutor> substitutors = ConstraintsUtil.getSubstitutorsForConflictingParameters(
inferenceErrorData.constraintsBuilder); inferenceErrorData.constraintsSystem);
for (TypeSubstitutor substitutor : substitutors) { for (TypeSubstitutor substitutor : substitutors) {
CallableDescriptor substitutedDescriptor = inferenceErrorData.descriptor.substitute(substitutor); CallableDescriptor substitutedDescriptor = inferenceErrorData.descriptor.substitute(substitutor);
substitutedDescriptors.add(substitutedDescriptor); substitutedDescriptors.add(substitutedDescriptor);
} }
TypeParameterDescriptor firstConflictingParameter = ConstraintsUtil.getFirstConflictingParameter(inferenceErrorData.constraintsBuilder); TypeParameterDescriptor firstConflictingParameter = ConstraintsUtil.getFirstConflictingParameter(inferenceErrorData.constraintsSystem);
assert firstConflictingParameter != null; assert firstConflictingParameter != null;
result.text(newText() result.text(newText()
@@ -226,15 +226,15 @@ public class Renderers {
.functionArgumentTypeList( .functionArgumentTypeList(
inferenceErrorData.receiverArgumentType, inferenceErrorData.receiverArgumentType,
inferenceErrorData.valueArgumentsTypes, inferenceErrorData.valueArgumentsTypes,
inferenceErrorData.constraintsBuilder inferenceErrorData.constraintsSystem
.getTypeConstructorMismatchConstraintPositions())); .getTypeConstructorMismatchConstraintPositions()));
} }
public static TabledDescriptorRenderer renderNoInformationForParameterError(InferenceErrorData inferenceErrorData, public static TabledDescriptorRenderer renderNoInformationForParameterError(InferenceErrorData inferenceErrorData,
TabledDescriptorRenderer renderer) { TabledDescriptorRenderer renderer) {
TypeParameterDescriptor firstUnknownParameter = null; TypeParameterDescriptor firstUnknownParameter = null;
for (TypeParameterDescriptor typeParameter : inferenceErrorData.constraintsBuilder.getTypeParameters()) { for (TypeParameterDescriptor typeParameter : inferenceErrorData.constraintsSystem.getTypeVariables()) {
if (inferenceErrorData.constraintsBuilder.getTypeConstraints(typeParameter).isEmpty()) { if (inferenceErrorData.constraintsSystem.getTypeConstraints(typeParameter).isEmpty()) {
firstUnknownParameter = typeParameter; firstUnknownParameter = typeParameter;
break; break;
} }
@@ -253,7 +253,7 @@ public class Renderers {
public static TabledDescriptorRenderer renderUpperBoundViolatedInferenceError(InferenceErrorData inferenceErrorData, TabledDescriptorRenderer result) { public static TabledDescriptorRenderer renderUpperBoundViolatedInferenceError(InferenceErrorData inferenceErrorData, TabledDescriptorRenderer result) {
TypeParameterDescriptor typeParameterDescriptor = null; TypeParameterDescriptor typeParameterDescriptor = null;
for (TypeParameterDescriptor typeParameter : inferenceErrorData.descriptor.getTypeParameters()) { for (TypeParameterDescriptor typeParameter : inferenceErrorData.descriptor.getTypeParameters()) {
if (!ConstraintsUtil.checkUpperBoundIsSatisfied(inferenceErrorData.constraintsBuilder, typeParameter)) { if (!ConstraintsUtil.checkUpperBoundIsSatisfied(inferenceErrorData.constraintsSystem, typeParameter)) {
typeParameterDescriptor = typeParameter; typeParameterDescriptor = typeParameter;
break; break;
} }
@@ -264,9 +264,9 @@ public class Renderers {
.table(newTable(). .table(newTable().
descriptor(inferenceErrorData.descriptor)); descriptor(inferenceErrorData.descriptor));
JetType type = inferenceErrorData.constraintsBuilder.getValue(typeParameterDescriptor); JetType type = inferenceErrorData.constraintsSystem.getValue(typeParameterDescriptor);
JetType upperBound = typeParameterDescriptor.getUpperBoundsAsType(); JetType upperBound = typeParameterDescriptor.getUpperBoundsAsType();
JetType substitute = inferenceErrorData.constraintsBuilder.getSubstitutor().substitute(upperBound, Variance.INVARIANT); JetType substitute = inferenceErrorData.constraintsSystem.getSubstitutor().substitute(upperBound, Variance.INVARIANT);
result.text(newText() result.text(newText()
.normal(" is not satisfied: inferred type ") .normal(" is not satisfied: inferred type ")
@@ -335,10 +335,10 @@ public class CallResolver {
Set<ResolvedCallWithTrace<D>> failed) { Set<ResolvedCallWithTrace<D>> failed) {
assert resolvedCall.hasUnknownTypeParameters(); assert resolvedCall.hasUnknownTypeParameters();
D descriptor = resolvedCall.getCandidateDescriptor(); D descriptor = resolvedCall.getCandidateDescriptor();
ConstraintsBuilder constraintsBuilder = resolvedCall.getConstraintsBuilder(); ConstraintsSystem constraintsSystem = resolvedCall.getConstraintsSystem();
assert constraintsBuilder != null; assert constraintsSystem != null;
constraintsBuilder.addSupertypeConstraint(context.expectedType, descriptor.getReturnType(), ConstraintPosition.EXPECTED_TYPE_POSITION); constraintsSystem.addSupertypeConstraint(context.expectedType, descriptor.getReturnType(), ConstraintPosition.EXPECTED_TYPE_POSITION);
// constraints for function literals // constraints for function literals
// Value parameters // Value parameters
@@ -349,24 +349,24 @@ public class CallResolver {
for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) { for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
if (!JetPsiUtil.isFunctionLiteralWithoutDeclaredParameterTypes(valueArgument.getArgumentExpression())) continue; if (!JetPsiUtil.isFunctionLiteralWithoutDeclaredParameterTypes(valueArgument.getArgumentExpression())) continue;
addConstraintForValueArgument(valueArgument, valueParameterDescriptor, constraintsBuilder.getSubstitutor(), addConstraintForValueArgument(valueArgument, valueParameterDescriptor, constraintsSystem.getSubstitutor(),
constraintsBuilder, context); constraintsSystem, context);
} }
} }
if (!constraintsBuilder.isSuccessful()) { if (!constraintsSystem.isSuccessful()) {
List<JetType> argumentTypes = Lists.newArrayList(); List<JetType> argumentTypes = Lists.newArrayList();
checkValueArgumentTypes(context, resolvedCall, context.trace, argumentTypes); checkValueArgumentTypes(context, resolvedCall, context.trace, argumentTypes);
JetType receiverType = resolvedCall.getReceiverArgument().exists() ? resolvedCall.getReceiverArgument().getType() : null; JetType receiverType = resolvedCall.getReceiverArgument().exists() ? resolvedCall.getReceiverArgument().getType() : null;
reportTypeInferenceFailed(context.trace, context.call, InferenceErrorData.create(descriptor, constraintsBuilder, reportTypeInferenceFailed(context.trace, context.call, InferenceErrorData.create(descriptor, constraintsSystem,
argumentTypes, receiverType)); argumentTypes, receiverType));
resolvedCall.addStatus(ResolutionStatus.TYPE_INFERENCE_ERROR); resolvedCall.addStatus(ResolutionStatus.TYPE_INFERENCE_ERROR);
failed.add(resolvedCall); failed.add(resolvedCall);
return; return;
} }
D substitute = (D) descriptor.substitute(constraintsBuilder.getSubstitutor()); D substitute = (D) descriptor.substitute(constraintsSystem.getSubstitutor());
assert substitute != null; assert substitute != null;
replaceValueParametersWithSubstitutedOnes(resolvedCall, substitute); replaceValueParametersWithSubstitutedOnes(resolvedCall, substitute);
resolvedCall.setResultingDescriptor(substitute); //replacement resolvedCall.setResultingDescriptor(substitute); //replacement
@@ -374,7 +374,7 @@ public class CallResolver {
// Here we type check the arguments with inferred types expected // Here we type check the arguments with inferred types expected
checkValueArgumentTypes(context, resolvedCall, context.trace, null); checkValueArgumentTypes(context, resolvedCall, context.trace, null);
checkBounds(resolvedCall, constraintsBuilder, context); checkBounds(resolvedCall, constraintsSystem, context);
resolvedCall.setHasUnknownTypeParameters(false); resolvedCall.setHasUnknownTypeParameters(false);
if (resolvedCall.getStatus().isSuccess() || resolvedCall.getStatus() == ResolutionStatus.UNKNOWN_STATUS) { if (resolvedCall.getStatus().isSuccess() || resolvedCall.getStatus() == ResolutionStatus.UNKNOWN_STATUS) {
resolvedCall.addStatus(ResolutionStatus.SUCCESS); resolvedCall.addStatus(ResolutionStatus.SUCCESS);
@@ -386,26 +386,26 @@ public class CallResolver {
} }
private void reportTypeInferenceFailed(@NotNull BindingTrace trace, @NotNull Call call, @NotNull InferenceErrorData inferenceErrorData) { private void reportTypeInferenceFailed(@NotNull BindingTrace trace, @NotNull Call call, @NotNull InferenceErrorData inferenceErrorData) {
assert !inferenceErrorData.constraintsBuilder.isSuccessful(); assert !inferenceErrorData.constraintsSystem.isSuccessful();
JetExpression calleeExpression = call.getCalleeExpression(); JetExpression calleeExpression = call.getCalleeExpression();
PsiElement element = calleeExpression != null ? calleeExpression : call.getCallElement(); PsiElement element = calleeExpression != null ? calleeExpression : call.getCallElement();
if (inferenceErrorData.constraintsBuilder.hasTypeConstructorMismatch()) { if (inferenceErrorData.constraintsSystem.hasTypeConstructorMismatch()) {
trace.report(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH.on(element, inferenceErrorData)); trace.report(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH.on(element, inferenceErrorData));
} }
else if (inferenceErrorData.constraintsBuilder.hasConflictingParameters()) { else if (inferenceErrorData.constraintsSystem.hasConflictingParameters()) {
trace.report(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS.on(element, inferenceErrorData)); trace.report(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS.on(element, inferenceErrorData));
} }
else { else {
assert inferenceErrorData.constraintsBuilder.hasUnknownParameters(); assert inferenceErrorData.constraintsSystem.hasUnknownParameters();
trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(element, inferenceErrorData)); trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(element, inferenceErrorData));
} }
} }
private <D extends CallableDescriptor> void checkBounds(ResolvedCallImpl<D> call, ConstraintsBuilder constraintsBuilder, BasicResolutionContext context) { private <D extends CallableDescriptor> void checkBounds(ResolvedCallImpl<D> call, ConstraintsSystem constraintsSystem, BasicResolutionContext context) {
for (TypeParameterDescriptor typeParameter : call.getCandidateDescriptor().getTypeParameters()) { for (TypeParameterDescriptor typeParameter : call.getCandidateDescriptor().getTypeParameters()) {
if (!ConstraintsUtil.checkUpperBoundIsSatisfied(constraintsBuilder, typeParameter)) { if (!ConstraintsUtil.checkUpperBoundIsSatisfied(constraintsSystem, typeParameter)) {
context.trace.report(Errors.TYPE_INFERENCE_UPPER_BOUND_VIOLATED.on(context.call.getCallElement(), InferenceErrorData context.trace.report(Errors.TYPE_INFERENCE_UPPER_BOUND_VIOLATED.on(context.call.getCallElement(), InferenceErrorData
.create(call.getCandidateDescriptor(), constraintsBuilder))); .create(call.getCandidateDescriptor(), constraintsSystem)));
} }
} }
} }
@@ -700,7 +700,7 @@ public class CallResolver {
ResolutionDebugInfo.Data debugInfo = context.trace.get(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement()); ResolutionDebugInfo.Data debugInfo = context.trace.get(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement());
ConstraintsBuilder constraintsBuilder = new ConstraintsBuilderImpl(); ConstraintsSystem constraintsSystem = new ConstraintsSystemImpl();
// If the call is recursive, e.g. // If the call is recursive, e.g.
// fun foo<T>(t : T) : T = foo(t) // fun foo<T>(t : T) : T = foo(t)
@@ -712,11 +712,11 @@ public class CallResolver {
for (TypeParameterDescriptor typeParameterDescriptor : candidateWithFreshVariables.getTypeParameters()) { for (TypeParameterDescriptor typeParameterDescriptor : candidateWithFreshVariables.getTypeParameters()) {
constraintsBuilder.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences constraintsSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences
} }
TypeSubstitutor substituteDontCare = ConstraintSystemWithPriorities TypeSubstitutor substituteDontCare = ConstraintSystemWithPriorities
.makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), ConstraintsBuilderImpl.DONT_CARE); .makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), ConstraintsSystemImpl.DONT_CARE);
// Value parameters // Value parameters
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) { for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
@@ -731,7 +731,8 @@ public class CallResolver {
// Here we type check expecting an error type (DONT_CARE, substitution with substituteDontCare) // Here we type check expecting an error type (DONT_CARE, substitution with substituteDontCare)
// and throw the results away // and throw the results away
// We'll type check the arguments later, with the inferred types expected // We'll type check the arguments later, with the inferred types expected
boolean success = addConstraintForValueArgument(valueArgument, valueParameterDescriptor, substituteDontCare, constraintsBuilder, context); boolean success = addConstraintForValueArgument(valueArgument, valueParameterDescriptor, substituteDontCare,
constraintsSystem, context);
if (!success) { if (!success) {
candidateCall.argumentHasNoType(); candidateCall.argumentHasNoType();
} }
@@ -743,21 +744,21 @@ public class CallResolver {
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument(); ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
ReceiverDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter(); ReceiverDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter();
if (receiverArgument.exists() && receiverParameter.exists()) { if (receiverArgument.exists() && receiverParameter.exists()) {
constraintsBuilder.addSubtypingConstraint(receiverArgument.getType(), receiverParameter.getType(), ConstraintPosition.RECEIVER_POSITION); constraintsSystem.addSubtypingConstraint(receiverArgument.getType(), receiverParameter.getType(), ConstraintPosition.RECEIVER_POSITION);
} }
ConstraintsBuilderImpl constraintsBuilderWithRightTypeParameters = new ConstraintsBuilderImpl(constraintsBuilder.hasTypeConstructorMismatch(), constraintsBuilder ConstraintsSystemImpl constraintsBuilderWithRightTypeParameters = new ConstraintsSystemImpl(constraintsSystem.hasTypeConstructorMismatch(), constraintsSystem
.getTypeConstructorMismatchConstraintPositions()); .getTypeConstructorMismatchConstraintPositions());
for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) { for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) {
TypeConstraints typeConstraints = constraintsBuilder.getTypeConstraints( TypeConstraints typeConstraints = constraintsSystem.getTypeConstraints(
candidateWithFreshVariables.getTypeParameters().get(typeParameterDescriptor.getIndex())); candidateWithFreshVariables.getTypeParameters().get(typeParameterDescriptor.getIndex()));
constraintsBuilderWithRightTypeParameters.registerTypeVariable(typeParameterDescriptor, typeConstraints); constraintsBuilderWithRightTypeParameters.registerTypeVariable(typeParameterDescriptor, typeConstraints);
} }
candidateCall.setConstraintsBuilder(constraintsBuilderWithRightTypeParameters); candidateCall.setConstraintsSystem(constraintsBuilderWithRightTypeParameters);
// Solution // Solution
if (!constraintsBuilder.hasContradiction()) { if (!constraintsSystem.hasContradiction()) {
candidateCall.setHasUnknownTypeParameters(true); candidateCall.setHasUnknownTypeParameters(true);
return SUCCESS; return SUCCESS;
} }
@@ -774,7 +775,7 @@ public class CallResolver {
private boolean addConstraintForValueArgument(ValueArgument valueArgument, private boolean addConstraintForValueArgument(ValueArgument valueArgument,
@NotNull ValueParameterDescriptor valueParameterDescriptor, @NotNull ValueParameterDescriptor valueParameterDescriptor,
@NotNull TypeSubstitutor substitutor, @NotNull TypeSubstitutor substitutor,
@NotNull ConstraintsBuilder constraintsBuilder, @NotNull ConstraintsSystem constraintsSystem,
@NotNull ResolutionContext context) { @NotNull ResolutionContext context) {
JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument); JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
@@ -784,7 +785,7 @@ public class CallResolver {
context.scope, argumentExpression, substitutor.substitute(valueParameterDescriptor.getType(), Variance.INVARIANT), context.scope, argumentExpression, substitutor.substitute(valueParameterDescriptor.getType(), Variance.INVARIANT),
context.dataFlowInfo, traceForUnknown) : null; context.dataFlowInfo, traceForUnknown) : null;
if (type == null || ErrorUtils.isErrorType(type)) return false; if (type == null || ErrorUtils.isErrorType(type)) return false;
constraintsBuilder.addSubtypingConstraint(type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition( constraintsSystem.addSubtypingConstraint(type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(
valueParameterDescriptor.getIndex())); valueParameterDescriptor.getIndex()));
return true; return true;
} }
@@ -972,7 +973,7 @@ public class CallResolver {
if (argument.getSpreadElement() != null) { if (argument.getSpreadElement() != null) {
if (parameterDescriptor.getVarargElementType() == null) { if (parameterDescriptor.getVarargElementType() == null) {
// Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper // Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
return ConstraintsBuilderImpl.DONT_CARE; return ConstraintsSystemImpl.DONT_CARE;
} }
else { else {
return parameterDescriptor.getType(); return parameterDescriptor.getType();
@@ -24,9 +24,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsBuilder; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsSystem;
import org.jetbrains.jet.lang.resolve.calls.inference.TypeConstraints;
import org.jetbrains.jet.lang.resolve.calls.inference.TypeConstraintsImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
@@ -74,7 +72,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
private TemporaryBindingTrace trace; private TemporaryBindingTrace trace;
private ResolutionStatus status = UNKNOWN_STATUS; private ResolutionStatus status = UNKNOWN_STATUS;
private boolean hasUnknownTypeParameters = false; private boolean hasUnknownTypeParameters = false;
private ConstraintsBuilder constraintsBuilder = null; private ConstraintsSystem constraintsSystem = null;
private ResolvedCallImpl(@NotNull ResolutionCandidate<D> candidate, @NotNull TemporaryBindingTrace trace) { private ResolvedCallImpl(@NotNull ResolutionCandidate<D> candidate, @NotNull TemporaryBindingTrace trace) {
this.candidateDescriptor = candidate.getDescriptor(); this.candidateDescriptor = candidate.getDescriptor();
@@ -132,13 +130,13 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
typeArguments.put(typeParameter, typeArgument); typeArguments.put(typeParameter, typeArgument);
} }
public void setConstraintsBuilder(@NotNull ConstraintsBuilder constraintsBuilder) { public void setConstraintsSystem(@NotNull ConstraintsSystem constraintsSystem) {
this.constraintsBuilder = constraintsBuilder; this.constraintsSystem = constraintsSystem;
} }
@Nullable @Nullable
public ConstraintsBuilder getConstraintsBuilder() { public ConstraintsSystem getConstraintsSystem() {
return constraintsBuilder; return constraintsSystem;
} }
public void recordValueArgument(@NotNull ValueParameterDescriptor valueParameter, @NotNull ResolvedValueArgument valueArgument) { public void recordValueArgument(@NotNull ValueParameterDescriptor valueParameter, @NotNull ResolvedValueArgument valueArgument) {
@@ -30,15 +30,17 @@ import java.util.Set;
/** /**
* @author svtk * @author svtk
*/ */
public interface ConstraintsBuilder { public interface ConstraintsSystem {
void registerTypeVariable(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull Variance positionVariance); void registerTypeVariable(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull Variance positionVariance);
@NotNull @NotNull
Set<TypeParameterDescriptor> getTypeParameters(); Set<TypeParameterDescriptor> getTypeVariables();
// only subject type might contain type variables
void addSubtypingConstraint(@NotNull JetType subjectType, @NotNull JetType constrainingType, @NotNull ConstraintPosition constraintPosition); void addSubtypingConstraint(@NotNull JetType subjectType, @NotNull JetType constrainingType, @NotNull ConstraintPosition constraintPosition);
// only subject type might contain type variables
void addSupertypeConstraint(@NotNull JetType subjectType, @NotNull JetType constrainingType, @NotNull ConstraintPosition constraintPosition); void addSupertypeConstraint(@NotNull JetType subjectType, @NotNull JetType constrainingType, @NotNull ConstraintPosition constraintPosition);
boolean isSuccessful(); boolean isSuccessful();
@@ -33,22 +33,22 @@ import java.util.*;
/** /**
* @author svtk * @author svtk
*/ */
public class ConstraintsBuilderImpl implements ConstraintsBuilder { public class ConstraintsSystemImpl implements ConstraintsSystem {
public static final JetType DONT_CARE = ErrorUtils.createErrorTypeWithCustomDebugName("DONT_CARE"); public static final JetType DONT_CARE = ErrorUtils.createErrorTypeWithCustomDebugName("DONT_CARE");
enum ConstraintType { enum ConstraintKind {
SUB_TYPE, SUPER_TYPE, EQUAL SUB_TYPE, SUPER_TYPE, EQUAL
} }
public static ConstraintType varianceToConstraintType(Variance variance) { public static ConstraintKind varianceToConstraintKind(Variance variance) {
if (variance == Variance.INVARIANT) { if (variance == Variance.INVARIANT) {
return ConstraintType.EQUAL; return ConstraintKind.EQUAL;
} }
if (variance == Variance.OUT_VARIANCE) { if (variance == Variance.OUT_VARIANCE) {
return ConstraintType.SUB_TYPE; return ConstraintKind.SUB_TYPE;
} }
return ConstraintType.SUPER_TYPE; return ConstraintKind.SUPER_TYPE;
} }
private final Map<TypeParameterDescriptor, TypeConstraintsImpl> typeParameterConstraints = Maps.newLinkedHashMap(); private final Map<TypeParameterDescriptor, TypeConstraintsImpl> typeParameterConstraints = Maps.newLinkedHashMap();
@@ -56,11 +56,11 @@ public class ConstraintsBuilderImpl implements ConstraintsBuilder {
private final Collection<ConstraintPosition> errorConstraintPositions; private final Collection<ConstraintPosition> errorConstraintPositions;
private boolean typeConstructorMismatch; private boolean typeConstructorMismatch;
public ConstraintsBuilderImpl() { public ConstraintsSystemImpl() {
this(false, Lists.<ConstraintPosition>newArrayList()); this(false, Lists.<ConstraintPosition>newArrayList());
} }
public ConstraintsBuilderImpl(boolean typeConstructorMismatch, Collection<ConstraintPosition> errorConstraintPositions) { public ConstraintsSystemImpl(boolean typeConstructorMismatch, Collection<ConstraintPosition> errorConstraintPositions) {
this.typeConstructorMismatch = typeConstructorMismatch; this.typeConstructorMismatch = typeConstructorMismatch;
this.errorConstraintPositions = errorConstraintPositions; this.errorConstraintPositions = errorConstraintPositions;
this.typeSubstitutor = TypeSubstitutor.create(new TypeSubstitution() { this.typeSubstitutor = TypeSubstitutor.create(new TypeSubstitution() {
@@ -115,70 +115,70 @@ public class ConstraintsBuilderImpl implements ConstraintsBuilder {
@Override @Override
public void addSubtypingConstraint(@NotNull JetType subjectType, @NotNull JetType constrainingType, @NotNull ConstraintPosition constraintPosition) { public void addSubtypingConstraint(@NotNull JetType subjectType, @NotNull JetType constrainingType, @NotNull ConstraintPosition constraintPosition) {
addConstraint(ConstraintType.SUB_TYPE, subjectType, constrainingType, constraintPosition); addConstraint(ConstraintKind.SUB_TYPE, subjectType, constrainingType, constraintPosition);
} }
@Override @Override
public void addSupertypeConstraint(@NotNull JetType subjectType, @NotNull JetType constrainingType, @NotNull ConstraintPosition constraintPosition) { public void addSupertypeConstraint(@NotNull JetType subjectType, @NotNull JetType constrainingType, @NotNull ConstraintPosition constraintPosition) {
addConstraint(ConstraintType.SUPER_TYPE, subjectType, constrainingType, constraintPosition); addConstraint(ConstraintKind.SUPER_TYPE, subjectType, constrainingType, constraintPosition);
} }
public void addConstraint(@NotNull ConstraintType constraintType, @NotNull JetType exactType, @NotNull JetType expectedType, public void addConstraint(@NotNull ConstraintKind constraintKind, @NotNull JetType subjectType, @NotNull JetType constrainingType,
@NotNull ConstraintPosition constraintPosition) { @NotNull ConstraintPosition constraintPosition) {
if (exactType == DONT_CARE || expectedType == DONT_CARE || exactType == TypeUtils.NO_EXPECTED_TYPE if (subjectType == DONT_CARE || constrainingType == DONT_CARE || subjectType == TypeUtils.NO_EXPECTED_TYPE
|| expectedType == TypeUtils.NO_EXPECTED_TYPE) { || constrainingType == TypeUtils.NO_EXPECTED_TYPE) {
return; return;
} }
DeclarationDescriptor expectedTypeDescriptor = expectedType.getConstructor().getDeclarationDescriptor(); DeclarationDescriptor constrainingTypeDescriptor = constrainingType.getConstructor().getDeclarationDescriptor();
DeclarationDescriptor exactTypeDescriptor = exactType.getConstructor().getDeclarationDescriptor(); DeclarationDescriptor subjectTypeDescriptor = subjectType.getConstructor().getDeclarationDescriptor();
if (expectedTypeDescriptor instanceof TypeParameterDescriptor) { if (constrainingTypeDescriptor instanceof TypeParameterDescriptor) {
if (TypeUtils.dependsOnTypeParameterConstructors(exactType, Collections.singleton(DONT_CARE.getConstructor()))) return; if (TypeUtils.dependsOnTypeParameterConstructors(subjectType, Collections.singleton(DONT_CARE.getConstructor()))) return;
if (expectedType.isNullable()) { if (constrainingType.isNullable()) {
exactType = TypeUtils.makeNotNullable(exactType); subjectType = TypeUtils.makeNotNullable(subjectType);
} }
TypeParameterDescriptor typeParameter = (TypeParameterDescriptor) expectedTypeDescriptor; TypeParameterDescriptor typeParameter = (TypeParameterDescriptor) constrainingTypeDescriptor;
if (constraintType == ConstraintType.SUB_TYPE) { if (constraintKind == ConstraintKind.SUB_TYPE) {
typeParameterConstraints.get(typeParameter).addLowerConstraint(exactType); typeParameterConstraints.get(typeParameter).addLowerConstraint(subjectType);
} }
else if (constraintType == ConstraintType.SUPER_TYPE) { else if (constraintKind == ConstraintKind.SUPER_TYPE) {
typeParameterConstraints.get(typeParameter).addUpperConstraint(exactType); typeParameterConstraints.get(typeParameter).addUpperConstraint(subjectType);
} }
else { else {
typeParameterConstraints.get(typeParameter).addEqualConstraint(exactType); typeParameterConstraints.get(typeParameter).addEqualConstraint(subjectType);
} }
return; return;
} }
if (exactTypeDescriptor instanceof ClassDescriptor && expectedTypeDescriptor instanceof ClassDescriptor) { if (subjectTypeDescriptor instanceof ClassDescriptor && constrainingTypeDescriptor instanceof ClassDescriptor) {
if (constraintType != ConstraintType.SUPER_TYPE) { if (constraintKind != ConstraintKind.SUPER_TYPE) {
JetType correspondingSupertype = TypeCheckingProcedure.findCorrespondingSupertype(exactType, expectedType); JetType correspondingSupertype = TypeCheckingProcedure.findCorrespondingSupertype(subjectType, constrainingType);
if (correspondingSupertype != null) { if (correspondingSupertype != null) {
exactType = correspondingSupertype; subjectType = correspondingSupertype;
} }
} }
else { else {
JetType correspondingSupertype = TypeCheckingProcedure.findCorrespondingSupertype(expectedType, exactType); JetType correspondingSupertype = TypeCheckingProcedure.findCorrespondingSupertype(constrainingType, subjectType);
if (correspondingSupertype != null) { if (correspondingSupertype != null) {
expectedType = correspondingSupertype; constrainingType = correspondingSupertype;
} }
} }
if (exactType.getConstructor().getParameters().size() != expectedType.getConstructor().getParameters().size()) { if (subjectType.getConstructor().getParameters().size() != constrainingType.getConstructor().getParameters().size()) {
errorConstraintPositions.add(constraintPosition); errorConstraintPositions.add(constraintPosition);
typeConstructorMismatch = true; typeConstructorMismatch = true;
return; return;
} }
ClassDescriptor subClass = (ClassDescriptor) exactType.getConstructor().getDeclarationDescriptor(); ClassDescriptor subClass = (ClassDescriptor) subjectType.getConstructor().getDeclarationDescriptor();
ClassDescriptor superClass = (ClassDescriptor) expectedType.getConstructor().getDeclarationDescriptor(); ClassDescriptor superClass = (ClassDescriptor) constrainingType.getConstructor().getDeclarationDescriptor();
if (DescriptorUtils.isSubclass(subClass, superClass)) { if (DescriptorUtils.isSubclass(subClass, superClass)) {
List<TypeProjection> subArguments = exactType.getArguments(); List<TypeProjection> subArguments = subjectType.getArguments();
List<TypeProjection> superArguments = expectedType.getArguments(); List<TypeProjection> superArguments = constrainingType.getArguments();
List<TypeParameterDescriptor> superParameters = expectedType.getConstructor().getParameters(); List<TypeParameterDescriptor> superParameters = constrainingType.getConstructor().getParameters();
for (int i = 0; i < superArguments.size(); i++) { for (int i = 0; i < superArguments.size(); i++) {
addConstraint(varianceToConstraintType(superParameters.get(i).getVariance()), subArguments.get(i).getType(), superArguments.get(i).getType(), addConstraint(varianceToConstraintKind(superParameters.get(i).getVariance()), subArguments.get(i).getType(), superArguments.get(i).getType(),
constraintPosition); constraintPosition);
} }
return; return;
@@ -209,7 +209,7 @@ public class ConstraintsBuilderImpl implements ConstraintsBuilder {
@NotNull @NotNull
@Override @Override
public Set<TypeParameterDescriptor> getTypeParameters() { public Set<TypeParameterDescriptor> getTypeVariables() {
return typeParameterConstraints.keySet(); return typeParameterConstraints.keySet();
} }
@@ -35,9 +35,9 @@ import java.util.Map;
public class ConstraintsUtil { public class ConstraintsUtil {
@Nullable @Nullable
public static TypeParameterDescriptor getFirstConflictingParameter(@NotNull ConstraintsBuilder constraintsBuilder) { public static TypeParameterDescriptor getFirstConflictingParameter(@NotNull ConstraintsSystem constraintsSystem) {
for (TypeParameterDescriptor typeParameter : constraintsBuilder.getTypeParameters()) { for (TypeParameterDescriptor typeParameter : constraintsSystem.getTypeVariables()) {
TypeConstraints constraints = constraintsBuilder.getTypeConstraints(typeParameter); TypeConstraints constraints = constraintsSystem.getTypeConstraints(typeParameter);
if (!constraints.getConflicts().isEmpty()) { if (!constraints.getConflicts().isEmpty()) {
return typeParameter; return typeParameter;
} }
@@ -46,11 +46,11 @@ public class ConstraintsUtil {
} }
@NotNull @NotNull
public static Collection<TypeSubstitutor> getSubstitutorsForConflictingParameters(@NotNull ConstraintsBuilder constraintsBuilder) { public static Collection<TypeSubstitutor> getSubstitutorsForConflictingParameters(@NotNull ConstraintsSystem constraintsSystem) {
TypeParameterDescriptor firstConflictingParameter = getFirstConflictingParameter(constraintsBuilder); TypeParameterDescriptor firstConflictingParameter = getFirstConflictingParameter(constraintsSystem);
if (firstConflictingParameter == null) return Collections.emptyList(); if (firstConflictingParameter == null) return Collections.emptyList();
Collection<JetType> conflictingTypes = constraintsBuilder.getTypeConstraints(firstConflictingParameter).getConflicts(); Collection<JetType> conflictingTypes = constraintsSystem.getTypeConstraints(firstConflictingParameter).getConflicts();
ArrayList<Map<TypeConstructor, TypeProjection>> substitutionContexts = Lists.newArrayList(); ArrayList<Map<TypeConstructor, TypeProjection>> substitutionContexts = Lists.newArrayList();
for (JetType type : conflictingTypes) { for (JetType type : conflictingTypes) {
@@ -59,10 +59,10 @@ public class ConstraintsUtil {
substitutionContexts.add(context); substitutionContexts.add(context);
} }
for (TypeParameterDescriptor typeParameter : constraintsBuilder.getTypeParameters()) { for (TypeParameterDescriptor typeParameter : constraintsSystem.getTypeVariables()) {
if (typeParameter == firstConflictingParameter) continue; if (typeParameter == firstConflictingParameter) continue;
JetType safeType = getSafeValue(constraintsBuilder, typeParameter); JetType safeType = getSafeValue(constraintsSystem, typeParameter);
for (Map<TypeConstructor, TypeProjection> context : substitutionContexts) { for (Map<TypeConstructor, TypeProjection> context : substitutionContexts) {
TypeProjection typeProjection = new TypeProjection(safeType); TypeProjection typeProjection = new TypeProjection(safeType);
context.put(typeParameter.getTypeConstructor(), typeProjection); context.put(typeParameter.getTypeConstructor(), typeProjection);
@@ -76,8 +76,8 @@ public class ConstraintsUtil {
} }
@NotNull @NotNull
public static JetType getSafeValue(@NotNull ConstraintsBuilder constraintsBuilder, @NotNull TypeParameterDescriptor typeParameter) { public static JetType getSafeValue(@NotNull ConstraintsSystem constraintsSystem, @NotNull TypeParameterDescriptor typeParameter) {
JetType type = constraintsBuilder.getValue(typeParameter); JetType type = constraintsSystem.getValue(typeParameter);
if (type != null) { if (type != null) {
return type; return type;
} }
@@ -85,12 +85,12 @@ public class ConstraintsUtil {
return typeParameter.getUpperBoundsAsType(); return typeParameter.getUpperBoundsAsType();
} }
public static boolean checkUpperBoundIsSatisfied(@NotNull ConstraintsBuilder constraintsBuilder, public static boolean checkUpperBoundIsSatisfied(@NotNull ConstraintsSystem constraintsSystem,
@NotNull TypeParameterDescriptor typeParameter) { @NotNull TypeParameterDescriptor typeParameter) {
assert constraintsBuilder.getTypeConstraints(typeParameter) != null; assert constraintsSystem.getTypeConstraints(typeParameter) != null;
JetType type = constraintsBuilder.getValue(typeParameter); JetType type = constraintsSystem.getValue(typeParameter);
JetType upperBound = typeParameter.getUpperBoundsAsType(); JetType upperBound = typeParameter.getUpperBoundsAsType();
JetType substitute = constraintsBuilder.getSubstitutor().substitute(upperBound, Variance.INVARIANT); JetType substitute = constraintsSystem.getSubstitutor().substitute(upperBound, Variance.INVARIANT);
if (type != null) { if (type != null) {
if (substitute == null || !JetTypeChecker.INSTANCE.isSubtypeOf(type, substitute)) { if (substitute == null || !JetTypeChecker.INSTANCE.isSubtypeOf(type, substitute)) {
@@ -28,24 +28,24 @@ import java.util.List;
*/ */
public class InferenceErrorData { public class InferenceErrorData {
public final CallableDescriptor descriptor; public final CallableDescriptor descriptor;
public final ConstraintsBuilder constraintsBuilder; public final ConstraintsSystem constraintsSystem;
public final JetType receiverArgumentType; public final JetType receiverArgumentType;
public final List<JetType> valueArgumentsTypes; public final List<JetType> valueArgumentsTypes;
private InferenceErrorData(@NotNull CallableDescriptor descriptor, @NotNull ConstraintsBuilder constraintsBuilder, private InferenceErrorData(@NotNull CallableDescriptor descriptor, @NotNull ConstraintsSystem constraintsSystem,
@Nullable List<JetType> valueArgumentsTypes, @Nullable JetType receiverArgumentType) { @Nullable List<JetType> valueArgumentsTypes, @Nullable JetType receiverArgumentType) {
this.descriptor = descriptor; this.descriptor = descriptor;
this.constraintsBuilder = constraintsBuilder; this.constraintsSystem = constraintsSystem;
this.receiverArgumentType = receiverArgumentType; this.receiverArgumentType = receiverArgumentType;
this.valueArgumentsTypes = valueArgumentsTypes; this.valueArgumentsTypes = valueArgumentsTypes;
} }
public static InferenceErrorData create(@NotNull CallableDescriptor descriptor, @NotNull ConstraintsBuilder constraintsBuilder, public static InferenceErrorData create(@NotNull CallableDescriptor descriptor, @NotNull ConstraintsSystem constraintsSystem,
@NotNull List<JetType> valueArgumentsTypes, @Nullable JetType receiverArgumentType) { @NotNull List<JetType> valueArgumentsTypes, @Nullable JetType receiverArgumentType) {
return new InferenceErrorData(descriptor, constraintsBuilder, valueArgumentsTypes, receiverArgumentType); return new InferenceErrorData(descriptor, constraintsSystem, valueArgumentsTypes, receiverArgumentType);
} }
public static InferenceErrorData create(@NotNull CallableDescriptor descriptor, @NotNull ConstraintsBuilder constraintsBuilder) { public static InferenceErrorData create(@NotNull CallableDescriptor descriptor, @NotNull ConstraintsSystem constraintsSystem) {
return new InferenceErrorData(descriptor, constraintsBuilder, null, null); return new InferenceErrorData(descriptor, constraintsSystem, null, null);
} }
} }
@@ -232,7 +232,7 @@ public class ExpressionTypingUtils {
@NotNull JetType receiverType, @NotNull JetType receiverType,
@NotNull CallableDescriptor receiverArgument @NotNull CallableDescriptor receiverArgument
) { ) {
ConstraintsBuilderImpl constraintsBuilder = new ConstraintsBuilderImpl(); ConstraintsSystemImpl constraintsBuilder = new ConstraintsSystemImpl();
for (TypeParameterDescriptor typeParameterDescriptor : receiverArgument.getTypeParameters()) { for (TypeParameterDescriptor typeParameterDescriptor : receiverArgument.getTypeParameters()) {
constraintsBuilder.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); constraintsBuilder.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT);
} }