added special method to replace type variables in constraint system
This commit is contained in:
@@ -388,6 +388,7 @@ 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.constraintsSystem.isSuccessful();
|
assert !inferenceErrorData.constraintsSystem.isSuccessful();
|
||||||
|
if (inferenceErrorData.constraintsSystem.hasErrorInConstrainingTypes()) return;
|
||||||
JetExpression calleeExpression = call.getCalleeExpression();
|
JetExpression calleeExpression = call.getCalleeExpression();
|
||||||
PsiElement element = calleeExpression != null ? calleeExpression : call.getCallElement();
|
PsiElement element = calleeExpression != null ? calleeExpression : call.getCallElement();
|
||||||
if (inferenceErrorData.constraintsSystem.hasTypeConstructorMismatch()) {
|
if (inferenceErrorData.constraintsSystem.hasTypeConstructorMismatch()) {
|
||||||
@@ -701,7 +702,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());
|
||||||
|
|
||||||
ConstraintsSystem constraintsSystem = new ConstraintsSystemImpl();
|
ConstraintsSystemImpl 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)
|
||||||
@@ -749,13 +750,12 @@ public class CallResolver {
|
|||||||
ConstraintPosition.RECEIVER_POSITION);
|
ConstraintPosition.RECEIVER_POSITION);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstraintsSystemImpl constraintsBuilderWithRightTypeParameters = new ConstraintsSystemImpl(constraintsSystem.hasTypeConstructorMismatch(), constraintsSystem
|
Map<TypeParameterDescriptor, TypeParameterDescriptor> typeVariablesMap = Maps.newLinkedHashMap();
|
||||||
.getTypeConstructorMismatchConstraintPositions());
|
|
||||||
for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) {
|
for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) {
|
||||||
TypeConstraints typeConstraints = constraintsSystem.getTypeConstraints(
|
typeVariablesMap.put(candidateWithFreshVariables.getTypeParameters().get(typeParameterDescriptor.getIndex()),
|
||||||
candidateWithFreshVariables.getTypeParameters().get(typeParameterDescriptor.getIndex()));
|
typeParameterDescriptor);
|
||||||
constraintsBuilderWithRightTypeParameters.registerTypeVariable(typeParameterDescriptor, typeConstraints);
|
|
||||||
}
|
}
|
||||||
|
ConstraintsSystem constraintsBuilderWithRightTypeParameters = constraintsSystem.replaceTypeVariables(typeVariablesMap);
|
||||||
candidateCall.setConstraintsSystem(constraintsBuilderWithRightTypeParameters);
|
candidateCall.setConstraintsSystem(constraintsBuilderWithRightTypeParameters);
|
||||||
|
|
||||||
|
|
||||||
@@ -786,9 +786,10 @@ public class CallResolver {
|
|||||||
JetType type = argumentExpression != null ? expressionTypingServices.getType(
|
JetType type = argumentExpression != null ? expressionTypingServices.getType(
|
||||||
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;
|
|
||||||
constraintsSystem.addSupertypeConstraint(effectiveExpectedType, type, ConstraintPosition.getValueParameterPosition(
|
constraintsSystem.addSupertypeConstraint(effectiveExpectedType, type, ConstraintPosition.getValueParameterPosition(
|
||||||
valueParameterDescriptor.getIndex()));
|
valueParameterDescriptor.getIndex()));
|
||||||
|
//todo no return
|
||||||
|
if (type == null || ErrorUtils.isErrorType(type)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+79
-49
@@ -36,32 +36,12 @@ 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 ConstraintKind {
|
|
||||||
SUB_TYPE, SUPER_TYPE, EQUAL
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ConstraintKind varianceToConstraintKind(Variance variance) {
|
|
||||||
if (variance == Variance.INVARIANT) {
|
|
||||||
return ConstraintKind.EQUAL;
|
|
||||||
}
|
|
||||||
if (variance == Variance.OUT_VARIANCE) {
|
|
||||||
return ConstraintKind.SUPER_TYPE;
|
|
||||||
}
|
|
||||||
return ConstraintKind.SUB_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Map<TypeParameterDescriptor, TypeConstraintsImpl> typeParameterConstraints = Maps.newLinkedHashMap();
|
private final Map<TypeParameterDescriptor, TypeConstraintsImpl> typeParameterConstraints = Maps.newLinkedHashMap();
|
||||||
|
private final Set<ConstraintPosition> errorConstraintPositions = Sets.newHashSet();
|
||||||
private final TypeSubstitutor resultingSubstitutor;
|
private final TypeSubstitutor resultingSubstitutor;
|
||||||
private final Set<ConstraintPosition> errorConstraintPositions;
|
private boolean hasErrorInConstrainingTypes;
|
||||||
private boolean typeConstructorMismatch;
|
|
||||||
|
|
||||||
public ConstraintsSystemImpl() {
|
public ConstraintsSystemImpl() {
|
||||||
this(false, Sets.<ConstraintPosition>newHashSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConstraintsSystemImpl(boolean typeConstructorMismatch, Set<ConstraintPosition> errorConstraintPositions) {
|
|
||||||
this.typeConstructorMismatch = typeConstructorMismatch;
|
|
||||||
this.errorConstraintPositions = errorConstraintPositions;
|
|
||||||
this.resultingSubstitutor = TypeSubstitutor.create(new TypeSubstitution() {
|
this.resultingSubstitutor = TypeSubstitutor.create(new TypeSubstitution() {
|
||||||
@Override
|
@Override
|
||||||
public TypeProjection get(TypeConstructor key) {
|
public TypeProjection get(TypeConstructor key) {
|
||||||
@@ -93,13 +73,17 @@ public class ConstraintsSystemImpl implements ConstraintsSystem {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTypeConstructorMismatch() {
|
public boolean hasTypeConstructorMismatch() {
|
||||||
return typeConstructorMismatch;
|
return !errorConstraintPositions.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ConstraintPosition> getTypeConstructorMismatchConstraintPositions() {
|
public boolean hasTypeConstructorMismatchAt(@NotNull ConstraintPosition constraintPosition) {
|
||||||
return errorConstraintPositions;
|
return errorConstraintPositions.contains(constraintPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasErrorInConstrainingTypes() {
|
||||||
|
return hasErrorInConstrainingTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -107,28 +91,47 @@ public class ConstraintsSystemImpl implements ConstraintsSystem {
|
|||||||
typeParameterConstraints.put(typeParameterDescriptor, new TypeConstraintsImpl(positionVariance));
|
typeParameterConstraints.put(typeParameterDescriptor, new TypeConstraintsImpl(positionVariance));
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo remove
|
@NotNull
|
||||||
public void registerTypeVariable(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull TypeConstraints typeConstraints) {
|
public ConstraintsSystemImpl replaceTypeVariables(@NotNull Map<TypeParameterDescriptor, TypeParameterDescriptor> typeVariablesMap) {
|
||||||
typeParameterConstraints.put(typeParameterDescriptor, (TypeConstraintsImpl) typeConstraints);
|
ConstraintsSystemImpl newConstraintSystem = new ConstraintsSystemImpl();
|
||||||
|
for (Map.Entry<TypeParameterDescriptor, TypeConstraintsImpl> entry : typeParameterConstraints.entrySet()) {
|
||||||
|
TypeParameterDescriptor typeParameter = entry.getKey();
|
||||||
|
TypeConstraintsImpl typeConstraints = entry.getValue();
|
||||||
|
|
||||||
|
TypeParameterDescriptor newTypeParameter = typeVariablesMap.get(typeParameter);
|
||||||
|
assert newTypeParameter != null;
|
||||||
|
newConstraintSystem.typeParameterConstraints.put(newTypeParameter, typeConstraints);
|
||||||
|
}
|
||||||
|
for (ConstraintPosition constraintPosition : errorConstraintPositions) {
|
||||||
|
newConstraintSystem.errorConstraintPositions.add(constraintPosition);
|
||||||
|
}
|
||||||
|
newConstraintSystem.hasErrorInConstrainingTypes = hasErrorInConstrainingTypes;
|
||||||
|
return newConstraintSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addSubtypingConstraint(@NotNull JetType subjectType, @NotNull JetType constrainingType, @NotNull ConstraintPosition constraintPosition) {
|
public void addSubtypingConstraint(@NotNull JetType subjectType, @Nullable JetType constrainingType, @NotNull ConstraintPosition constraintPosition) {
|
||||||
addConstraint(ConstraintKind.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, @Nullable JetType constrainingType, @NotNull ConstraintPosition constraintPosition) {
|
||||||
addConstraint(ConstraintKind.SUPER_TYPE, subjectType, constrainingType, constraintPosition);
|
addConstraint(ConstraintKind.SUPER_TYPE, subjectType, constrainingType, constraintPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addConstraint(@NotNull ConstraintKind constraintKind,
|
private void addConstraint(@NotNull ConstraintKind constraintKind,
|
||||||
@NotNull JetType subjectType,
|
@NotNull JetType subjectType,
|
||||||
@NotNull JetType constrainingType,
|
@Nullable JetType constrainingType,
|
||||||
@NotNull ConstraintPosition constraintPosition) {
|
@NotNull ConstraintPosition constraintPosition) {
|
||||||
|
|
||||||
if (constrainingType == DONT_CARE || subjectType == DONT_CARE || constrainingType == TypeUtils.NO_EXPECTED_TYPE
|
if (constrainingType == null || (ErrorUtils.isErrorType(constrainingType) && constrainingType != DONT_CARE)) {
|
||||||
|| subjectType == TypeUtils.NO_EXPECTED_TYPE) {
|
hasErrorInConstrainingTypes = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert subjectType != TypeUtils.NO_EXPECTED_TYPE : "Subject type shouldn't be NO_EXPECTED_TYPE (in position " + constraintPosition + " )";
|
||||||
|
|
||||||
|
if (constrainingType == DONT_CARE || ErrorUtils.isErrorType(subjectType) || constrainingType == TypeUtils.NO_EXPECTED_TYPE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,30 +147,34 @@ public class ConstraintsSystemImpl implements ConstraintsSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (constrainingTypeDescriptor instanceof TypeParameterDescriptor) {
|
if (constrainingTypeDescriptor instanceof TypeParameterDescriptor) {
|
||||||
// assert that constraining type doesn't contain type variables
|
assert typeParameterConstraints.get(constrainingTypeDescriptor) == null : "Constraining type contains type variable " + "";//todo
|
||||||
assert typeParameterConstraints.get(constrainingTypeDescriptor) == null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (constrainingTypeDescriptor instanceof ClassDescriptor && subjectTypeDescriptor instanceof ClassDescriptor) {
|
if (constrainingTypeDescriptor instanceof ClassDescriptor && subjectTypeDescriptor instanceof ClassDescriptor) {
|
||||||
if (constraintKind != ConstraintKind.SUB_TYPE) {
|
switch (constraintKind) {
|
||||||
JetType correspondingSupertype = TypeCheckingProcedure.findCorrespondingSupertype(constrainingType, subjectType);
|
case SUPER_TYPE:
|
||||||
if (correspondingSupertype != null) {
|
{
|
||||||
constrainingType = correspondingSupertype;
|
JetType correspondingSupertype = TypeCheckingProcedure.findCorrespondingSupertype(constrainingType, subjectType);
|
||||||
|
if (correspondingSupertype != null) {
|
||||||
|
constrainingType = correspondingSupertype;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
case SUB_TYPE:
|
||||||
else {
|
{
|
||||||
JetType correspondingSupertype = TypeCheckingProcedure.findCorrespondingSupertype(subjectType, constrainingType);
|
JetType correspondingSupertype = TypeCheckingProcedure.findCorrespondingSupertype(subjectType, constrainingType);
|
||||||
if (correspondingSupertype != null) {
|
if (correspondingSupertype != null) {
|
||||||
subjectType = correspondingSupertype;
|
subjectType = correspondingSupertype;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
case EQUAL: //nothing
|
||||||
}
|
}
|
||||||
|
//todo type constructors are same, else error
|
||||||
|
|
||||||
if (constrainingType.getConstructor().getParameters().size() != subjectType.getConstructor().getParameters().size()) {
|
if (constrainingType.getConstructor().getParameters().size() != subjectType.getConstructor().getParameters().size()) {
|
||||||
errorConstraintPositions.add(constraintPosition);
|
errorConstraintPositions.add(constraintPosition);
|
||||||
typeConstructorMismatch = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassDescriptor subClass = (ClassDescriptor) constrainingType.getConstructor().getDeclarationDescriptor();
|
ClassDescriptor subClass = (ClassDescriptor) constrainingType.getConstructor().getDeclarationDescriptor();
|
||||||
ClassDescriptor superClass = (ClassDescriptor) subjectType.getConstructor().getDeclarationDescriptor();
|
ClassDescriptor superClass = (ClassDescriptor) subjectType.getConstructor().getDeclarationDescriptor();
|
||||||
if (DescriptorUtils.isSubclass(subClass, superClass)) {
|
if (DescriptorUtils.isSubclass(subClass, superClass)) {
|
||||||
@@ -175,23 +182,26 @@ public class ConstraintsSystemImpl implements ConstraintsSystem {
|
|||||||
List<TypeProjection> superArguments = subjectType.getArguments();
|
List<TypeProjection> superArguments = subjectType.getArguments();
|
||||||
List<TypeParameterDescriptor> superParameters = subjectType.getConstructor().getParameters();
|
List<TypeParameterDescriptor> superParameters = subjectType.getConstructor().getParameters();
|
||||||
for (int i = 0; i < superArguments.size(); i++) {
|
for (int i = 0; i < superArguments.size(); i++) {
|
||||||
addConstraint(varianceToConstraintKind(superParameters.get(i).getVariance()), superArguments.get(i).getType(),
|
//todo subArguments.get(i).getType() -> type projections
|
||||||
|
addConstraint(ConstraintKind.fromVariance(superParameters.get(i).getVariance()), superArguments.get(i).getType(),
|
||||||
subArguments.get(i).getType(), constraintPosition);
|
subArguments.get(i).getType(), constraintPosition);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typeConstructorMismatch = true;
|
|
||||||
errorConstraintPositions.add(constraintPosition);
|
errorConstraintPositions.add(constraintPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//todo move to type constraints
|
||||||
private void addBoundToTypeConstraints(@NotNull ConstraintKind constraintKind, @NotNull JetType subjectType,
|
private void addBoundToTypeConstraints(@NotNull ConstraintKind constraintKind, @NotNull JetType subjectType,
|
||||||
@NotNull JetType constrainingType, @NotNull TypeConstraintsImpl typeConstraints) {
|
@NotNull JetType constrainingType, @NotNull TypeConstraintsImpl typeConstraints) {
|
||||||
|
|
||||||
if (TypeUtils.dependsOnTypeParameterConstructors(constrainingType, Collections.singleton(DONT_CARE.getConstructor()))) return;
|
if (TypeUtils.dependsOnTypeParameterConstructors(constrainingType, Collections.singleton(DONT_CARE.getConstructor()))) return;
|
||||||
|
//todo it's an error
|
||||||
if (subjectType.isNullable()) {
|
if (subjectType.isNullable()) {
|
||||||
constrainingType = TypeUtils.makeNotNullable(constrainingType);
|
constrainingType = TypeUtils.makeNotNullable(constrainingType);
|
||||||
}
|
}
|
||||||
|
//todo switch
|
||||||
if (constraintKind == ConstraintKind.SUPER_TYPE) {
|
if (constraintKind == ConstraintKind.SUPER_TYPE) {
|
||||||
typeConstraints.addLowerBound(constrainingType);
|
typeConstraints.addLowerBound(constrainingType);
|
||||||
}
|
}
|
||||||
@@ -249,4 +259,24 @@ public class ConstraintsSystemImpl implements ConstraintsSystem {
|
|||||||
public TypeSubstitutor getResultingSubstitutor() {
|
public TypeSubstitutor getResultingSubstitutor() {
|
||||||
return resultingSubstitutor;
|
return resultingSubstitutor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private enum ConstraintKind {
|
||||||
|
SUB_TYPE, SUPER_TYPE, EQUAL;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
static ConstraintKind fromVariance(@NotNull Variance variance) {
|
||||||
|
ConstraintKind constraintKind = null;
|
||||||
|
switch (variance) {
|
||||||
|
case INVARIANT:
|
||||||
|
constraintKind = EQUAL;
|
||||||
|
break;
|
||||||
|
case OUT_VARIANCE:
|
||||||
|
constraintKind = SUPER_TYPE;
|
||||||
|
break;
|
||||||
|
case IN_VARIANCE:
|
||||||
|
constraintKind = SUB_TYPE;
|
||||||
|
}
|
||||||
|
return constraintKind;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user