added assert for last type inference error type

restructured 'isSuccessful' method of constraint system:
!hasTypeConstructorMismatch && !hasUnknownParameters && !hasConflictingParameters
to correspond with type inference errors
This commit is contained in:
Svetlana Isakova
2012-07-10 15:10:18 +04:00
parent 33c25ea01f
commit 0394da053d
3 changed files with 64 additions and 30 deletions
@@ -399,15 +399,17 @@ 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.constraintSystem.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.constraintSystem.hasError()) { if (inferenceErrorData.constraintSystem.hasTypeConstructorMismatch()) {
trace.report(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH.on(element, inferenceErrorData)); trace.report(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH.on(element, inferenceErrorData));
} }
else if (inferenceErrorData.constraintSystem.hasContradiction()) { else if (inferenceErrorData.constraintSystem.hasConflictingParameters()) {
trace.report(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS.on(element, inferenceErrorData)); trace.report(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS.on(element, inferenceErrorData));
} }
else { else {
assert inferenceErrorData.constraintSystem.hasUnknownParameters();
trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(element, inferenceErrorData)); trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(element, inferenceErrorData));
} }
} }
@@ -415,7 +417,8 @@ public class CallResolver {
private <D extends CallableDescriptor> void checkBounds(ResolvedCallImpl<D> call, ConstraintSystem constraintSystem, BasicResolutionContext context) { private <D extends CallableDescriptor> void checkBounds(ResolvedCallImpl<D> call, ConstraintSystem constraintSystem, BasicResolutionContext context) {
for (TypeParameterDescriptor typeParameter : call.getCandidateDescriptor().getTypeParameters()) { for (TypeParameterDescriptor typeParameter : call.getCandidateDescriptor().getTypeParameters()) {
if (!constraintSystem.checkUpperBound(typeParameter)) { if (!constraintSystem.checkUpperBound(typeParameter)) {
context.trace.report(Errors.TYPE_INFERENCE_UPPER_BOUND_VIOLATED.on(context.call.getCallElement(), InferenceErrorData.create(call.getCandidateDescriptor(), constraintSystem))); context.trace.report(Errors.TYPE_INFERENCE_UPPER_BOUND_VIOLATED.on(context.call.getCallElement(), InferenceErrorData
.create(call.getCandidateDescriptor(), constraintSystem)));
} }
} }
} }
@@ -765,7 +768,7 @@ public class CallResolver {
constraintSystem.addSubtypingConstraint(receiverArgument.getType(), receiverParameter.getType(), ConstraintPosition.RECEIVER_POSITION); constraintSystem.addSubtypingConstraint(receiverArgument.getType(), receiverParameter.getType(), ConstraintPosition.RECEIVER_POSITION);
} }
ConstraintSystemImpl constraintSystemWithRightTypeParameters = new ConstraintSystemImpl(constraintSystem.hasError(), constraintSystem.getErrorConstraintPositions()); ConstraintSystemImpl constraintSystemWithRightTypeParameters = new ConstraintSystemImpl(constraintSystem.hasTypeConstructorMismatch(), constraintSystem.getErrorConstraintPositions());
for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) { for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) {
TypeBounds typeBounds = constraintSystem.getTypeBounds( TypeBounds typeBounds = constraintSystem.getTypeBounds(
candidateWithFreshVariables.getTypeParameters().get(typeParameterDescriptor.getIndex())); candidateWithFreshVariables.getTypeParameters().get(typeParameterDescriptor.getIndex()));
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.resolve.calls.inference; package org.jetbrains.jet.lang.resolve.calls.inference;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
@@ -25,7 +26,6 @@ import org.jetbrains.jet.lang.types.Variance;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Queue;
/** /**
* @author svtk * @author svtk
@@ -46,25 +46,34 @@ public interface ConstraintSystem {
void addConstraint(@NotNull ConstraintType constraintType, @NotNull JetType exactType, @NotNull JetType expectedType, @NotNull ConstraintPosition constraintPosition); void addConstraint(@NotNull ConstraintType constraintType, @NotNull JetType exactType, @NotNull JetType expectedType, @NotNull ConstraintPosition constraintPosition);
TypeBounds getTypeBounds(TypeParameterDescriptor typeParameterDescriptor);
Map<TypeParameterDescriptor, TypeBounds> getTypeBoundsMap();
boolean isSuccessful(); boolean isSuccessful();
boolean hasContradiction(); boolean hasContradiction();
boolean hasConflictingParameters();
boolean hasUnknownParameters();
boolean hasTypeConstructorMismatch();
TypeBounds getTypeBounds(TypeParameterDescriptor typeParameterDescriptor);
Map<TypeParameterDescriptor, TypeBounds> getTypeBoundsMap();
@Nullable
TypeParameterDescriptor getFirstConflictingParameter(); TypeParameterDescriptor getFirstConflictingParameter();
@NotNull
TypeSubstitutor getSubstitutor(); TypeSubstitutor getSubstitutor();
@NotNull
Collection<TypeSubstitutor> getSubstitutors(); Collection<TypeSubstitutor> getSubstitutors();
@Nullable
JetType getValue(TypeParameterDescriptor typeParameterDescriptor); JetType getValue(TypeParameterDescriptor typeParameterDescriptor);
boolean hasError(); @NotNull
Collection<ConstraintPosition> getErrorConstraintPositions();
Queue<ConstraintPosition> getErrorConstraintPositions();
boolean checkUpperBound(@NotNull TypeParameterDescriptor typeParameterDescriptor); boolean checkUpperBound(@NotNull TypeParameterDescriptor typeParameterDescriptor);
} }
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
@@ -49,15 +48,15 @@ public class ConstraintSystemImpl implements ConstraintSystem {
private final Map<TypeParameterDescriptor, TypeBounds> typeParameterBounds = Maps.newLinkedHashMap(); private final Map<TypeParameterDescriptor, TypeBounds> typeParameterBounds = Maps.newLinkedHashMap();
private final TypeSubstitutor typeSubstitutor; private final TypeSubstitutor typeSubstitutor;
private final Queue<ConstraintPosition> errorConstraintPositions; private final Collection<ConstraintPosition> errorConstraintPositions;
private boolean error; private boolean typeConstructorMismatch;
public ConstraintSystemImpl() { public ConstraintSystemImpl() {
this(false, Lists.<ConstraintPosition>newLinkedList()); this(false, Lists.<ConstraintPosition>newArrayList());
} }
public ConstraintSystemImpl(boolean error, Queue<ConstraintPosition> errorConstraintPositions) { public ConstraintSystemImpl(boolean typeConstructorMismatch, Collection<ConstraintPosition> errorConstraintPositions) {
this.error = error; this.typeConstructorMismatch = typeConstructorMismatch;
this.errorConstraintPositions = errorConstraintPositions; this.errorConstraintPositions = errorConstraintPositions;
this.typeSubstitutor = TypeSubstitutor.create(new TypeSubstitution() { this.typeSubstitutor = TypeSubstitutor.create(new TypeSubstitution() {
@Override @Override
@@ -88,12 +87,13 @@ public class ConstraintSystemImpl implements ConstraintSystem {
} }
@Override @Override
public boolean hasError() { public boolean hasTypeConstructorMismatch() {
return error; return typeConstructorMismatch;
} }
@NotNull
@Override @Override
public Queue<ConstraintPosition> getErrorConstraintPositions() { public Collection<ConstraintPosition> getErrorConstraintPositions() {
return errorConstraintPositions; return errorConstraintPositions;
} }
@@ -164,7 +164,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
if (exactType.getConstructor().getParameters().size() != expectedType.getConstructor().getParameters().size()) { if (exactType.getConstructor().getParameters().size() != expectedType.getConstructor().getParameters().size()) {
errorConstraintPositions.add(constraintPosition); errorConstraintPositions.add(constraintPosition);
error = true; typeConstructorMismatch = true;
return; return;
} }
@@ -181,15 +181,12 @@ public class ConstraintSystemImpl implements ConstraintSystem {
return; return;
} }
} }
error = true; typeConstructorMismatch = true;
errorConstraintPositions.add(constraintPosition); errorConstraintPositions.add(constraintPosition);
} }
private boolean checkConstraints(TypeParameterDescriptor typeParameterDescriptor) { private boolean checkConstraints(TypeParameterDescriptor typeParameterDescriptor) {
//todo refactor //todo refactor
if (error) {
return false;
}
TypeBounds typeBounds = typeParameterBounds.get(typeParameterDescriptor); TypeBounds typeBounds = typeParameterBounds.get(typeParameterDescriptor);
if (typeBounds == null || typeBounds.isEmpty()) return true; if (typeBounds == null || typeBounds.isEmpty()) return true;
JetType exactType = null; JetType exactType = null;
@@ -268,14 +265,30 @@ public class ConstraintSystemImpl implements ConstraintSystem {
values.addAll(typeBounds.getExactValues()); values.addAll(typeBounds.getExactValues());
if (!typeBounds.getLowerBounds().isEmpty()) { if (!typeBounds.getLowerBounds().isEmpty()) {
JetType superTypeOfLowerBounds = CommonSupertypes.commonSupertype(typeBounds.getLowerBounds()); JetType superTypeOfLowerBounds = CommonSupertypes.commonSupertype(typeBounds.getLowerBounds());
if (values.isEmpty()) {
values.add(superTypeOfLowerBounds);
}
for (JetType value : values) { for (JetType value : values) {
if (!JetTypeChecker.INSTANCE.isSubtypeOf(superTypeOfLowerBounds, value)) { if (!JetTypeChecker.INSTANCE.isSubtypeOf(superTypeOfLowerBounds, value)) {
values.add(superTypeOfLowerBounds); values.add(superTypeOfLowerBounds);
break;
}
}
}
if (!typeBounds.getUpperBounds().isEmpty()) {
//todo subTypeOfUpperBounds
JetType subTypeOfUpperBounds = typeBounds.getUpperBounds().iterator().next(); //todo
if (values.isEmpty()) {
values.add(subTypeOfUpperBounds);
}
for (JetType value : values) {
if (!JetTypeChecker.INSTANCE.isSubtypeOf(value, subTypeOfUpperBounds)) {
values.add(subTypeOfUpperBounds);
break;
} }
} }
} }
} }
//todo subTypeOfLowerBounds
return values; return values;
} }
@@ -291,6 +304,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
return null; return null;
} }
@NotNull
@Override @Override
public Collection<TypeSubstitutor> getSubstitutors() { public Collection<TypeSubstitutor> getSubstitutors() {
TypeParameterDescriptor firstConflictingParameter = getFirstConflictingParameter(); TypeParameterDescriptor firstConflictingParameter = getFirstConflictingParameter();
@@ -334,18 +348,25 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@Override @Override
public boolean isSuccessful() { public boolean isSuccessful() {
return !error && !hasUnknownParameters() && !hasContradiction(); return !hasTypeConstructorMismatch() && !hasUnknownParameters() && !hasConflictingParameters();
} }
@Override @Override
public boolean hasContradiction() { public boolean hasContradiction() {
return hasTypeConstructorMismatch() || hasConflictingParameters();
}
@Override
public boolean hasConflictingParameters() {
for (TypeParameterDescriptor typeParameter : typeParameterBounds.keySet()) { for (TypeParameterDescriptor typeParameter : typeParameterBounds.keySet()) {
if (!checkConstraints(typeParameter)) return true; if (getValues(typeParameter).size() > 1) return true;
//if (!checkConstraints(typeParameter)) return true;
} }
return false; return false;
} }
private boolean hasUnknownParameters() { @Override
public boolean hasUnknownParameters() {
for (TypeBounds bounds : typeParameterBounds.values()) { for (TypeBounds bounds : typeParameterBounds.values()) {
if (bounds.isEmpty()) { if (bounds.isEmpty()) {
return true; return true;
@@ -354,6 +375,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
return false; return false;
} }
@NotNull
@Override @Override
public TypeSubstitutor getSubstitutor() { public TypeSubstitutor getSubstitutor() {
return typeSubstitutor; return typeSubstitutor;