added declared bound constraints directly to constraint system

added status 'hasViolatedUpperBound'
class TypeConstraintsImpl now stores constraint position for each constraint,
so we can filter out bound constraints and find out if the system is successful without them
This commit is contained in:
Svetlana Isakova
2013-09-26 14:05:49 +04:00
parent ac33ccc0fe
commit 731efd0781
16 changed files with 387 additions and 205 deletions
@@ -354,7 +354,7 @@ public interface Errors {
DiagnosticFactory1<PsiElement, ExtendedInferenceErrorData> TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, ExtendedInferenceErrorData> TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, ExtendedInferenceErrorData> TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, InferenceErrorData> TYPE_INFERENCE_UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, ExtendedInferenceErrorData> TYPE_INFERENCE_UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR);
DiagnosticFactory2<JetExpression, JetType, JetType> TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR);
// Callable references
@@ -28,10 +28,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsUtil;
import org.jetbrains.jet.lang.resolve.calls.inference.InferenceErrorData;
import org.jetbrains.jet.lang.resolve.calls.inference.TypeConstraints;
import org.jetbrains.jet.lang.resolve.calls.inference.*;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
@@ -159,11 +156,11 @@ public class Renderers {
}
};
public static final Renderer<InferenceErrorData> TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER =
new Renderer<InferenceErrorData>() {
public static final Renderer<ExtendedInferenceErrorData> TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER =
new Renderer<ExtendedInferenceErrorData>() {
@NotNull
@Override
public String render(@NotNull InferenceErrorData inferenceErrorData) {
public String render(@NotNull ExtendedInferenceErrorData inferenceErrorData) {
return renderUpperBoundViolatedInferenceError(inferenceErrorData, TabledDescriptorRenderer.create()).toString();
}
};
@@ -265,32 +262,47 @@ public class Renderers {
.text("Please specify it explicitly."));
}
public static TabledDescriptorRenderer renderUpperBoundViolatedInferenceError(InferenceErrorData inferenceErrorData, TabledDescriptorRenderer result) {
@NotNull
public static TabledDescriptorRenderer renderUpperBoundViolatedInferenceError(ExtendedInferenceErrorData inferenceErrorData, TabledDescriptorRenderer result) {
String errorMessage = "Rendering 'upper bound violated' error for " + inferenceErrorData.descriptor;
TypeParameterDescriptor typeParameterDescriptor = null;
ConstraintSystemImpl constraintSystem = (ConstraintSystemImpl) inferenceErrorData.constraintSystem;
assert constraintSystem.getStatus().hasViolatedUpperBound();
ConstraintSystem systemWithoutWeakConstraints = constraintSystem.getSystemWithoutWeakConstraints();
for (TypeParameterDescriptor typeParameter : inferenceErrorData.descriptor.getTypeParameters()) {
if (!ConstraintsUtil.checkUpperBoundIsSatisfied(inferenceErrorData.constraintSystem, typeParameter, true)) {
if (!ConstraintsUtil.checkUpperBoundIsSatisfied(systemWithoutWeakConstraints, typeParameter, true)) {
typeParameterDescriptor = typeParameter;
break;
}
}
assert typeParameterDescriptor != null;
assert typeParameterDescriptor != null : errorMessage;
JetType inferredValueForTypeParameter = systemWithoutWeakConstraints.getTypeConstraints(typeParameterDescriptor).getValue();
assert inferredValueForTypeParameter != null : errorMessage;
result.text(newText().normal("Type parameter bound for ").strong(typeParameterDescriptor.getName()).normal(" in "))
.table(newTable().
descriptor(inferenceErrorData.descriptor));
JetType inferredValueForTypeParameter = inferenceErrorData.constraintSystem.getTypeConstraints(typeParameterDescriptor).getValue();
assert inferredValueForTypeParameter != null;
JetType upperBound = typeParameterDescriptor.getUpperBoundsAsType();
JetType upperBoundWithSubstitutedInferredTypes = inferenceErrorData.constraintSystem.getResultingSubstitutor().substitute(upperBound, Variance.INVARIANT);
assert upperBoundWithSubstitutedInferredTypes != null;
JetType violatedUpperBound = null;
for (JetType upperBound : typeParameterDescriptor.getUpperBounds()) {
JetType upperBoundWithSubstitutedInferredTypes =
systemWithoutWeakConstraints.getResultingSubstitutor().substitute(upperBound, Variance.INVARIANT);
if (upperBoundWithSubstitutedInferredTypes != null &&
!JetTypeChecker.INSTANCE.isSubtypeOf(inferredValueForTypeParameter, upperBoundWithSubstitutedInferredTypes)) {
violatedUpperBound = upperBoundWithSubstitutedInferredTypes;
break;
}
}
assert violatedUpperBound != null : errorMessage;
Renderer<JetType> typeRenderer = result.getTypeRenderer();
result.text(newText()
.normal(" is not satisfied: inferred type ")
.error(typeRenderer.render(inferredValueForTypeParameter))
.normal(" is not a subtype of ")
.strong(typeRenderer.render(upperBoundWithSubstitutedInferredTypes)));
.strong(typeRenderer.render(violatedUpperBound)));
return result;
}
@@ -232,19 +232,13 @@ public class CandidateResolver {
updateSystemWithConstraintSystemCompleter(context, resolvedCall);
if (resolvedCall.getConstraintSystem().getStatus().hasContradiction()) {
return reportInferenceError(context);
}
updateSystemIfExpectedTypeIsUnit(context, resolvedCall);
boolean boundsAreSatisfied = updateSystemCheckingBounds(resolvedCall);
((ConstraintSystemImpl)resolvedCall.getConstraintSystem()).processDeclaredBoundConstraints();
if (!resolvedCall.getConstraintSystem().getStatus().isSuccessful()) {
return reportInferenceError(context);
}
if (!boundsAreSatisfied) {
context.tracing.upperBoundViolated(context.trace, InferenceErrorData.create(
resolvedCall.getCandidateDescriptor(), resolvedCall.getConstraintSystem()));
}
resolvedCall.setResultingSubstitutor(resolvedCall.getConstraintSystem().getResultingSubstitutor());
completeNestedCallsInference(context);
@@ -307,30 +301,12 @@ public class CandidateResolver {
}
}
private static <D extends CallableDescriptor> boolean updateSystemCheckingBounds(
@NotNull ResolvedCallImpl<D> resolvedCall
) {
ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
assert constraintSystem != null;
if (ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/true)
&& !constraintSystem.getStatus().hasUnknownParameters()) {
return true;
}
ConstraintSystemImpl copy = (ConstraintSystemImpl) constraintSystem.copy();
copy.processDeclaredBoundConstraints();
if (copy.getStatus().isSuccessful() && ConstraintsUtil.checkBoundsAreSatisfied(copy, /*substituteOtherTypeParametersInBounds=*/true)) {
resolvedCall.setConstraintSystem(copy);
return true;
}
return false;
}
private <D extends CallableDescriptor> JetType reportInferenceError(
@NotNull CallCandidateResolutionContext<D> context
) {
ResolvedCallImpl<D> resolvedCall = context.candidateCall;
ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem();
assert constraintSystem != null;
resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor());
completeNestedCallsInference(context);
@@ -471,7 +447,8 @@ public class CandidateResolver {
if (expression == null) return;
DataFlowInfo dataFlowInfoForValueArgument = context.candidateCall.getDataFlowInfoForArguments().getInfo(argument);
ResolutionContext<?> newContext = context.replaceExpectedType(context.expectedType).replaceDataFlowInfo(dataFlowInfoForValueArgument);
ResolutionContext<?> newContext = context.replaceExpectedType(context.expectedType).replaceDataFlowInfo(
dataFlowInfoForValueArgument);
DataFlowUtils.checkType(type, expression, newContext);
}
@@ -617,9 +594,8 @@ public class CandidateResolver {
// Solution
boolean hasContradiction = constraintSystem.getStatus().hasContradiction();
boolean boundsAreSatisfied = ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/false);
candidateCall.setHasUnknownTypeParameters(true);
if (!hasContradiction && boundsAreSatisfied) {
if (!hasContradiction) {
return INCOMPLETE_TYPE_INFERENCE;
}
ValueArgumentsCheckingResult checkingResult = checkAllValueArguments(context, SKIP_FUNCTION_ARGUMENTS);
@@ -23,7 +23,6 @@ import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.inference.InferenceErrorData;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.JetType;
@@ -95,9 +94,6 @@ public interface TracingStrategy {
@Override
public void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull ExtendedInferenceErrorData inferenceErrorData) {}
@Override
public void upperBoundViolated(@NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData) {}
};
<D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallWithTrace<D> resolvedCall);
@@ -140,6 +136,4 @@ public interface TracingStrategy {
void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptorWithVisibility descriptor);
void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull ExtendedInferenceErrorData inferenceErrorData);
void upperBoundViolated(@NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData);
}
@@ -21,7 +21,6 @@ import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
@@ -233,6 +232,9 @@ public class TracingStrategyImpl implements TracingStrategy {
assert !noExpectedType(data.expectedType) : "Expected type doesn't exist, but there is an expected type mismatch error";
trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(reference, data.expectedType, substitutedReturnType));
}
else if (status.hasViolatedUpperBound()) {
trace.report(TYPE_INFERENCE_UPPER_BOUND_VIOLATED.on(reference, data));
}
else if (status.hasTypeConstructorMismatch()) {
trace.report(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH.on(reference, data));
}
@@ -244,9 +246,4 @@ public class TracingStrategyImpl implements TracingStrategy {
trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(reference, data));
}
}
@Override
public void upperBoundViolated(@NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData) {
trace.report(Errors.TYPE_INFERENCE_UPPER_BOUND_VIOLATED.on(reference, inferenceErrorData));
}
}
@@ -477,12 +477,5 @@ public class ControlStructureTypingUtils {
) {
throwError();
}
@Override
public void upperBoundViolated(
@NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData
) {
throwError();
}
}
}