mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[CSSimplify] NFC: Switch matchTypes methods to use TypeMatchResult
This commit is contained in:
@@ -121,6 +121,8 @@ static ConstraintSystem::TypeMatchOptions getDefaultDecompositionOptions(
|
||||
return flags | ConstraintSystem::TMF_GenerateConstraints;
|
||||
}
|
||||
|
||||
// FIXME: This should return ConstraintSystem::TypeMatchResult instead
|
||||
// to give more information to the solver about the failure.
|
||||
bool constraints::
|
||||
matchCallArguments(ArrayRef<AnyFunctionType::Param> args,
|
||||
ArrayRef<AnyFunctionType::Param> params,
|
||||
@@ -646,14 +648,14 @@ getCalleeDeclAndArgs(ConstraintSystem &cs,
|
||||
}
|
||||
|
||||
// Match the argument of a call to the parameter.
|
||||
static ConstraintSystem::SolutionKind
|
||||
static ConstraintSystem::TypeMatchResult
|
||||
matchCallArguments(ConstraintSystem &cs, ConstraintKind kind,
|
||||
Type argType, Type paramType,
|
||||
ConstraintLocatorBuilder locator) {
|
||||
|
||||
if (paramType->isAny()) {
|
||||
if (argType->is<InOutType>())
|
||||
return ConstraintSystem::SolutionKind::Error;
|
||||
return cs.getTypeMatchFailure(locator);
|
||||
|
||||
// If the param type is Any, the function can only have one argument.
|
||||
// Check if exactly one argument was passed to this function, otherwise
|
||||
@@ -664,10 +666,10 @@ matchCallArguments(ConstraintSystem &cs, ConstraintKind kind,
|
||||
if (tupleArgType->getNumElements() != 1 ||
|
||||
(!cs.getASTContext().isSwiftVersion3() &&
|
||||
tupleArgType->getElement(0).hasName())) {
|
||||
return ConstraintSystem::SolutionKind::Error;
|
||||
return cs.getTypeMatchFailure(locator);
|
||||
}
|
||||
}
|
||||
return ConstraintSystem::SolutionKind::Solved;
|
||||
return cs.getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
// Extract the parameters.
|
||||
@@ -711,7 +713,7 @@ matchCallArguments(ConstraintSystem &cs, ConstraintKind kind,
|
||||
hasTrailingClosure,
|
||||
cs.shouldAttemptFixes(), listener,
|
||||
parameterBindings))
|
||||
return ConstraintSystem::SolutionKind::Error;
|
||||
return cs.getTypeMatchFailure(locator);
|
||||
|
||||
// Check the argument types for each of the parameters.
|
||||
ConstraintSystem::TypeMatchOptions subflags =
|
||||
@@ -779,21 +781,16 @@ matchCallArguments(ConstraintSystem &cs, ConstraintKind kind,
|
||||
subflags |= ConstraintSystem::TMF_ApplyingOperatorParameter;
|
||||
}
|
||||
|
||||
switch (cs.matchTypes(argTy, paramTy, subKind, subflags, loc)) {
|
||||
case ConstraintSystem::SolutionKind::Error:
|
||||
return ConstraintSystem::SolutionKind::Error;
|
||||
|
||||
case ConstraintSystem::SolutionKind::Solved:
|
||||
case ConstraintSystem::SolutionKind::Unsolved:
|
||||
break;
|
||||
}
|
||||
auto result = cs.matchTypes(argTy, paramTy, subKind, subflags, loc);
|
||||
if (result.isFailure())
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return ConstraintSystem::SolutionKind::Solved;
|
||||
return cs.getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
ConstraintSystem::SolutionKind
|
||||
ConstraintSystem::TypeMatchResult
|
||||
ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
|
||||
ConstraintKind kind, TypeMatchOptions flags,
|
||||
ConstraintLocatorBuilder locator) {
|
||||
@@ -803,7 +800,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
|
||||
// requiring element names to either match up or be disjoint.
|
||||
if (kind < ConstraintKind::Conversion) {
|
||||
if (tuple1->getNumElements() != tuple2->getNumElements())
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
for (unsigned i = 0, n = tuple1->getNumElements(); i != n; ++i) {
|
||||
const auto &elt1 = tuple1->getElement(i);
|
||||
@@ -813,31 +810,27 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
|
||||
if (elt1.getName() != elt2.getName()) {
|
||||
// Same-type requirements require exact name matches.
|
||||
if (kind <= ConstraintKind::Equal)
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
// For subtyping constraints, just make sure that this name isn't
|
||||
// used at some other position.
|
||||
if (elt2.hasName() && tuple1->getNamedElementId(elt2.getName()) != -1)
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
}
|
||||
|
||||
// Variadic bit must match.
|
||||
if (elt1.isVararg() != elt2.isVararg())
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
// Compare the element types.
|
||||
switch (matchTypes(elt1.getType(), elt2.getType(), kind, subflags,
|
||||
locator.withPathElement(
|
||||
LocatorPathElt::getTupleElement(i)))) {
|
||||
case SolutionKind::Error:
|
||||
return SolutionKind::Error;
|
||||
|
||||
case SolutionKind::Solved:
|
||||
case SolutionKind::Unsolved:
|
||||
break;
|
||||
}
|
||||
auto result = matchTypes(elt1.getType(), elt2.getType(), kind, subflags,
|
||||
locator.withPathElement(
|
||||
LocatorPathElt::getTupleElement(i)));
|
||||
if (result.isFailure())
|
||||
return result;
|
||||
}
|
||||
return SolutionKind::Solved;
|
||||
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
assert(kind >= ConstraintKind::Conversion);
|
||||
@@ -886,7 +879,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
|
||||
SmallVector<int, 16> sources;
|
||||
SmallVector<unsigned, 4> variadicArguments;
|
||||
if (computeTupleShuffle(tuple1, tuple2, sources, variadicArguments))
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
// Check each of the elements.
|
||||
bool hasVariadic = false;
|
||||
@@ -911,17 +904,11 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
|
||||
// Match up the types.
|
||||
const auto &elt1 = tuple1->getElement(idx1);
|
||||
const auto &elt2 = tuple2->getElement(idx2);
|
||||
switch (matchTypes(elt1.getType(), elt2.getType(), subKind, subflags,
|
||||
auto result = matchTypes(elt1.getType(), elt2.getType(), subKind, subflags,
|
||||
locator.withPathElement(
|
||||
LocatorPathElt::getTupleElement(idx1)))) {
|
||||
case SolutionKind::Error:
|
||||
return SolutionKind::Error;
|
||||
|
||||
case SolutionKind::Solved:
|
||||
case SolutionKind::Unsolved:
|
||||
break;
|
||||
}
|
||||
|
||||
LocatorPathElt::getTupleElement(idx1)));
|
||||
if (result.isFailure())
|
||||
return result;
|
||||
}
|
||||
|
||||
// If we have variadic arguments to check, do so now.
|
||||
@@ -930,26 +917,22 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
|
||||
auto eltType2 = elt2.getVarargBaseTy();
|
||||
|
||||
for (unsigned idx1 : variadicArguments) {
|
||||
switch (matchTypes(tuple1->getElementType(idx1), eltType2, subKind,
|
||||
auto result = matchTypes(tuple1->getElementType(idx1), eltType2, subKind,
|
||||
subflags,
|
||||
locator.withPathElement(
|
||||
LocatorPathElt::getTupleElement(idx1)))) {
|
||||
case SolutionKind::Error:
|
||||
return SolutionKind::Error;
|
||||
|
||||
case SolutionKind::Solved:
|
||||
case SolutionKind::Unsolved:
|
||||
break;
|
||||
}
|
||||
LocatorPathElt::getTupleElement(idx1)));
|
||||
if (result.isFailure())
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
ConstraintSystem::SolutionKind
|
||||
ConstraintSystem::TypeMatchResult
|
||||
ConstraintSystem::matchScalarToTupleTypes(Type type1, TupleType *tuple2,
|
||||
ConstraintKind kind, TypeMatchOptions flags,
|
||||
ConstraintKind kind,
|
||||
TypeMatchOptions flags,
|
||||
ConstraintLocatorBuilder locator) {
|
||||
int scalarFieldIdx = tuple2->getElementForScalarInit();
|
||||
assert(scalarFieldIdx >= 0 && "Invalid tuple for scalar-to-tuple");
|
||||
@@ -1001,7 +984,7 @@ static bool matchFunctionRepresentations(FunctionTypeRepresentation rep1,
|
||||
llvm_unreachable("Unhandled ConstraintKind in switch.");
|
||||
}
|
||||
|
||||
ConstraintSystem::SolutionKind
|
||||
ConstraintSystem::TypeMatchResult
|
||||
ConstraintSystem::matchFunctionParamTypes(ArrayRef<AnyFunctionType::Param> type1,
|
||||
ArrayRef<AnyFunctionType::Param> type2,
|
||||
Type argType,
|
||||
@@ -1011,7 +994,7 @@ ConstraintSystem::matchFunctionParamTypes(ArrayRef<AnyFunctionType::Param> type1
|
||||
ConstraintLocatorBuilder locator) {
|
||||
// Short-circuit matching zero-argument function types.
|
||||
if (type1.empty() && type2.empty()) {
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
TypeMatchOptions subflags = getDefaultDecompositionOptions(flags) | TMF_GenerateConstraints;
|
||||
@@ -1041,7 +1024,7 @@ ConstraintSystem::matchFunctionParamTypes(ArrayRef<AnyFunctionType::Param> type1
|
||||
if (constraints::matchCallArguments(
|
||||
type2, type1, defaultMap, hasTrailingClosure,
|
||||
/*allowFixes=*/false, listener, parameterBindings))
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
// Compare each of the bound arguments for this parameter.
|
||||
for (unsigned paramIdx = 0, numParams = parameterBindings.size();
|
||||
@@ -1061,22 +1044,17 @@ ConstraintSystem::matchFunctionParamTypes(ArrayRef<AnyFunctionType::Param> type1
|
||||
paramIdx));
|
||||
auto argTy = type1[argIdx].getType();
|
||||
|
||||
switch (matchTypes(argTy, paramTy, kind, subflags, loc)) {
|
||||
case ConstraintSystem::SolutionKind::Error:
|
||||
return SolutionKind::Error;
|
||||
|
||||
case SolutionKind::Solved:
|
||||
case SolutionKind::Unsolved:
|
||||
break;
|
||||
}
|
||||
auto result = matchTypes(argTy, paramTy, kind, subflags, loc);
|
||||
if (result.isFailure())
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
|
||||
ConstraintSystem::SolutionKind
|
||||
ConstraintSystem::TypeMatchResult
|
||||
ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
|
||||
ConstraintKind kind, TypeMatchOptions flags,
|
||||
ConstraintLocatorBuilder locator) {
|
||||
@@ -1086,28 +1064,28 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
|
||||
// If the 2nd type is an autoclosure, then the first type needs wrapping in a
|
||||
// closure despite already being a function type.
|
||||
if (func2->isAutoClosure())
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
if (kind < ConstraintKind::Subtype)
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
}
|
||||
|
||||
// A non-throwing function can be a subtype of a throwing function.
|
||||
if (func1->throws() != func2->throws()) {
|
||||
// Cannot drop 'throws'.
|
||||
if (func1->throws() || kind < ConstraintKind::Subtype)
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
}
|
||||
|
||||
// A non-@noescape function type can be a subtype of a @noescape function
|
||||
// type.
|
||||
if (func1->isNoEscape() != func2->isNoEscape() &&
|
||||
(func1->isNoEscape() || kind < ConstraintKind::Subtype))
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
if (matchFunctionRepresentations(func1->getExtInfo().getRepresentation(),
|
||||
func2->getExtInfo().getRepresentation(),
|
||||
kind)) {
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
}
|
||||
|
||||
// Determine how we match up the input/result types.
|
||||
@@ -1184,14 +1162,13 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
|
||||
AnyFunctionType::decomposeInput(func1Input, func1Params);
|
||||
AnyFunctionType::decomposeInput(func2Input, func2Params);
|
||||
|
||||
SolutionKind result =
|
||||
auto result =
|
||||
matchFunctionParamTypes(func2Params, func1Params, func2Input, func1Input,
|
||||
subKind, subflags,
|
||||
locator.withPathElement(ConstraintLocator::FunctionArgument));
|
||||
|
||||
if (result == SolutionKind::Error) {
|
||||
return SolutionKind::Error;
|
||||
}
|
||||
if (result.isFailure())
|
||||
return result;
|
||||
|
||||
// Result type can be covariant (or equal).
|
||||
return matchTypes(func1->getResult(), func2->getResult(), subKind,
|
||||
@@ -1200,7 +1177,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
|
||||
ConstraintLocator::FunctionResult));
|
||||
}
|
||||
|
||||
ConstraintSystem::SolutionKind
|
||||
ConstraintSystem::TypeMatchResult
|
||||
ConstraintSystem::matchSuperclassTypes(Type type1, Type type2,
|
||||
TypeMatchOptions flags,
|
||||
ConstraintLocatorBuilder locator) {
|
||||
@@ -1217,10 +1194,10 @@ ConstraintSystem::matchSuperclassTypes(Type type1, Type type2,
|
||||
subflags, locator);
|
||||
}
|
||||
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
}
|
||||
|
||||
ConstraintSystem::SolutionKind
|
||||
ConstraintSystem::TypeMatchResult
|
||||
ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
|
||||
ConstraintLocatorBuilder locator) {
|
||||
TypeMatchOptions subflags = TMF_GenerateConstraints;
|
||||
@@ -1233,7 +1210,7 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
|
||||
"Mismatched parents of nominal types");
|
||||
|
||||
if (!nominal1->getParent())
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
|
||||
// Match up the parents, exactly.
|
||||
return matchTypes(nominal1->getParent(), nominal2->getParent(),
|
||||
@@ -1248,53 +1225,44 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
|
||||
assert((bool)bound1->getParent() == (bool)bound2->getParent() &&
|
||||
"Mismatched parents of bound generics");
|
||||
if (bound1->getParent()) {
|
||||
switch (matchTypes(bound1->getParent(), bound2->getParent(),
|
||||
ConstraintKind::Equal, subflags,
|
||||
locator.withPathElement(ConstraintLocator::ParentType))){
|
||||
case SolutionKind::Error:
|
||||
return SolutionKind::Error;
|
||||
|
||||
case SolutionKind::Solved:
|
||||
case SolutionKind::Unsolved:
|
||||
break;
|
||||
}
|
||||
auto result = matchTypes(bound1->getParent(), bound2->getParent(),
|
||||
ConstraintKind::Equal, subflags,
|
||||
locator.withPathElement(
|
||||
ConstraintLocator::ParentType));
|
||||
if (result.isFailure())
|
||||
return result;
|
||||
}
|
||||
|
||||
// Match up the generic arguments, exactly.
|
||||
auto args1 = bound1->getGenericArgs();
|
||||
auto args2 = bound2->getGenericArgs();
|
||||
if (args1.size() != args2.size()) {
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
}
|
||||
for (unsigned i = 0, n = args1.size(); i != n; ++i) {
|
||||
switch (matchTypes(args1[i], args2[i], ConstraintKind::Equal,
|
||||
subflags,
|
||||
locator.withPathElement(
|
||||
LocatorPathElt::getGenericArgument(i)))) {
|
||||
case SolutionKind::Error:
|
||||
return SolutionKind::Error;
|
||||
auto result = matchTypes(args1[i], args2[i], ConstraintKind::Equal,
|
||||
subflags, locator.withPathElement(
|
||||
LocatorPathElt::getGenericArgument(i)));
|
||||
|
||||
case SolutionKind::Solved:
|
||||
case SolutionKind::Unsolved:
|
||||
break;
|
||||
}
|
||||
if (result.isFailure())
|
||||
return result;
|
||||
}
|
||||
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
ConstraintSystem::SolutionKind
|
||||
ConstraintSystem::TypeMatchResult
|
||||
ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
|
||||
ConstraintKind kind,
|
||||
TypeMatchOptions flags,
|
||||
ConstraintLocatorBuilder locator) {
|
||||
// FIXME: Feels like a hack.
|
||||
if (type1->is<InOutType>())
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
// Conformance to 'Any' always holds.
|
||||
if (type2->isAny())
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
|
||||
// If the first type is a type variable or member thereof, there's nothing
|
||||
// we can do now.
|
||||
@@ -1303,10 +1271,10 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
|
||||
addUnsolvedConstraint(
|
||||
Constraint::create(*this, kind, type1, type2,
|
||||
getConstraintLocator(locator)));
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
return SolutionKind::Unsolved;
|
||||
return getTypeMatchAmbiguous();
|
||||
}
|
||||
|
||||
TypeMatchOptions subflags = getDefaultDecompositionOptions(flags);
|
||||
@@ -1322,7 +1290,7 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
|
||||
}
|
||||
|
||||
if (!type2->isExistentialType())
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
auto layout = type2->getExistentialLayout();
|
||||
|
||||
@@ -1337,14 +1305,14 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
|
||||
// - classes
|
||||
if (!type1->isObjCExistentialType() &&
|
||||
!type1->mayHaveSuperclass())
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
} else {
|
||||
// Subtype relation to AnyObject also allows class-bound
|
||||
// existentials that are not @objc and therefore carry
|
||||
// witness tables.
|
||||
if (!type1->isClassExistentialType() &&
|
||||
!type1->mayHaveSuperclass())
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
}
|
||||
|
||||
// Keep going.
|
||||
@@ -1353,14 +1321,10 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
|
||||
|
||||
if (layout.superclass) {
|
||||
auto subKind = std::min(ConstraintKind::Subtype, kind);
|
||||
switch (matchTypes(type1, layout.superclass, subKind, subflags, locator)) {
|
||||
case SolutionKind::Solved:
|
||||
case SolutionKind::Unsolved:
|
||||
break;
|
||||
|
||||
case SolutionKind::Error:
|
||||
return SolutionKind::Error;
|
||||
}
|
||||
auto result = matchTypes(type1, layout.superclass, subKind, subflags,
|
||||
locator);
|
||||
if (result.isFailure())
|
||||
return result;
|
||||
}
|
||||
|
||||
for (auto *proto : layout.getProtocols()) {
|
||||
@@ -1373,11 +1337,11 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
|
||||
break;
|
||||
|
||||
case SolutionKind::Error:
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
}
|
||||
}
|
||||
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
static bool isStringCompatiblePointerBaseType(TypeChecker &TC,
|
||||
@@ -1467,10 +1431,11 @@ static bool isBindable(TypeVariableType *typeVar, Type type) {
|
||||
!type->is<DependentMemberType>();
|
||||
}
|
||||
|
||||
ConstraintSystem::SolutionKind ConstraintSystem::matchTypesBindTypeVar(
|
||||
ConstraintSystem::TypeMatchResult
|
||||
ConstraintSystem::matchTypesBindTypeVar(
|
||||
TypeVariableType *typeVar, Type type, ConstraintKind kind,
|
||||
TypeMatchOptions flags, ConstraintLocatorBuilder locator,
|
||||
std::function<SolutionKind()> formUnsolvedResult) {
|
||||
std::function<TypeMatchResult()> formUnsolvedResult) {
|
||||
assert(typeVar->is<TypeVariableType>() && "Expected a type variable!");
|
||||
// FIXME: Due to some SE-0110 related code farther up we can end
|
||||
// up with type variables wrapped in parens that will trip this
|
||||
@@ -1499,7 +1464,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::matchTypesBindTypeVar(
|
||||
// If the left-hand type variable cannot bind to an lvalue,
|
||||
// but we still have an lvalue, fail.
|
||||
if (!typeVar->getImpl().canBindToLValue() && type->hasLValueType())
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
// Okay. Bind below.
|
||||
|
||||
@@ -1507,7 +1472,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::matchTypesBindTypeVar(
|
||||
// type.
|
||||
if (typeVar->getImpl().mustBeMaterializable()) {
|
||||
if (!type->isMaterializable())
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
setMustBeMaterializableRecursive(type);
|
||||
}
|
||||
@@ -1518,15 +1483,15 @@ ConstraintSystem::SolutionKind ConstraintSystem::matchTypesBindTypeVar(
|
||||
// Bind type1 to Void only as a last resort.
|
||||
addConstraint(ConstraintKind::Defaultable, typeVar, type,
|
||||
getConstraintLocator(locator));
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
assignFixedType(typeVar, type);
|
||||
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
ConstraintSystem::SolutionKind
|
||||
ConstraintSystem::TypeMatchResult
|
||||
ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
TypeMatchOptions flags,
|
||||
ConstraintLocatorBuilder locator) {
|
||||
@@ -1564,14 +1529,14 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
// If the types are obviously equivalent, we're done.
|
||||
if (type1->hasParenSugar() == type2->hasParenSugar() &&
|
||||
type1->isEqual(type2))
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
} else {
|
||||
typeVar1 = desugar1->getAs<TypeVariableType>();
|
||||
typeVar2 = desugar2->getAs<TypeVariableType>();
|
||||
|
||||
// If the types are obviously equivalent, we're done.
|
||||
if (desugar1->isEqual(desugar2))
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
// Local function that should be used to produce the return value whenever
|
||||
@@ -1593,10 +1558,10 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
// algorithm would not terminate.
|
||||
addUnsolvedConstraint(Constraint::create(*this, kind, type1, type2,
|
||||
getConstraintLocator(locator)));
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
return SolutionKind::Unsolved;
|
||||
return getTypeMatchAmbiguous();
|
||||
};
|
||||
|
||||
// If either (or both) types are type variables, unify the type variables.
|
||||
@@ -1609,7 +1574,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
if (rep1 == rep2) {
|
||||
// We already merged these two types, so this constraint is
|
||||
// trivially solved.
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1629,7 +1594,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
|
||||
// Merge the equivalence classes corresponding to these two variables.
|
||||
mergeEquivalenceClasses(rep1, rep2);
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
assert((type1->is<TypeVariableType>() || type2->is<TypeVariableType>()) &&
|
||||
@@ -1661,7 +1626,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
} else {
|
||||
assignFixedType(typeVar2, type1);
|
||||
}
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
} else if (typeVar1 && !typeVar2) {
|
||||
// Simplify the right-hand type and perform the "occurs" check.
|
||||
typeVar1 = getRepresentative(typeVar1);
|
||||
@@ -1691,7 +1656,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
addUnsolvedConstraint(
|
||||
Constraint::create(*this, ConstraintKind::Equal, typeVar1, type2,
|
||||
getConstraintLocator(locator)));
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
return formUnsolvedResult();
|
||||
@@ -1747,7 +1712,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
!isSwiftVersion3) {
|
||||
if (!typeVar1 && !typeVar2) {
|
||||
if (type1->hasParenSugar() != type2->hasParenSugar()) {
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1778,14 +1743,13 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
#include "swift/AST/TypeNodes.def"
|
||||
case TypeKind::Module:
|
||||
if (desugar1 == desugar2) {
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
case TypeKind::Error:
|
||||
case TypeKind::Unresolved:
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
case TypeKind::GenericTypeParam:
|
||||
llvm_unreachable("unmapped dependent type in type checker");
|
||||
@@ -1899,7 +1863,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
|
||||
case TypeKind::LValue:
|
||||
if (kind == ConstraintKind::BindParam)
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
return matchTypes(cast<LValueType>(desugar1)->getObjectType(),
|
||||
cast<LValueType>(desugar2)->getObjectType(),
|
||||
ConstraintKind::Equal, subflags,
|
||||
@@ -1910,7 +1874,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
// If the RHS is an inout type, the LHS must be an @lvalue type.
|
||||
if (kind == ConstraintKind::BindParam ||
|
||||
kind >= ConstraintKind::OperatorArgumentConversion)
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
return matchTypes(cast<InOutType>(desugar1)->getObjectType(),
|
||||
cast<InOutType>(desugar2)->getObjectType(),
|
||||
@@ -2042,10 +2006,10 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
// These conversions are between concrete types that don't need further
|
||||
// resolution, so we can consider them immediately solved.
|
||||
auto addSolvedRestrictedConstraint
|
||||
= [&](ConversionRestrictionKind restriction) -> SolutionKind {
|
||||
= [&](ConversionRestrictionKind restriction) -> TypeMatchResult {
|
||||
addRestrictedConstraint(ConstraintKind::Subtype, restriction,
|
||||
type1, type2, locator);
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
};
|
||||
|
||||
if (auto meta1 = type1->getAs<MetatypeType>()) {
|
||||
@@ -2108,7 +2072,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
|
||||
if (kind == ConstraintKind::BindToPointerType) {
|
||||
if (desugar2->isEqual(getASTContext().TheEmptyTupleType))
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
if (concrete && kind >= ConstraintKind::Conversion) {
|
||||
@@ -2276,7 +2240,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
|
||||
if (concrete && kind >= ConstraintKind::Subtype &&
|
||||
(type1->isUninhabited() || type2->isVoid())) {
|
||||
increaseScore(SK_FunctionConversion);
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2368,7 +2332,7 @@ commit_to_conversions:
|
||||
if (isTypeVarOrMember1 || isTypeVarOrMember2)
|
||||
return formUnsolvedResult();
|
||||
|
||||
return SolutionKind::Error;
|
||||
return getTypeMatchFailure(locator);
|
||||
}
|
||||
|
||||
// Where there is more than one potential conversion, create a disjunction
|
||||
@@ -2397,21 +2361,36 @@ commit_to_conversions:
|
||||
fixedLocator));
|
||||
}
|
||||
addDisjunctionConstraint(constraints, fixedLocator);
|
||||
return SolutionKind::Solved;
|
||||
return getTypeMatchSuccess();
|
||||
}
|
||||
|
||||
// For a single potential conversion, directly recurse, so that we
|
||||
// don't allocate a new constraint or constraint locator.
|
||||
|
||||
auto formTypeMatchResult = [&](SolutionKind kind) {
|
||||
switch (kind) {
|
||||
case SolutionKind::Error:
|
||||
return getTypeMatchFailure(locator);
|
||||
|
||||
case SolutionKind::Solved:
|
||||
return getTypeMatchSuccess();
|
||||
|
||||
case SolutionKind::Unsolved:
|
||||
return getTypeMatchAmbiguous();
|
||||
}
|
||||
};
|
||||
|
||||
// Handle restrictions.
|
||||
if (auto restriction = conversionsOrFixes[0].getRestriction()) {
|
||||
return simplifyRestrictedConstraint(*restriction, type1, type2,
|
||||
kind, subflags, locator);
|
||||
return formTypeMatchResult(simplifyRestrictedConstraint(*restriction, type1,
|
||||
type2, kind,
|
||||
subflags, locator));
|
||||
}
|
||||
|
||||
// Handle fixes.
|
||||
auto fix = *conversionsOrFixes[0].getFix();
|
||||
return simplifyFixConstraint(fix, type1, type2, kind, subflags, locator);
|
||||
return formTypeMatchResult(simplifyFixConstraint(fix, type1, type2, kind,
|
||||
subflags, locator));
|
||||
}
|
||||
|
||||
ConstraintSystem::SolutionKind
|
||||
@@ -2456,7 +2435,7 @@ ConstraintSystem::simplifyConstructionConstraint(
|
||||
flags,
|
||||
ConstraintLocatorBuilder(locator)
|
||||
.withPathElement(ConstraintLocator::ApplyFunction))
|
||||
== SolutionKind::Error)
|
||||
.isFailure())
|
||||
return SolutionKind::Error;
|
||||
|
||||
return matchTypes(argType, valueType, ConstraintKind::Conversion,
|
||||
@@ -3668,8 +3647,7 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1,
|
||||
|
||||
// Make sure we have the bridged value type.
|
||||
if (matchTypes(unwrappedToType, bridgedValueType, ConstraintKind::Equal,
|
||||
subflags, locator)
|
||||
== ConstraintSystem::SolutionKind::Error)
|
||||
subflags, locator).isFailure())
|
||||
return SolutionKind::Error;
|
||||
|
||||
countOptionalInjections();
|
||||
@@ -3857,12 +3835,12 @@ ConstraintSystem::simplifyKeyPathConstraint(Type keyPathTy,
|
||||
return SolutionKind::Solved;
|
||||
}
|
||||
if (matchTypes(boundRoot, rootTy,
|
||||
ConstraintKind::Bind, subflags, locator) == SolutionKind::Error)
|
||||
ConstraintKind::Bind, subflags, locator).isFailure())
|
||||
return SolutionKind::Error;
|
||||
|
||||
if (boundValue
|
||||
&& matchTypes(boundValue, valueTy,
|
||||
ConstraintKind::Bind, subflags, locator) == SolutionKind::Error)
|
||||
ConstraintKind::Bind, subflags, locator).isFailure())
|
||||
return SolutionKind::Error;
|
||||
|
||||
return SolutionKind::Solved;
|
||||
@@ -4065,9 +4043,8 @@ ConstraintSystem::simplifyKeyPathApplicationConstraint(
|
||||
};
|
||||
/// Solve for a base whose lvalueness is to be determined.
|
||||
auto solveUnknown = [&]() -> ConstraintSystem::SolutionKind {
|
||||
if (matchTypes(kpValueTy, valueTy,
|
||||
ConstraintKind::Equal, subflags, locator)
|
||||
== SolutionKind::Error)
|
||||
if (matchTypes(kpValueTy, valueTy, ConstraintKind::Equal, subflags,
|
||||
locator).isFailure())
|
||||
return SolutionKind::Error;
|
||||
return unsolved();
|
||||
};
|
||||
@@ -4199,16 +4176,14 @@ ConstraintSystem::simplifyApplicableFnConstraint(
|
||||
if (matchTypes(func1->getInput(), func2->getInput(),
|
||||
ArgConv, subflags,
|
||||
outerLocator.withPathElement(
|
||||
ConstraintLocator::ApplyArgument))
|
||||
== SolutionKind::Error)
|
||||
ConstraintLocator::ApplyArgument)).isFailure())
|
||||
return SolutionKind::Error;
|
||||
|
||||
// The result types are equivalent.
|
||||
if (matchTypes(func1->getResult(), func2->getResult(),
|
||||
ConstraintKind::Bind,
|
||||
subflags,
|
||||
locator.withPathElement(ConstraintLocator::FunctionResult))
|
||||
== SolutionKind::Error)
|
||||
locator.withPathElement(ConstraintLocator::FunctionResult)).isFailure())
|
||||
return SolutionKind::Error;
|
||||
|
||||
// Record any fixes we attempted to get to the correct solution.
|
||||
@@ -4564,7 +4539,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
|
||||
matchKind,
|
||||
subflags,
|
||||
locator.withPathElement(
|
||||
ConstraintLocator::PathElement::getGenericArgument(0)));
|
||||
ConstraintLocator::PathElement::getGenericArgument(0)));
|
||||
}
|
||||
|
||||
// K1 < K2 && V1 < V2 || K1 bridges to K2 && V1 bridges to V2 ===>
|
||||
@@ -4585,7 +4560,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
|
||||
auto result = matchTypes(key1, key2, subMatchKind, subflags,
|
||||
locator.withPathElement(
|
||||
ConstraintLocator::PathElement::getGenericArgument(0)));
|
||||
if (result == SolutionKind::Error)
|
||||
if (result.isFailure())
|
||||
return result;
|
||||
|
||||
switch (matchTypes(value1, value2, subMatchKind, subflags,
|
||||
|
||||
Reference in New Issue
Block a user