New type checking algorithm is used for subtyping constraint generation
This commit is contained in:
@@ -21,7 +21,7 @@ import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
|||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||||
import org.jetbrains.jet.lang.types.inference.ConstraintSystem;
|
import org.jetbrains.jet.lang.types.inference.ConstraintSystem;
|
||||||
import org.jetbrains.jet.lang.types.inference.ConstraintSystemSolution;
|
import org.jetbrains.jet.lang.types.inference.ConstraintSystemSolution;
|
||||||
import org.jetbrains.jet.lang.types.inference.SubtypingOnlyConstraintSystem;
|
import org.jetbrains.jet.lang.types.inference.ConstraintSystemImpl;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -414,7 +414,7 @@ public class CallResolver {
|
|||||||
if (!candidate.getTypeParameters().isEmpty()) {
|
if (!candidate.getTypeParameters().isEmpty()) {
|
||||||
// Type argument inference
|
// Type argument inference
|
||||||
|
|
||||||
ConstraintSystem constraintSystem = new SubtypingOnlyConstraintSystem();
|
ConstraintSystem constraintSystem = new ConstraintSystemImpl();
|
||||||
for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) {
|
for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) {
|
||||||
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO
|
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.types.Variance.INVARIANT;
|
||||||
import static org.jetbrains.jet.lang.types.Variance.IN_VARIANCE;
|
import static org.jetbrains.jet.lang.types.Variance.IN_VARIANCE;
|
||||||
import static org.jetbrains.jet.lang.types.Variance.OUT_VARIANCE;
|
import static org.jetbrains.jet.lang.types.Variance.OUT_VARIANCE;
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ public class JetTypeChecker {
|
|||||||
|
|
||||||
public boolean isSubtypeOf(@NotNull JetType subtype, @NotNull JetType supertype) {
|
public boolean isSubtypeOf(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
// return new TypeCheckingProcedure().run(subtype, supertype);
|
// return new TypeCheckingProcedure().run(subtype, supertype);
|
||||||
return new ExplicitInOutTypeCheckingProcedure().run(subtype, supertype);
|
return TYPE_CHECKER.run(subtype, supertype);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method returns the supertype of the first parameter that has the same constructor
|
// This method returns the supertype of the first parameter that has the same constructor
|
||||||
@@ -51,7 +52,39 @@ public class JetTypeChecker {
|
|||||||
return isOutProjected ? JetStandardClasses.getNothingType() : argument.getType();
|
return isOutProjected ? JetStandardClasses.getNothingType() : argument.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ExplicitInOutTypeCheckingProcedure {
|
/**
|
||||||
|
* Methods of this class return true to continue type checking and false to fail
|
||||||
|
*/
|
||||||
|
public interface TypingConstraintBuilder {
|
||||||
|
boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b);
|
||||||
|
boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype);
|
||||||
|
boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final TypeCheckingProcedure TYPE_CHECKER = new TypeCheckingProcedure(new TypingConstraintBuilder() {
|
||||||
|
@Override
|
||||||
|
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b) {
|
||||||
|
return TypeUtils.equalTypes(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
|
return INSTANCE.isSubtypeOf(subtype, supertype);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
|
return false; // type checking fails
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public static class TypeCheckingProcedure {
|
||||||
|
|
||||||
|
private final TypingConstraintBuilder constraintBuilder;
|
||||||
|
|
||||||
|
public TypeCheckingProcedure(TypingConstraintBuilder constraintBuilder) {
|
||||||
|
this.constraintBuilder = constraintBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean run(@NotNull JetType subtype, @NotNull JetType supertype) {
|
public boolean run(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
return isSubtypeOf(subtype, supertype);
|
return isSubtypeOf(subtype, supertype);
|
||||||
@@ -69,7 +102,7 @@ public class JetTypeChecker {
|
|||||||
}
|
}
|
||||||
@Nullable JetType closestSupertype = findCorrespondingSupertype(subtype, supertype);
|
@Nullable JetType closestSupertype = findCorrespondingSupertype(subtype, supertype);
|
||||||
if (closestSupertype == null) {
|
if (closestSupertype == null) {
|
||||||
return false;
|
if (!constraintBuilder.noCorrespondingSupertype(subtype, supertype)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return checkSubtypeForTheSameConstructor(closestSupertype, supertype);
|
return checkSubtypeForTheSameConstructor(closestSupertype, supertype);
|
||||||
@@ -84,6 +117,7 @@ public class JetTypeChecker {
|
|||||||
List<TypeParameterDescriptor> parameters = constructor.getParameters();
|
List<TypeParameterDescriptor> parameters = constructor.getParameters();
|
||||||
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
|
||||||
TypeParameterDescriptor parameter = parameters.get(i);
|
TypeParameterDescriptor parameter = parameters.get(i);
|
||||||
|
|
||||||
|
|
||||||
TypeProjection subArgument = subArguments.get(i);
|
TypeProjection subArgument = subArguments.get(i);
|
||||||
JetType subIn = getInType(parameter, subArgument);
|
JetType subIn = getInType(parameter, subArgument);
|
||||||
@@ -93,189 +127,193 @@ public class JetTypeChecker {
|
|||||||
JetType superIn = getInType(parameter, superArgument);
|
JetType superIn = getInType(parameter, superArgument);
|
||||||
JetType superOut = getOutType(parameter, superArgument);
|
JetType superOut = getOutType(parameter, superArgument);
|
||||||
|
|
||||||
if (!isSubtypeOf(subOut, superOut) || !isSubtypeOf(superIn, subIn)) {
|
if (parameter.getVariance() == INVARIANT && subArgument.getProjectionKind() == INVARIANT && superArgument.getProjectionKind() == INVARIANT) {
|
||||||
return false;
|
if (!constraintBuilder.assertEqualTypes(subArgument.getType(), superArgument.getType())) return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!constraintBuilder.assertSubtype(subOut, superOut)) return false;
|
||||||
|
if (!constraintBuilder.assertSubtype(superIn, subIn)) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static abstract class AbstractTypeCheckingProcedure<T> {
|
// public static abstract class AbstractTypeCheckingProcedure<T> {
|
||||||
|
//
|
||||||
protected enum StatusAction {
|
// protected enum StatusAction {
|
||||||
PROCEED(false),
|
// PROCEED(false),
|
||||||
DONE_WITH_CURRENT_TYPE(true),
|
// DONE_WITH_CURRENT_TYPE(true),
|
||||||
ABORT_ALL(true);
|
// ABORT_ALL(true);
|
||||||
|
//
|
||||||
private final boolean abort;
|
// private final boolean abort;
|
||||||
|
//
|
||||||
private StatusAction(boolean abort) {
|
// private StatusAction(boolean abort) {
|
||||||
this.abort = abort;
|
// this.abort = abort;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public boolean isAbort() {
|
// public boolean isAbort() {
|
||||||
return abort;
|
// return abort;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public final T run(@NotNull JetType subtype, @NotNull JetType supertype) {
|
// public final T run(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
proceedOrStop(subtype, supertype);
|
// proceedOrStop(subtype, supertype);
|
||||||
return result();
|
// return result();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
protected abstract StatusAction startForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype);
|
// protected abstract StatusAction startForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype);
|
||||||
|
//
|
||||||
protected abstract StatusAction noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype);
|
// protected abstract StatusAction noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype);
|
||||||
|
//
|
||||||
protected abstract StatusAction equalTypesRequired(@NotNull JetType subArgumentType, @NotNull JetType superArgumentType);
|
// protected abstract StatusAction equalTypesRequired(@NotNull JetType subArgumentType, @NotNull JetType superArgumentType);
|
||||||
|
//
|
||||||
protected abstract StatusAction varianceConflictFound(@NotNull TypeProjection subArgument, @NotNull TypeProjection superArgument);
|
// protected abstract StatusAction varianceConflictFound(@NotNull TypeProjection subArgument, @NotNull TypeProjection superArgument);
|
||||||
|
//
|
||||||
protected abstract StatusAction doneForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype);
|
// protected abstract StatusAction doneForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype);
|
||||||
|
//
|
||||||
protected abstract T result();
|
// protected abstract T result();
|
||||||
|
//
|
||||||
private StatusAction proceedOrStop(@NotNull JetType subtype, @NotNull JetType supertype) {
|
// private StatusAction proceedOrStop(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
StatusAction statusAction = startForPairOfTypes(subtype, supertype);
|
// StatusAction statusAction = startForPairOfTypes(subtype, supertype);
|
||||||
if (statusAction.isAbort()) {
|
// if (statusAction.isAbort()) {
|
||||||
return statusAction;
|
// return statusAction;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
JetType closestSupertype = findCorrespondingSupertype(subtype, supertype);
|
// JetType closestSupertype = findCorrespondingSupertype(subtype, supertype);
|
||||||
if (closestSupertype == null) {
|
// if (closestSupertype == null) {
|
||||||
return noCorrespondingSupertype(subtype, supertype);
|
// return noCorrespondingSupertype(subtype, supertype);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
proceed(closestSupertype, supertype);
|
// proceed(closestSupertype, supertype);
|
||||||
return doneForPairOfTypes(subtype, supertype);
|
// return doneForPairOfTypes(subtype, supertype);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private void proceed(@NotNull JetType subtype, @NotNull JetType supertype) {
|
// private void proceed(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
TypeConstructor constructor = subtype.getConstructor();
|
// TypeConstructor constructor = subtype.getConstructor();
|
||||||
assert constructor.equals(supertype.getConstructor()) : constructor + " is not " + supertype.getConstructor();
|
// assert constructor.equals(supertype.getConstructor()) : constructor + " is not " + supertype.getConstructor();
|
||||||
|
//
|
||||||
List<TypeProjection> subArguments = subtype.getArguments();
|
// List<TypeProjection> subArguments = subtype.getArguments();
|
||||||
List<TypeProjection> superArguments = supertype.getArguments();
|
// List<TypeProjection> superArguments = supertype.getArguments();
|
||||||
List<TypeParameterDescriptor> parameters = constructor.getParameters();
|
// List<TypeParameterDescriptor> parameters = constructor.getParameters();
|
||||||
|
//
|
||||||
loop:
|
// loop:
|
||||||
for (int i = 0; i < parameters.size(); i++) {
|
// for (int i = 0; i < parameters.size(); i++) {
|
||||||
TypeParameterDescriptor parameter = parameters.get(i);
|
// TypeParameterDescriptor parameter = parameters.get(i);
|
||||||
TypeProjection subArgument = subArguments.get(i);
|
// TypeProjection subArgument = subArguments.get(i);
|
||||||
TypeProjection superArgument = superArguments.get(i);
|
// TypeProjection superArgument = superArguments.get(i);
|
||||||
|
//
|
||||||
JetType subArgumentType = subArgument.getType();
|
// JetType subArgumentType = subArgument.getType();
|
||||||
JetType superArgumentType = superArgument.getType();
|
// JetType superArgumentType = superArgument.getType();
|
||||||
|
//
|
||||||
StatusAction action = null;
|
// StatusAction action = null;
|
||||||
switch (parameter.getVariance()) {
|
// switch (parameter.getVariance()) {
|
||||||
case INVARIANT:
|
// case INVARIANT:
|
||||||
switch (superArgument.getProjectionKind()) {
|
// switch (superArgument.getProjectionKind()) {
|
||||||
case INVARIANT:
|
// case INVARIANT:
|
||||||
action = equalTypesRequired(subArgumentType, superArgumentType);
|
// action = equalTypesRequired(subArgumentType, superArgumentType);
|
||||||
break;
|
// break;
|
||||||
case OUT_VARIANCE:
|
// case OUT_VARIANCE:
|
||||||
if (!subArgument.getProjectionKind().allowsOutPosition()) {
|
// if (!subArgument.getProjectionKind().allowsOutPosition()) {
|
||||||
action = varianceConflictFound(subArgument, superArgument);
|
// action = varianceConflictFound(subArgument, superArgument);
|
||||||
}
|
// }
|
||||||
else {
|
// else {
|
||||||
action = proceedOrStop(subArgumentType, superArgumentType);
|
// action = proceedOrStop(subArgumentType, superArgumentType);
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
case IN_VARIANCE:
|
// case IN_VARIANCE:
|
||||||
if (!subArgument.getProjectionKind().allowsInPosition()) {
|
// if (!subArgument.getProjectionKind().allowsInPosition()) {
|
||||||
action = varianceConflictFound(subArgument, superArgument);
|
// action = varianceConflictFound(subArgument, superArgument);
|
||||||
}
|
// }
|
||||||
else {
|
// else {
|
||||||
action = proceedOrStop(superArgumentType, subArgumentType);
|
// action = proceedOrStop(superArgumentType, subArgumentType);
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
case IN_VARIANCE:
|
// case IN_VARIANCE:
|
||||||
switch (superArgument.getProjectionKind()) {
|
// switch (superArgument.getProjectionKind()) {
|
||||||
case INVARIANT:
|
// case INVARIANT:
|
||||||
case IN_VARIANCE:
|
// case IN_VARIANCE:
|
||||||
action = proceedOrStop(superArgumentType, subArgumentType);
|
// action = proceedOrStop(superArgumentType, subArgumentType);
|
||||||
break;
|
// break;
|
||||||
case OUT_VARIANCE:
|
// case OUT_VARIANCE:
|
||||||
action = proceedOrStop(subArgumentType, superArgumentType);
|
// action = proceedOrStop(subArgumentType, superArgumentType);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
case OUT_VARIANCE:
|
// case OUT_VARIANCE:
|
||||||
switch (superArgument.getProjectionKind()) {
|
// switch (superArgument.getProjectionKind()) {
|
||||||
case INVARIANT:
|
// case INVARIANT:
|
||||||
case OUT_VARIANCE:
|
// case OUT_VARIANCE:
|
||||||
case IN_VARIANCE:
|
// case IN_VARIANCE:
|
||||||
action = proceedOrStop(subArgumentType, superArgumentType);
|
// action = proceedOrStop(subArgumentType, superArgumentType);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
switch (action) {
|
// switch (action) {
|
||||||
case ABORT_ALL: break loop;
|
// case ABORT_ALL: break loop;
|
||||||
case DONE_WITH_CURRENT_TYPE:
|
// case DONE_WITH_CURRENT_TYPE:
|
||||||
default:
|
// default:
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
private static class TypeCheckingProcedure extends AbstractTypeCheckingProcedure<Boolean> {
|
// private static class TypeCheckingProcedure extends AbstractTypeCheckingProcedure<Boolean> {
|
||||||
|
//
|
||||||
private boolean result = true;
|
// private boolean result = true;
|
||||||
|
//
|
||||||
private StatusAction fail() {
|
// private StatusAction fail() {
|
||||||
result = false;
|
// result = false;
|
||||||
return StatusAction.ABORT_ALL;
|
// return StatusAction.ABORT_ALL;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public StatusAction startForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype) {
|
// public StatusAction startForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
if (ErrorUtils.isErrorType(subtype) || ErrorUtils.isErrorType(supertype)) {
|
// if (ErrorUtils.isErrorType(subtype) || ErrorUtils.isErrorType(supertype)) {
|
||||||
return StatusAction.DONE_WITH_CURRENT_TYPE;
|
// return StatusAction.DONE_WITH_CURRENT_TYPE;
|
||||||
}
|
// }
|
||||||
if (!supertype.isNullable() && subtype.isNullable()) {
|
// if (!supertype.isNullable() && subtype.isNullable()) {
|
||||||
return fail();
|
// return fail();
|
||||||
}
|
// }
|
||||||
if (JetStandardClasses.isNothingOrNullableNothing(subtype)) {
|
// if (JetStandardClasses.isNothingOrNullableNothing(subtype)) {
|
||||||
return StatusAction.DONE_WITH_CURRENT_TYPE;
|
// return StatusAction.DONE_WITH_CURRENT_TYPE;
|
||||||
}
|
// }
|
||||||
return StatusAction.PROCEED;
|
// return StatusAction.PROCEED;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected StatusAction noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
// protected StatusAction noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
return fail();
|
// return fail();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected StatusAction equalTypesRequired(@NotNull JetType subArgumentType, @NotNull JetType superArgumentType) {
|
// protected StatusAction equalTypesRequired(@NotNull JetType subArgumentType, @NotNull JetType superArgumentType) {
|
||||||
if (!subArgumentType.equals(superArgumentType)) {
|
// if (!subArgumentType.equals(superArgumentType)) {
|
||||||
return fail();
|
// return fail();
|
||||||
}
|
// }
|
||||||
return StatusAction.PROCEED;
|
// return StatusAction.PROCEED;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected StatusAction varianceConflictFound(@NotNull TypeProjection subArgument, @NotNull TypeProjection superArgument) {
|
// protected StatusAction varianceConflictFound(@NotNull TypeProjection subArgument, @NotNull TypeProjection superArgument) {
|
||||||
return fail();
|
// return fail();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected StatusAction doneForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype) {
|
// protected StatusAction doneForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
return StatusAction.PROCEED;
|
// return StatusAction.PROCEED;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
protected Boolean result() {
|
// protected Boolean result() {
|
||||||
return result;
|
// return result;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-67
@@ -14,7 +14,7 @@ import java.util.Set;
|
|||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class SubtypingOnlyConstraintSystem implements ConstraintSystem {
|
public class ConstraintSystemImpl implements ConstraintSystem {
|
||||||
|
|
||||||
private static class LoopInTypeVariableConstraintsException extends RuntimeException {
|
private static class LoopInTypeVariableConstraintsException extends RuntimeException {
|
||||||
private LoopInTypeVariableConstraintsException() {
|
private LoopInTypeVariableConstraintsException() {
|
||||||
@@ -158,6 +158,39 @@ public class SubtypingOnlyConstraintSystem implements ConstraintSystem {
|
|||||||
private final Map<TypeParameterDescriptor, UnknownType> unknownTypes = Maps.newHashMap();
|
private final Map<TypeParameterDescriptor, UnknownType> unknownTypes = Maps.newHashMap();
|
||||||
private final JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
|
private final JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
|
||||||
|
|
||||||
|
private final JetTypeChecker.TypeCheckingProcedure constraintExpander = new JetTypeChecker.TypeCheckingProcedure(new JetTypeChecker.TypingConstraintBuilder() {
|
||||||
|
@Override
|
||||||
|
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b) {
|
||||||
|
return TypeUtils.equalTypes(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
|
TypeValue subtypeValue = getTypeValueFor(subtype);
|
||||||
|
TypeValue supertypeValue = getTypeValueFor(supertype);
|
||||||
|
|
||||||
|
if (someUnknown(subtypeValue, supertypeValue)) {
|
||||||
|
addSubtypingConstraintOnTypeValues(subtypeValue, supertypeValue);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||||
|
// If some of the types is an unknown, the constraint is already generated, and we should carry on
|
||||||
|
// otherwise there can be no solution, and we should fail
|
||||||
|
return someUnknown(getTypeValueFor(subtype), getTypeValueFor(supertype));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) {
|
||||||
|
return subtypeValue instanceof UnknownType || supertypeValue instanceof UnknownType;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
public ConstraintSystemImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private TypeValue getTypeValueFor(@NotNull JetType type) {
|
private TypeValue getTypeValueFor(@NotNull JetType type) {
|
||||||
DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
|
DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
|
||||||
@@ -217,7 +250,7 @@ public class SubtypingOnlyConstraintSystem implements ConstraintSystem {
|
|||||||
for (TypeValue upperBound : typeValue.getUpperBounds()) {
|
for (TypeValue upperBound : typeValue.getUpperBounds()) {
|
||||||
if (upperBound instanceof KnownType) {
|
if (upperBound instanceof KnownType) {
|
||||||
KnownType knownBoundType = (KnownType) upperBound;
|
KnownType knownBoundType = (KnownType) upperBound;
|
||||||
boolean ok = new SubtypingConstraintExpander().run(jetType, knownBoundType.getType());
|
boolean ok = constraintExpander.run(jetType, knownBoundType.getType());
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
return new Solution(true);
|
return new Solution(true);
|
||||||
}
|
}
|
||||||
@@ -344,72 +377,7 @@ public class SubtypingOnlyConstraintSystem implements ConstraintSystem {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// private class EqualityConstraintExpander extends JetTypeChecker.AbstractTypeCheckingProcedure<Boolean> {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
private class SubtypingConstraintExpander extends JetTypeChecker.AbstractTypeCheckingProcedure<Boolean> {
|
|
||||||
|
|
||||||
private boolean error = false;
|
|
||||||
|
|
||||||
private StatusAction fail() {
|
|
||||||
error = true;
|
|
||||||
return StatusAction.ABORT_ALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected StatusAction startForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype) {
|
|
||||||
return tryToAddConstraint(subtype, supertype);
|
|
||||||
}
|
|
||||||
|
|
||||||
private StatusAction tryToAddConstraint(@NotNull JetType subtype, @NotNull JetType supertype) {
|
|
||||||
TypeValue subtypeValue = getTypeValueFor(subtype);
|
|
||||||
TypeValue supertypeValue = getTypeValueFor(supertype);
|
|
||||||
|
|
||||||
if (someUnknown(subtypeValue, supertypeValue)) {
|
|
||||||
addSubtypingConstraintOnTypeValues(subtypeValue, supertypeValue);
|
|
||||||
}
|
|
||||||
return StatusAction.PROCEED;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) {
|
|
||||||
return subtypeValue instanceof UnknownType || supertypeValue instanceof UnknownType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected StatusAction noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
|
|
||||||
if (someUnknown(getTypeValueFor(subtype), getTypeValueFor(supertype))) {
|
|
||||||
return StatusAction.PROCEED;
|
|
||||||
}
|
|
||||||
return fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected StatusAction equalTypesRequired(@NotNull JetType subArgumentType, @NotNull JetType superArgumentType) {
|
|
||||||
if (!subArgumentType.equals(superArgumentType)) {
|
|
||||||
return fail();
|
|
||||||
}
|
|
||||||
return StatusAction.PROCEED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected StatusAction varianceConflictFound(@NotNull TypeProjection subArgument, @NotNull TypeProjection superArgument) {
|
|
||||||
return fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected StatusAction doneForPairOfTypes(@NotNull JetType subtype, @NotNull JetType supertype) {
|
|
||||||
return StatusAction.PROCEED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Boolean result() {
|
|
||||||
return !error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void println(String message) {
|
private static void println(String message) {
|
||||||
// System.out.println(message);
|
// System.out.println(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
-55
@@ -1,55 +0,0 @@
|
|||||||
package org.jetbrains.jet.lang.types.inference;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
|
||||||
import org.jetbrains.jet.lang.types.Variance;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author abreslav
|
|
||||||
*/
|
|
||||||
public class EqualityBasedConstraintSystem implements ConstraintSystem {
|
|
||||||
|
|
||||||
private abstract class Constraint {
|
|
||||||
private final TypeParameterDescriptor typeParameterDescriptor;
|
|
||||||
|
|
||||||
protected Constraint(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
|
|
||||||
this.typeParameterDescriptor = typeParameterDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public TypeParameterDescriptor getTypeParameterDescriptor() {
|
|
||||||
return typeParameterDescriptor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Unknown {
|
|
||||||
// T -> variance of its position
|
|
||||||
private final Map<TypeParameterDescriptor, Variance> typeParameters = Maps.newHashMap();
|
|
||||||
private final List<Constraint> constraints = Lists.newArrayList();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Map<TypeParameterDescriptor, Unknown> unknowns = Maps.newHashMap();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerTypeVariable(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull Variance positionVariance) {
|
|
||||||
throw new UnsupportedOperationException(); // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addSubtypingConstraint(@NotNull JetType lower, @NotNull JetType upper) {
|
|
||||||
throw new UnsupportedOperationException(); // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public ConstraintSystemSolution solve() {
|
|
||||||
throw new UnsupportedOperationException(); // TODO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user