diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 7b45f1d2650aa..cd989dcb7c59b 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -620,7 +620,7 @@ getCalleeDeclAndArgs(ConstraintSystem &cs, // Match the argument of a call to the parameter. static ConstraintSystem::SolutionKind -matchCallArguments(ConstraintSystem &cs, TypeMatchKind kind, +matchCallArguments(ConstraintSystem &cs, ConstraintKind kind, Type argType, Type paramType, ConstraintLocatorBuilder locator) { // Extract the parameters. @@ -657,30 +657,43 @@ matchCallArguments(ConstraintSystem &cs, TypeMatchKind kind, // Check the argument types for each of the parameters. ConstraintSystem::TypeMatchOptions subflags = ConstraintSystem::TMF_GenerateConstraints; - TypeMatchKind subKind; + ConstraintKind subKind; switch (kind) { - case TypeMatchKind::ArgumentTupleConversion: - subKind = TypeMatchKind::ArgumentConversion; + case ConstraintKind::ArgumentTupleConversion: + subKind = ConstraintKind::ArgumentConversion; break; - case TypeMatchKind::OperatorArgumentTupleConversion: - subKind = TypeMatchKind::OperatorArgumentConversion; + case ConstraintKind::OperatorArgumentTupleConversion: + subKind = ConstraintKind::OperatorArgumentConversion; break; - case TypeMatchKind::Conversion: - case TypeMatchKind::ExplicitConversion: - case TypeMatchKind::OperatorArgumentConversion: - case TypeMatchKind::ArgumentConversion: - case TypeMatchKind::BindType: - case TypeMatchKind::BindParamType: - case TypeMatchKind::BindToPointerType: - case TypeMatchKind::SameType: - case TypeMatchKind::Subtype: + case ConstraintKind::Conversion: + case ConstraintKind::ExplicitConversion: + case ConstraintKind::OperatorArgumentConversion: + case ConstraintKind::ArgumentConversion: + case ConstraintKind::Bind: + case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: + case ConstraintKind::Equal: + case ConstraintKind::Subtype: + case ConstraintKind::ApplicableFunction: + case ConstraintKind::BindOverload: + case ConstraintKind::CheckedCast: + case ConstraintKind::ConformsTo: + case ConstraintKind::Defaultable: + case ConstraintKind::Disjunction: + case ConstraintKind::DynamicTypeOf: + case ConstraintKind::LiteralConformsTo: + case ConstraintKind::OptionalObject: + case ConstraintKind::SelfObjectOfProtocol: + case ConstraintKind::TypeMember: + case ConstraintKind::UnresolvedValueMember: + case ConstraintKind::ValueMember: llvm_unreachable("Not a call argument constraint"); } auto haveOneNonUserConversion = - (subKind != TypeMatchKind::OperatorArgumentConversion); + (subKind != ConstraintKind::OperatorArgumentConversion); for (unsigned paramIdx = 0, numParams = parameterBindings.size(); @@ -722,13 +735,13 @@ matchCallArguments(ConstraintSystem &cs, TypeMatchKind kind, ConstraintSystem::SolutionKind ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2, - TypeMatchKind kind, TypeMatchOptions flags, + ConstraintKind kind, TypeMatchOptions flags, ConstraintLocatorBuilder locator) { TypeMatchOptions subflags = getDefaultDecompositionOptions(flags); // Equality and subtyping have fairly strict requirements on tuple matching, // requiring element names to either match up or be disjoint. - if (kind < TypeMatchKind::Conversion) { + if (kind < ConstraintKind::Conversion) { if (tuple1->getNumElements() != tuple2->getNumElements()) return SolutionKind::Error; @@ -739,7 +752,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2, // If the names don't match, we may have a conflict. if (elt1.getName() != elt2.getName()) { // Same-type requirements require exact name matches. - if (kind <= TypeMatchKind::SameType) + if (kind <= ConstraintKind::Equal) return SolutionKind::Error; // For subtyping constraints, just make sure that this name isn't @@ -767,29 +780,42 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2, return SolutionKind::Solved; } - assert(kind >= TypeMatchKind::Conversion); - TypeMatchKind subKind; + assert(kind >= ConstraintKind::Conversion); + ConstraintKind subKind; switch (kind) { - case TypeMatchKind::ArgumentTupleConversion: - subKind = TypeMatchKind::ArgumentConversion; + case ConstraintKind::ArgumentTupleConversion: + subKind = ConstraintKind::ArgumentConversion; break; - case TypeMatchKind::OperatorArgumentTupleConversion: - subKind = TypeMatchKind::OperatorArgumentConversion; + case ConstraintKind::OperatorArgumentTupleConversion: + subKind = ConstraintKind::OperatorArgumentConversion; break; - case TypeMatchKind::OperatorArgumentConversion: - case TypeMatchKind::ArgumentConversion: - case TypeMatchKind::ExplicitConversion: - case TypeMatchKind::Conversion: - subKind = TypeMatchKind::Conversion; + case ConstraintKind::OperatorArgumentConversion: + case ConstraintKind::ArgumentConversion: + case ConstraintKind::ExplicitConversion: + case ConstraintKind::Conversion: + subKind = ConstraintKind::Conversion; break; - case TypeMatchKind::BindType: - case TypeMatchKind::BindParamType: - case TypeMatchKind::BindToPointerType: - case TypeMatchKind::SameType: - case TypeMatchKind::Subtype: + case ConstraintKind::Bind: + case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: + case ConstraintKind::Equal: + case ConstraintKind::Subtype: + case ConstraintKind::ApplicableFunction: + case ConstraintKind::BindOverload: + case ConstraintKind::CheckedCast: + case ConstraintKind::ConformsTo: + case ConstraintKind::Defaultable: + case ConstraintKind::Disjunction: + case ConstraintKind::DynamicTypeOf: + case ConstraintKind::LiteralConformsTo: + case ConstraintKind::OptionalObject: + case ConstraintKind::SelfObjectOfProtocol: + case ConstraintKind::TypeMember: + case ConstraintKind::UnresolvedValueMember: + case ConstraintKind::ValueMember: llvm_unreachable("Not a conversion"); } @@ -860,7 +886,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2, ConstraintSystem::SolutionKind ConstraintSystem::matchScalarToTupleTypes(Type type1, TupleType *tuple2, - TypeMatchKind kind, TypeMatchOptions flags, + ConstraintKind kind, TypeMatchOptions flags, ConstraintLocatorBuilder locator) { int scalarFieldIdx = tuple2->getElementForScalarInit(); assert(scalarFieldIdx >= 0 && "Invalid tuple for scalar-to-tuple"); @@ -873,7 +899,7 @@ ConstraintSystem::matchScalarToTupleTypes(Type type1, TupleType *tuple2, ConstraintSystem::SolutionKind ConstraintSystem::matchTupleToScalarTypes(TupleType *tuple1, Type type2, - TypeMatchKind kind, TypeMatchOptions flags, + ConstraintKind kind, TypeMatchOptions flags, ConstraintLocatorBuilder locator) { assert(tuple1->getNumElements() == 1 && "Wrong number of elements"); assert(!tuple1->getElement(0).isVararg() && "Should not be variadic"); @@ -889,46 +915,59 @@ ConstraintSystem::matchTupleToScalarTypes(TupleType *tuple1, Type type2, // corresponding function type representations and the given match kind. static bool matchFunctionRepresentations(FunctionTypeRepresentation rep1, FunctionTypeRepresentation rep2, - TypeMatchKind kind) { + ConstraintKind kind) { switch (kind) { - case TypeMatchKind::BindType: - case TypeMatchKind::BindParamType: - case TypeMatchKind::BindToPointerType: - case TypeMatchKind::SameType: + case ConstraintKind::Bind: + case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: + case ConstraintKind::Equal: return rep1 != rep2; - case TypeMatchKind::Subtype: - case TypeMatchKind::Conversion: - case TypeMatchKind::ExplicitConversion: - case TypeMatchKind::ArgumentConversion: - case TypeMatchKind::ArgumentTupleConversion: - case TypeMatchKind::OperatorArgumentTupleConversion: - case TypeMatchKind::OperatorArgumentConversion: + case ConstraintKind::Subtype: + case ConstraintKind::Conversion: + case ConstraintKind::ExplicitConversion: + case ConstraintKind::ArgumentConversion: + case ConstraintKind::ArgumentTupleConversion: + case ConstraintKind::OperatorArgumentTupleConversion: + case ConstraintKind::OperatorArgumentConversion: + case ConstraintKind::ApplicableFunction: + case ConstraintKind::BindOverload: + case ConstraintKind::CheckedCast: + case ConstraintKind::ConformsTo: + case ConstraintKind::Defaultable: + case ConstraintKind::Disjunction: + case ConstraintKind::DynamicTypeOf: + case ConstraintKind::LiteralConformsTo: + case ConstraintKind::OptionalObject: + case ConstraintKind::SelfObjectOfProtocol: + case ConstraintKind::TypeMember: + case ConstraintKind::UnresolvedValueMember: + case ConstraintKind::ValueMember: return false; } } ConstraintSystem::SolutionKind ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, - TypeMatchKind kind, TypeMatchOptions flags, + ConstraintKind kind, TypeMatchOptions flags, ConstraintLocatorBuilder locator) { // An @autoclosure function type can be a subtype of a // non-@autoclosure function type. if (func1->isAutoClosure() != func2->isAutoClosure() && - kind < TypeMatchKind::Subtype) + kind < ConstraintKind::Subtype) return SolutionKind::Error; // A non-throwing function can be a subtype of a throwing function. if (func1->throws() != func2->throws()) { // Cannot drop 'throws'. - if (func1->throws() || (func2->throws() && kind < TypeMatchKind::Subtype)) + if (func1->throws() || (func2->throws() && kind < ConstraintKind::Subtype)) return SolutionKind::Error; } // A non-@noescape function type can be a subtype of a @noescape function // type. if (func1->isNoEscape() != func2->isNoEscape() && - (func1->isNoEscape() || kind < TypeMatchKind::Subtype)) + (func1->isNoEscape() || kind < ConstraintKind::Subtype)) return SolutionKind::Error; if (matchFunctionRepresentations(func1->getExtInfo().getRepresentation(), @@ -938,24 +977,39 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, } // Determine how we match up the input/result types. - TypeMatchKind subKind; + ConstraintKind subKind; switch (kind) { - case TypeMatchKind::BindType: - case TypeMatchKind::BindParamType: - case TypeMatchKind::BindToPointerType: - case TypeMatchKind::SameType: + case ConstraintKind::Bind: + case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: + case ConstraintKind::Equal: subKind = kind; break; - case TypeMatchKind::Subtype: - case TypeMatchKind::Conversion: - case TypeMatchKind::ExplicitConversion: - case TypeMatchKind::ArgumentConversion: - case TypeMatchKind::ArgumentTupleConversion: - case TypeMatchKind::OperatorArgumentTupleConversion: - case TypeMatchKind::OperatorArgumentConversion: - subKind = TypeMatchKind::Subtype; + case ConstraintKind::Subtype: + case ConstraintKind::Conversion: + case ConstraintKind::ExplicitConversion: + case ConstraintKind::ArgumentConversion: + case ConstraintKind::ArgumentTupleConversion: + case ConstraintKind::OperatorArgumentTupleConversion: + case ConstraintKind::OperatorArgumentConversion: + subKind = ConstraintKind::Subtype; break; + + case ConstraintKind::ApplicableFunction: + case ConstraintKind::BindOverload: + case ConstraintKind::CheckedCast: + case ConstraintKind::ConformsTo: + case ConstraintKind::Defaultable: + case ConstraintKind::Disjunction: + case ConstraintKind::DynamicTypeOf: + case ConstraintKind::LiteralConformsTo: + case ConstraintKind::OptionalObject: + case ConstraintKind::SelfObjectOfProtocol: + case ConstraintKind::TypeMember: + case ConstraintKind::UnresolvedValueMember: + case ConstraintKind::ValueMember: + llvm_unreachable("Not a relational constraint"); } TypeMatchOptions subflags = getDefaultDecompositionOptions(flags); @@ -979,7 +1033,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2, ConstraintSystem::SolutionKind ConstraintSystem::matchSuperclassTypes(Type type1, Type type2, - TypeMatchKind kind, + ConstraintKind kind, TypeMatchOptions flags, ConstraintLocatorBuilder locator) { TypeMatchOptions subflags = getDefaultDecompositionOptions(flags); @@ -992,7 +1046,7 @@ ConstraintSystem::matchSuperclassTypes(Type type1, Type type2, if (super1->getClassOrBoundGenericClass() != classDecl2) continue; - return matchTypes(super1, type2, TypeMatchKind::SameType, + return matchTypes(super1, type2, ConstraintKind::Equal, subflags, locator); } @@ -1016,7 +1070,7 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2, // Match up the parents, exactly. return matchTypes(nominal1->getParent(), nominal2->getParent(), - TypeMatchKind::SameType, subflags, + ConstraintKind::Equal, subflags, locator.withPathElement(ConstraintLocator::ParentType)); } @@ -1028,7 +1082,7 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2, "Mismatched parents of bound generics"); if (bound1->getParent()) { switch (matchTypes(bound1->getParent(), bound2->getParent(), - TypeMatchKind::SameType, subflags, + ConstraintKind::Equal, subflags, locator.withPathElement(ConstraintLocator::ParentType))){ case SolutionKind::Error: return SolutionKind::Error; @@ -1046,7 +1100,7 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2, return SolutionKind::Error; } for (unsigned i = 0, n = args1.size(); i != n; ++i) { - switch (matchTypes(args1[i], args2[i], TypeMatchKind::SameType, + switch (matchTypes(args1[i], args2[i], ConstraintKind::Equal, subflags, locator.withPathElement( LocatorPathElt::getGenericArgument(i)))) { @@ -1123,44 +1177,6 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2, return SolutionKind::Solved; } -/// \brief Map a type-matching kind to a constraint kind. -static ConstraintKind getConstraintKind(TypeMatchKind kind) { - switch (kind) { - case TypeMatchKind::BindType: - case TypeMatchKind::BindToPointerType: - return ConstraintKind::Bind; - - case TypeMatchKind::BindParamType: - return ConstraintKind::BindParam; - - case TypeMatchKind::SameType: - return ConstraintKind::Equal; - - case TypeMatchKind::Subtype: - return ConstraintKind::Subtype; - - case TypeMatchKind::Conversion: - return ConstraintKind::Conversion; - - case TypeMatchKind::ExplicitConversion: - return ConstraintKind::ExplicitConversion; - - case TypeMatchKind::ArgumentConversion: - return ConstraintKind::ArgumentConversion; - - case TypeMatchKind::ArgumentTupleConversion: - return ConstraintKind::ArgumentTupleConversion; - - case TypeMatchKind::OperatorArgumentTupleConversion: - return ConstraintKind::OperatorArgumentTupleConversion; - - case TypeMatchKind::OperatorArgumentConversion: - return ConstraintKind::OperatorArgumentConversion; - } - - llvm_unreachable("unhandled type matching kind"); -} - static bool isStringCompatiblePointerBaseType(TypeChecker &TC, DeclContext *DC, Type baseType) { @@ -1193,20 +1209,20 @@ static bool allowsBridgingFromObjC(TypeChecker &tc, DeclContext *dc, } ConstraintSystem::SolutionKind -ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, +ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, TypeMatchOptions flags, ConstraintLocatorBuilder locator) { // If we have type variables that have been bound to fixed types, look through // to the fixed type. bool isArgumentTupleConversion - = kind == TypeMatchKind::ArgumentTupleConversion || - kind == TypeMatchKind::OperatorArgumentTupleConversion; - type1 = getFixedTypeRecursive(type1, kind == TypeMatchKind::SameType, + = kind == ConstraintKind::ArgumentTupleConversion || + kind == ConstraintKind::OperatorArgumentTupleConversion; + type1 = getFixedTypeRecursive(type1, kind == ConstraintKind::Equal, isArgumentTupleConversion); auto desugar1 = type1->getDesugaredType(); TypeVariableType *typeVar1 = desugar1->getAs(); - type2 = getFixedTypeRecursive(type2, kind == TypeMatchKind::SameType, + type2 = getFixedTypeRecursive(type2, kind == ConstraintKind::Equal, isArgumentTupleConversion); auto desugar2 = type2->getDesugaredType(); TypeVariableType *typeVar2 = desugar2->getAs(); @@ -1232,9 +1248,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, // this new constraint will be solved at a later point. // Obviously, this must not happen at the top level, or the // algorithm would not terminate. - addUnsolvedConstraint(Constraint::create(*this, - getConstraintKind(kind), - type1, type2, DeclName(), + addUnsolvedConstraint(Constraint::create(*this, kind, type1, type2, + DeclName(), FunctionRefKind::Compound, getConstraintLocator(locator))); return SolutionKind::Solved; @@ -1246,9 +1261,9 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, // If either (or both) types are type variables, unify the type variables. if (typeVar1 || typeVar2) { switch (kind) { - case TypeMatchKind::BindType: - case TypeMatchKind::BindToPointerType: - case TypeMatchKind::SameType: { + case ConstraintKind::Bind: + case ConstraintKind::BindToPointerType: + case ConstraintKind::Equal: { if (typeVar1 && typeVar2) { auto rep1 = getRepresentative(typeVar1); auto rep2 = getRepresentative(typeVar2); @@ -1270,7 +1285,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, } // Provide a fixed type for the type variable. - bool wantRvalue = kind == TypeMatchKind::SameType; + bool wantRvalue = kind == ConstraintKind::Equal; if (typeVar1) { // If we want an rvalue, get the rvalue. if (wantRvalue) @@ -1295,7 +1310,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, // A constraint that binds any pointer to a void pointer is // ineffective, since any pointer can be converted to a void pointer. - if (kind == TypeMatchKind::BindToPointerType && desugar2->isVoid()) { + if (kind == ConstraintKind::BindToPointerType && desugar2->isVoid()) { // Bind type1 to Void only as a last resort. addConstraint(ConstraintKind::Defaultable, typeVar1, type2, getConstraintLocator(locator)); @@ -1327,7 +1342,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, return SolutionKind::Solved; } - case TypeMatchKind::BindParamType: { + case ConstraintKind::BindParam: { if (typeVar2 && !typeVar1) { if (auto *iot = dyn_cast(desugar1)) { assignFixedType(typeVar2, LValueType::get(iot->getObjectType())); @@ -1353,8 +1368,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, return formUnsolvedResult(); } - case TypeMatchKind::ArgumentTupleConversion: - case TypeMatchKind::Conversion: + case ConstraintKind::ArgumentTupleConversion: + case ConstraintKind::Conversion: if (typeVar1 && typeVar2) { auto rep1 = getRepresentative(typeVar1); auto rep2 = getRepresentative(typeVar2); @@ -1366,11 +1381,11 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, } SWIFT_FALLTHROUGH; - case TypeMatchKind::Subtype: - case TypeMatchKind::ExplicitConversion: - case TypeMatchKind::ArgumentConversion: - case TypeMatchKind::OperatorArgumentTupleConversion: - case TypeMatchKind::OperatorArgumentConversion: + case ConstraintKind::Subtype: + case ConstraintKind::ExplicitConversion: + case ConstraintKind::ArgumentConversion: + case ConstraintKind::OperatorArgumentTupleConversion: + case ConstraintKind::OperatorArgumentConversion: // We couldn't solve this constraint. If only one of the types is a type // variable, perhaps we can do something with it below. if (typeVar1 && typeVar2) { @@ -1380,6 +1395,21 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, } break; + + case ConstraintKind::ApplicableFunction: + case ConstraintKind::BindOverload: + case ConstraintKind::CheckedCast: + case ConstraintKind::ConformsTo: + case ConstraintKind::Defaultable: + case ConstraintKind::Disjunction: + case ConstraintKind::DynamicTypeOf: + case ConstraintKind::LiteralConformsTo: + case ConstraintKind::OptionalObject: + case ConstraintKind::SelfObjectOfProtocol: + case ConstraintKind::TypeMember: + case ConstraintKind::UnresolvedValueMember: + case ConstraintKind::ValueMember: + llvm_unreachable("Not a relational constraint"); } } @@ -1388,8 +1418,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, // If this is an argument conversion, handle it directly. The rules are // different from normal conversions. - if (kind == TypeMatchKind::ArgumentTupleConversion || - kind == TypeMatchKind::OperatorArgumentTupleConversion) { + if (kind == ConstraintKind::ArgumentTupleConversion || + kind == ConstraintKind::OperatorArgumentTupleConversion) { if (!typeVar2) { return ::matchCallArguments(*this, kind, type1, type2, locator); } @@ -1452,7 +1482,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, // Check for CF <-> ObjectiveC bridging. if (desugar1->getKind() == TypeKind::Class && - kind >= TypeMatchKind::Subtype) { + kind >= ConstraintKind::Subtype) { auto class1 = cast(nominal1->getDecl()); auto class2 = cast(nominal2->getDecl()); @@ -1489,18 +1519,18 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, auto meta1 = cast(desugar1); auto meta2 = cast(desugar2); - TypeMatchKind subKind = TypeMatchKind::SameType; + ConstraintKind subKind = ConstraintKind::Equal; // A.Type < B.Type if A < B and both A and B are classes. if (isa(desugar1) && - kind != TypeMatchKind::SameType && + kind != ConstraintKind::Equal && meta1->getInstanceType()->mayHaveSuperclass() && meta2->getInstanceType()->getClassOrBoundGenericClass()) - subKind = std::min(kind, TypeMatchKind::Subtype); + subKind = std::min(kind, ConstraintKind::Subtype); // P.Type < Q.Type if P < Q, both P and Q are protocols, and P.Type // and Q.Type are both existential metatypes. else if (isa(meta1) && isa(meta2)) - subKind = std::min(kind, TypeMatchKind::Subtype); + subKind = std::min(kind, ConstraintKind::Subtype); return matchTypes(meta1->getInstanceType(), meta2->getInstanceType(), subKind, subflags, @@ -1529,23 +1559,23 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, break; case TypeKind::LValue: - if (kind == TypeMatchKind::BindParamType) + if (kind == ConstraintKind::BindParam) return SolutionKind::Error; return matchTypes(cast(desugar1)->getObjectType(), cast(desugar2)->getObjectType(), - TypeMatchKind::SameType, subflags, + ConstraintKind::Equal, subflags, locator.withPathElement( ConstraintLocator::ArrayElementType)); case TypeKind::InOut: // If the RHS is an inout type, the LHS must be an @lvalue type. - if (kind == TypeMatchKind::BindParamType || - kind >= TypeMatchKind::OperatorArgumentConversion) + if (kind == ConstraintKind::BindParam || + kind >= ConstraintKind::OperatorArgumentConversion) return SolutionKind::Error; return matchTypes(cast(desugar1)->getObjectType(), cast(desugar2)->getObjectType(), - TypeMatchKind::SameType, subflags, + ConstraintKind::Equal, subflags, locator.withPathElement(ConstraintLocator::ArrayElementType)); case TypeKind::UnboundGeneric: @@ -1565,7 +1595,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, } } - if (concrete && kind >= TypeMatchKind::Subtype) { + if (concrete && kind >= ConstraintKind::Subtype) { auto tuple1 = type1->getAs(); auto tuple2 = type2->getAs(); @@ -1594,7 +1624,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, // to a tuple with varargs. if ((tuple2->getNumElements() == 1 && !tuple2->getElement(0).isVararg()) || - (kind >= TypeMatchKind::Conversion && + (kind >= ConstraintKind::Conversion && tuple2->getElementForScalarInit() >= 0 && (isArgumentTupleConversion || !tuple2->getVarArgsBaseType()))) { @@ -1628,7 +1658,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, // Don't allow this in operator contexts or we'll end up allowing // 'T() == U()' for unrelated T and U that just happen to be Hashable. // We can remove this special case when we implement operator hiding. - if (kind != TypeMatchKind::OperatorArgumentConversion) { + if (kind != ConstraintKind::OperatorArgumentConversion) { conversionsOrFixes.push_back( ConversionRestrictionKind::HashableToAnyHashable); } @@ -1688,7 +1718,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, } // Special implicit nominal conversions. - if (kind >= TypeMatchKind::Conversion) { + if (kind >= ConstraintKind::Conversion) { // Array -> Array. if (isArrayType(desugar1) && isArrayType(desugar2)) { conversionsOrFixes.push_back(ConversionRestrictionKind::ArrayUpcast); @@ -1704,12 +1734,12 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, } } - if (kind == TypeMatchKind::BindToPointerType) { + if (kind == ConstraintKind::BindToPointerType) { if (desugar2->isEqual(getASTContext().TheEmptyTupleType)) return SolutionKind::Solved; } - if (concrete && kind >= TypeMatchKind::Conversion) { + if (concrete && kind >= ConstraintKind::Conversion) { // An lvalue of type T1 can be converted to a value of type T2 so long as // T1 is convertible to T2 (by loading the value). Note that we cannot get // a value of inout type as an lvalue though. @@ -1726,7 +1756,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, } // Explicit bridging from a value type to an Objective-C class type. - if (kind == TypeMatchKind::ExplicitConversion) { + if (kind == ConstraintKind::ExplicitConversion) { if (type1->isPotentiallyBridgedValueType() && type1->getAnyNominal() != TC.Context.getImplicitlyUnwrappedOptionalDecl() && @@ -1749,7 +1779,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, if (isBridgeableTargetType) { Type bridgedValueType; if (TC.Context.getBridgedToObjC(DC, type1, &bridgedValueType)) { - if ((kind >= TypeMatchKind::ExplicitConversion || + if ((kind >= ConstraintKind::ExplicitConversion || bridgedValueType->getAnyNominal() != TC.Context.getErrorDecl())) conversionsOrFixes.push_back( @@ -1781,7 +1811,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, } // Pointer arguments can be converted from pointer-compatible types. - if (kind >= TypeMatchKind::ArgumentConversion) { + if (kind >= ConstraintKind::ArgumentConversion) { Type unwrappedType2 = type2; OptionalTypeKind type2OptionalKind; if (Type unwrapped = type2->getAnyOptionalObjectType(type2OptionalKind)) @@ -1801,7 +1831,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, Type simplifiedInoutBaseType = getFixedTypeRecursive(inoutBaseType, - kind == TypeMatchKind::SameType, + kind == ConstraintKind::Equal, isArgumentTupleConversion); // FIXME: If the base is still a type variable, we can't tell @@ -1819,8 +1849,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, if (!flags.contains(TMF_ApplyingOperatorParameter) && // Operators cannot use these implicit conversions. - (kind == TypeMatchKind::ArgumentConversion || - kind == TypeMatchKind::ArgumentTupleConversion)) { + (kind == ConstraintKind::ArgumentConversion || + kind == ConstraintKind::ArgumentTupleConversion)) { // We can potentially convert from an UnsafeMutablePointer // of a different type, if we're a void pointer. @@ -1902,7 +1932,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, } } - if (concrete && kind >= TypeMatchKind::OperatorArgumentConversion) { + if (concrete && kind >= ConstraintKind::OperatorArgumentConversion) { // If the RHS is an inout type, the LHS must be an @lvalue type. if (auto *iot = type2->getAs()) { return matchTypes(type1, LValueType::get(iot->getObjectType()), @@ -1916,7 +1946,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, // equivalent to a conformance relationship on the instance types. // This applies to nested metatype levels, so if A : P then // A.Type : P.Type. - if (concrete && kind >= TypeMatchKind::Subtype && + if (concrete && kind >= ConstraintKind::Subtype && type1->is() && type2->is()) { conversionsOrFixes.push_back( ConversionRestrictionKind::MetatypeToExistentialMetatype); @@ -1926,7 +1956,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, // we hit commit_to_conversions below, but we have to add a token restriction // to ensure we wrap the metatype value in a metatype erasure. if (concrete && type2->isExistentialType() && - kind >= TypeMatchKind::Subtype) { + kind >= ConstraintKind::Subtype) { conversionsOrFixes.push_back(ConversionRestrictionKind::Existential); } @@ -1937,7 +1967,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, { BoundGenericType *boundGenericType2; - if (concrete && kind >= TypeMatchKind::Subtype && + if (concrete && kind >= ConstraintKind::Subtype && (boundGenericType2 = type2->getAs())) { auto decl2 = boundGenericType2->getDecl(); if (auto optionalKind2 = decl2->classifyAsOptionalType()) { @@ -1956,7 +1986,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, conversionsOrFixes.push_back( ConversionRestrictionKind::ImplicitlyUnwrappedOptionalToOptional); } else if (optionalKind2 == OTK_ImplicitlyUnwrappedOptional && - kind >= TypeMatchKind::Conversion && + kind >= ConstraintKind::Conversion && decl1 == TC.Context.getOptionalDecl()) { assert(boundGenericType1->getGenericArgs().size() == 1); conversionsOrFixes.push_back( @@ -1974,7 +2004,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, // is convertible to U. { Type objectType1; - if (concrete && kind >= TypeMatchKind::Conversion && + if (concrete && kind >= ConstraintKind::Conversion && (objectType1 = lookThroughImplicitlyUnwrappedOptionalType(type1))) { conversionsOrFixes.push_back( ConversionRestrictionKind::ForceUnchecked); @@ -1984,7 +2014,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, // Allow '() -> T' to '() -> ()' and '() -> Never' to '() -> T' for closure // literals. { - if (concrete && kind >= TypeMatchKind::Subtype && + if (concrete && kind >= ConstraintKind::Subtype && (type1->isUninhabited() || type2->isVoid())) { SmallVector parts; locator.getLocatorParts(parts); @@ -1999,11 +2029,11 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, } } - if (concrete && kind == TypeMatchKind::BindParamType) { + if (concrete && kind == ConstraintKind::BindParam) { if (auto *iot = dyn_cast(desugar1)) { if (auto *lvt = dyn_cast(desugar2)) { return matchTypes(iot->getObjectType(), lvt->getObjectType(), - TypeMatchKind::BindType, subflags, + ConstraintKind::Bind, subflags, locator.withPathElement( ConstraintLocator::ArrayElementType)); } @@ -2023,7 +2053,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, // If we should attempt fixes, add those to the list. They'll only be visited // if there are no other possible solutions. if (shouldAttemptFixes() && !typeVar1 && !typeVar2 && - !flags.contains(TMF_ApplyingFix) && kind >= TypeMatchKind::Conversion) { + !flags.contains(TMF_ApplyingFix) && kind >= ConstraintKind::Conversion) { Type objectType1 = type1->getRValueObjectType(); // If we have an optional type, try to force-unwrap it. @@ -2093,7 +2123,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind, auto fixedLocator = getConstraintLocator(locator); SmallVector constraints; for (auto potential : conversionsOrFixes) { - auto constraintKind = getConstraintKind(kind); + auto constraintKind = kind; if (auto restriction = potential.getRestriction()) { // Determine the constraint kind. For a deep equality constraint, only @@ -2177,14 +2207,14 @@ ConstraintSystem::simplifyConstructionConstraint( case TypeKind::Tuple: { // Tuple construction is simply tuple conversion. if (matchTypes(resultType, desugarValueType, - TypeMatchKind::BindType, + ConstraintKind::Bind, flags, ConstraintLocatorBuilder(locator) .withPathElement(ConstraintLocator::ApplyFunction)) == SolutionKind::Error) return SolutionKind::Error; - return matchTypes(argType, valueType, TypeMatchKind::Conversion, + return matchTypes(argType, valueType, ConstraintKind::Conversion, getDefaultDecompositionOptions(flags), locator); } @@ -2455,11 +2485,11 @@ ConstraintSystem::simplifyCheckedCastConstraint( toBaseType)) { // The class we're bridging through must be a subtype of the type we're // coming from. - return matchTypes(classType, fromBaseType, TypeMatchKind::Subtype, + return matchTypes(classType, fromBaseType, ConstraintKind::Subtype, subflags, locator); } - return matchTypes(toBaseType, fromBaseType, TypeMatchKind::Subtype, + return matchTypes(toBaseType, fromBaseType, ConstraintKind::Subtype, subflags, locator); } case CheckedCastKind::DictionaryDowncast: { @@ -2480,7 +2510,7 @@ ConstraintSystem::simplifyCheckedCastConstraint( } // Perform subtype check on the possibly-bridged-through key type. - auto result = matchTypes(toKeyType, fromKeyType, TypeMatchKind::Subtype, + auto result = matchTypes(toKeyType, fromKeyType, ConstraintKind::Subtype, subflags, locator); if (result == SolutionKind::Error) return result; @@ -2493,7 +2523,7 @@ ConstraintSystem::simplifyCheckedCastConstraint( } // Perform subtype check on the possibly-bridged-through value type. - switch (matchTypes(toValueType, fromValueType, TypeMatchKind::Subtype, + switch (matchTypes(toValueType, fromValueType, ConstraintKind::Subtype, subflags, locator)) { case SolutionKind::Solved: return result; @@ -3342,7 +3372,7 @@ ConstraintSystem::simplifyDynamicTypeOfConstraint( } else { dynamicType2 = MetatypeType::get(type2); } - return matchTypes(type1, dynamicType2, TypeMatchKind::BindType, subflags, + return matchTypes(type1, dynamicType2, ConstraintKind::Bind, subflags, locator); } @@ -3355,7 +3385,7 @@ ConstraintSystem::simplifyDynamicTypeOfConstraint( // the constraint. if (auto metatype1 = type1->getAs()) return matchTypes(metatype1->getInstanceType(), type2, - TypeMatchKind::BindType, + ConstraintKind::Bind, subflags, locator); // If we have a normal metatype, we can't solve backwards unless we @@ -3366,7 +3396,7 @@ ConstraintSystem::simplifyDynamicTypeOfConstraint( if (instanceType1->isTypeVariableOrMember()) return formUnsolved(); - return matchTypes(instanceType1, type2, TypeMatchKind::BindType, subflags, + return matchTypes(instanceType1, type2, ConstraintKind::Bind, subflags, locator); } @@ -3441,10 +3471,10 @@ ConstraintSystem::simplifyApplicableFnConstraint( // If this application is part of an operator, then we allow an implicit // lvalue to be compatible with inout arguments. This is used by // assignment operators. - TypeMatchKind ArgConv = TypeMatchKind::ArgumentTupleConversion; + ConstraintKind ArgConv = ConstraintKind::ArgumentTupleConversion; if (isa(anchor) || isa(anchor) || isa(anchor)) - ArgConv = TypeMatchKind::OperatorArgumentTupleConversion; + ArgConv = ConstraintKind::OperatorArgumentTupleConversion; // The argument type must be convertible to the input type. if (matchTypes(func1->getInput(), func2->getInput(), @@ -3456,7 +3486,7 @@ ConstraintSystem::simplifyApplicableFnConstraint( // The result types are equivalent. if (matchTypes(func1->getResult(), func2->getResult(), - TypeMatchKind::BindType, + ConstraintKind::Bind, subflags, locator.withPathElement(ConstraintLocator::FunctionResult)) == SolutionKind::Error) @@ -3499,60 +3529,6 @@ ConstraintSystem::simplifyApplicableFnConstraint( return SolutionKind::Error; } -/// \brief Retrieve the type-matching kind corresponding to the given -/// constraint kind. -static TypeMatchKind getTypeMatchKind(ConstraintKind kind) { - switch (kind) { - case ConstraintKind::Bind: return TypeMatchKind::BindType; - case ConstraintKind::Equal: return TypeMatchKind::SameType; - case ConstraintKind::BindParam: return TypeMatchKind::BindParamType; - case ConstraintKind::Subtype: return TypeMatchKind::Subtype; - case ConstraintKind::Conversion: return TypeMatchKind::Conversion; - case ConstraintKind::ExplicitConversion: - return TypeMatchKind::ExplicitConversion; - case ConstraintKind::ArgumentConversion: - return TypeMatchKind::ArgumentConversion; - case ConstraintKind::ArgumentTupleConversion: - return TypeMatchKind::ArgumentTupleConversion; - case ConstraintKind::OperatorArgumentTupleConversion: - return TypeMatchKind::OperatorArgumentTupleConversion; - case ConstraintKind::OperatorArgumentConversion: - return TypeMatchKind::OperatorArgumentConversion; - - case ConstraintKind::ApplicableFunction: - llvm_unreachable("ApplicableFunction constraints don't involve " - "type matches"); - - case ConstraintKind::DynamicTypeOf: - llvm_unreachable("DynamicTypeOf constraints don't involve type matches"); - - case ConstraintKind::BindOverload: - llvm_unreachable("Overload binding constraints don't involve type matches"); - - case ConstraintKind::ConformsTo: - case ConstraintKind::LiteralConformsTo: - case ConstraintKind::SelfObjectOfProtocol: - llvm_unreachable("Conformance constraints don't involve type matches"); - - case ConstraintKind::CheckedCast: - llvm_unreachable("Checked cast constraints don't involve type matches"); - - case ConstraintKind::ValueMember: - case ConstraintKind::UnresolvedValueMember: - case ConstraintKind::TypeMember: - llvm_unreachable("Member constraints don't involve type matches"); - - case ConstraintKind::OptionalObject: - llvm_unreachable("optional object constraints don't involve type matches"); - - case ConstraintKind::Defaultable: - llvm_unreachable("Type properties don't involve type matches"); - - case ConstraintKind::Disjunction: - llvm_unreachable("Con/disjunction constraints don't involve type matches"); - } -} - Type ConstraintSystem::getBaseTypeForArrayType(TypeBase *type) { type = type->lookThroughAllAnyOptionalTypes().getPointer(); @@ -3593,8 +3569,7 @@ void ConstraintSystem::addRestrictedConstraint( ConversionRestrictionKind restriction, Type first, Type second, ConstraintLocatorBuilder locator) { - (void)simplifyRestrictedConstraint(restriction, first, second, - getTypeMatchKind(kind), + (void)simplifyRestrictedConstraint(restriction, first, second, kind, TMF_GenerateConstraints, locator); } @@ -3606,7 +3581,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyRestrictedConstraintImpl( ConversionRestrictionKind restriction, Type type1, Type type2, - TypeMatchKind matchKind, + ConstraintKind matchKind, TypeMatchOptions flags, ConstraintLocatorBuilder locator) { // Add to the score based on context. @@ -3622,7 +3597,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl( // We'll apply user conversions for operator arguments at the application // site. - if (matchKind == TypeMatchKind::OperatorArgumentConversion) { + if (matchKind == ConstraintKind::OperatorArgumentConversion) { flags |= TMF_ApplyingOperatorParameter; } @@ -3687,7 +3662,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl( addContextualScore(); increaseScore(SK_ValueToOptional); - assert(matchKind >= TypeMatchKind::Subtype); + assert(matchKind >= ConstraintKind::Subtype); auto generic2 = type2->castTo(); assert(generic2->getDecl()->classifyAsOptionalType()); return matchTypes(type1, generic2->getGenericArgs()[0], @@ -3704,7 +3679,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl( case ConversionRestrictionKind::ImplicitlyUnwrappedOptionalToOptional: case ConversionRestrictionKind::OptionalToOptional: { addContextualScore(); - assert(matchKind >= TypeMatchKind::Subtype); + assert(matchKind >= ConstraintKind::Subtype); auto generic1 = type1->castTo(); auto generic2 = type2->castTo(); assert(generic1->getDecl()->classifyAsOptionalType()); @@ -3726,7 +3701,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl( // conversions on their results. case ConversionRestrictionKind::ForceUnchecked: { addContextualScore(); - assert(matchKind >= TypeMatchKind::Conversion); + assert(matchKind >= ConstraintKind::Conversion); auto boundGenericType1 = type1->castTo(); assert(boundGenericType1->getDecl()->classifyAsOptionalType() == OTK_ImplicitlyUnwrappedOptional); @@ -3765,7 +3740,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl( auto baseType2 = getBaseTypeForPointer(*this, t2); return matchTypes(baseType1, baseType2, - TypeMatchKind::BindToPointerType, + ConstraintKind::BindToPointerType, subflags, locator); } @@ -3825,7 +3800,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl( // Set up the disjunction for the array or scalar cases. return matchTypes(baseType1, baseType2, - TypeMatchKind::BindToPointerType, + ConstraintKind::BindToPointerType, subflags, locator); } @@ -3838,7 +3813,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl( Type baseType2 = getBaseTypeForPointer(*this, t2); return matchTypes(baseType1, baseType2, - TypeMatchKind::BindToPointerType, + ConstraintKind::BindToPointerType, subflags, locator); } @@ -3935,7 +3910,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl( addConstraint(ConstraintKind::ConformsTo, tv, hashableProtocol->getDeclaredType(), constraintLocator); - return matchTypes(type1, tv, TypeMatchKind::Conversion, subflags, + return matchTypes(type1, tv, ConstraintKind::Conversion, subflags, locator); } @@ -3957,7 +3932,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl( return SolutionKind::Error; } - return matchTypes(objcClass, type2, TypeMatchKind::Subtype, subflags, + return matchTypes(objcClass, type2, ConstraintKind::Subtype, subflags, locator); } @@ -4021,11 +3996,11 @@ ConstraintSystem::simplifyRestrictedConstraintImpl( } // Make sure we have the bridged value type. - if (matchTypes(type2, bridgedValueType, TypeMatchKind::SameType, subflags, + if (matchTypes(type2, bridgedValueType, ConstraintKind::Equal, subflags, locator) == ConstraintSystem::SolutionKind::Error) return ConstraintSystem::SolutionKind::Error; - return matchTypes(type1, objcClass, TypeMatchKind::Subtype, subflags, + return matchTypes(type1, objcClass, ConstraintKind::Subtype, subflags, locator); } @@ -4041,7 +4016,7 @@ ConstraintSystem::simplifyRestrictedConstraintImpl( = nativeClass->getAttrs().getAttribute()->getObjCClass(); return matchTypes(bridgedObjCClass->getDeclaredInterfaceType(), - type2, TypeMatchKind::Subtype, subflags, locator); + type2, ConstraintKind::Subtype, subflags, locator); } // T < U' and U a toll-free-bridged to U' ===> T getDeclaredInterfaceType(), - TypeMatchKind::Subtype, subflags, locator); + ConstraintKind::Subtype, subflags, locator); } } @@ -4068,7 +4043,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyRestrictedConstraint( ConversionRestrictionKind restriction, Type type1, Type type2, - TypeMatchKind matchKind, + ConstraintKind matchKind, TypeMatchOptions flags, ConstraintLocatorBuilder locator) { switch (simplifyRestrictedConstraintImpl(restriction, type1, type2, @@ -4113,7 +4088,7 @@ bool ConstraintSystem::recordFix(Fix fix, ConstraintLocatorBuilder locator) { ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(Fix fix, Type type1, Type type2, - TypeMatchKind matchKind, + ConstraintKind matchKind, TypeMatchOptions flags, ConstraintLocatorBuilder locator) { if (recordFix(fix, locator)) @@ -4160,6 +4135,7 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first, case ConstraintKind::Equal: case ConstraintKind::Bind: case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: case ConstraintKind::Subtype: case ConstraintKind::Conversion: case ConstraintKind::ExplicitConversion: @@ -4167,8 +4143,7 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first, case ConstraintKind::ArgumentTupleConversion: case ConstraintKind::OperatorArgumentTupleConversion: case ConstraintKind::OperatorArgumentConversion: - return matchTypes(first, second, getTypeMatchKind(kind), subflags, - locator); + return matchTypes(first, second, kind, subflags, locator); case ConstraintKind::ApplicableFunction: return simplifyApplicableFnConstraint(first, second, subflags, locator); @@ -4230,6 +4205,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) { case ConstraintKind::Bind: case ConstraintKind::Equal: case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: case ConstraintKind::Subtype: case ConstraintKind::Conversion: case ConstraintKind::ExplicitConversion: @@ -4238,7 +4214,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) { case ConstraintKind::OperatorArgumentTupleConversion: case ConstraintKind::OperatorArgumentConversion: { // Relational constraints. - auto matchKind = getTypeMatchKind(constraint.getKind()); + auto matchKind = constraint.getKind(); // If there is a fix associated with this constraint, apply it. if (auto fix = constraint.getFix()) { diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index 233bcfdd06649..a6c94427401e8 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -676,6 +676,7 @@ static bool shouldBindToValueType(Constraint *constraint) case ConstraintKind::Bind: case ConstraintKind::Equal: case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: case ConstraintKind::ConformsTo: case ConstraintKind::LiteralConformsTo: case ConstraintKind::CheckedCast: @@ -757,6 +758,7 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs, case ConstraintKind::Bind: case ConstraintKind::Equal: case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: case ConstraintKind::Subtype: case ConstraintKind::Conversion: case ConstraintKind::ExplicitConversion: diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp index 601cbe726e533..eb97ddd17c4e1 100644 --- a/lib/Sema/Constraint.cpp +++ b/lib/Sema/Constraint.cpp @@ -53,6 +53,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second, case ConstraintKind::Bind: case ConstraintKind::Equal: case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: case ConstraintKind::Subtype: case ConstraintKind::Conversion: case ConstraintKind::ExplicitConversion: @@ -150,6 +151,7 @@ Constraint *Constraint::clone(ConstraintSystem &cs) const { case ConstraintKind::Bind: case ConstraintKind::Equal: case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: case ConstraintKind::Subtype: case ConstraintKind::Conversion: case ConstraintKind::ExplicitConversion: @@ -219,6 +221,7 @@ void Constraint::print(llvm::raw_ostream &Out, SourceManager *sm) const { case ConstraintKind::Bind: Out << " bind "; break; case ConstraintKind::Equal: Out << " equal "; break; case ConstraintKind::BindParam: Out << " bind param "; break; + case ConstraintKind::BindToPointerType: Out << " bind to pointer "; break; case ConstraintKind::Subtype: Out << " subtype "; break; case ConstraintKind::Conversion: Out << " conv "; break; case ConstraintKind::ExplicitConversion: Out << " expl conv "; break; @@ -449,6 +452,7 @@ gatherReferencedTypeVars(Constraint *constraint, case ConstraintKind::ApplicableFunction: case ConstraintKind::Bind: case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: case ConstraintKind::ArgumentConversion: case ConstraintKind::Conversion: case ConstraintKind::ExplicitConversion: diff --git a/lib/Sema/Constraint.h b/lib/Sema/Constraint.h index b2f1783ef2269..d08203699ed45 100644 --- a/lib/Sema/Constraint.h +++ b/lib/Sema/Constraint.h @@ -58,6 +58,8 @@ enum class ConstraintKind : char { /// type is an lvalue type with the same object type. Otherwise, the two /// types must be the same type. BindParam, + /// \brief Binds the first type to the element type of the second type. + BindToPointerType, /// \brief The first type is a subtype of the second type, i.e., a value /// of the type of the first type can be used wherever a value of the /// second type is expected. @@ -464,6 +466,7 @@ class Constraint final : public llvm::ilist_node, case ConstraintKind::Bind: case ConstraintKind::Equal: case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: case ConstraintKind::Subtype: case ConstraintKind::Conversion: case ConstraintKind::ExplicitConversion: diff --git a/lib/Sema/ConstraintGraph.cpp b/lib/Sema/ConstraintGraph.cpp index fe310b7c2dd29..edf8c9b9d443b 100644 --- a/lib/Sema/ConstraintGraph.cpp +++ b/lib/Sema/ConstraintGraph.cpp @@ -692,21 +692,22 @@ unsigned ConstraintGraph::computeConnectedComponents( /// edge in the graph. static bool shouldContractEdge(ConstraintKind kind) { switch (kind) { - case ConstraintKind::Bind: - case ConstraintKind::BindParam: - case ConstraintKind::Equal: - case ConstraintKind::BindOverload: - - // We currently only allow subtype contractions for the purpose of - // parameter binding constraints. - // TODO: We do this because of how inout parameter bindings are handled - // for implicit closure parameters. We should consider adjusting our - // current approach to unlock more opportunities for subtype contractions. - case ConstraintKind::Subtype: - return true; - - default: - return false; + case ConstraintKind::Bind: + case ConstraintKind::BindParam: + case ConstraintKind::BindToPointerType: + case ConstraintKind::Equal: + case ConstraintKind::BindOverload: + + // We currently only allow subtype contractions for the purpose of + // parameter binding constraints. + // TODO: We do this because of how inout parameter bindings are handled + // for implicit closure parameters. We should consider adjusting our + // current approach to unlock more opportunities for subtype contractions. + case ConstraintKind::Subtype: + return true; + + default: + return false; } } diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 70bfacfa2391e..704c7eea7ec9c 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -349,46 +349,6 @@ namespace constraints { struct ResolvedOverloadSetListItem; -/// \brief The kind of type matching to perform in matchTypes(). -enum class TypeMatchKind : char { - /// \brief Bind the types together directly. - BindType, - /// \brief Binds to a pointer element type. - BindToPointerType, - /// \brief Bind the type of a function parameter to the type of a reference - /// to it from within the function body. The param type is an inout type iff - /// the reference type is an lvalue type with the same object type. - /// Otherwise, the two types must be the same type. - BindParamType, - /// \brief Require the types to match exactly, but strips lvalueness from - /// a type when binding to a type variable. - SameType, - /// \brief Require the first type to be a subtype of the second type - /// (or be an exact match or trivial subtype). - Subtype, - /// \brief Requires the first type to be convertible to the second type, - /// which includes exact matches and both forms of subtyping. - Conversion, - /// \brief Requires the first type to be explicitly convertible to the second - /// type, which includes all forms of conversion included in Conversion, in - /// addition to bridging conversions. - ExplicitConversion, - /// \brief Requires the first type to be the element of an argument tuple - /// that is convertible to the second type, which represents the corresponding - /// element of the parameter tuple. - ArgumentConversion, - /// Requires the first type to be an argument type (tuple) that can be - /// converted to the second type, which represents the parameter type (tuple). - ArgumentTupleConversion, - /// \brief Requires the first type to be convertible to the second type, - /// which includes exact matches, both forms of subtyping, and inserting - /// address-of to convert implicit lvalues to inout arguments. This is - /// used by assignment operators. - OperatorArgumentConversion, - /// Like \c ArgumentTupleConversion, but for operators. - OperatorArgumentTupleConversion, -}; - /// \brief The result of comparing two constraint systems that are a solutions /// to the given set of constraints. enum class SolutionCompareResult { @@ -1852,7 +1812,7 @@ class ConstraintSystem { /// /// \returns the result of performing the tuple-to-tuple conversion. SolutionKind matchTupleTypes(TupleType *tuple1, TupleType *tuple2, - TypeMatchKind kind, TypeMatchOptions flags, + ConstraintKind kind, TypeMatchOptions flags, ConstraintLocatorBuilder locator); /// \brief Subroutine of \c matchTypes(), which matches a scalar type to @@ -1860,7 +1820,7 @@ class ConstraintSystem { /// /// \returns the result of performing the scalar-to-tuple conversion. SolutionKind matchScalarToTupleTypes(Type type1, TupleType *tuple2, - TypeMatchKind kind, + ConstraintKind kind, TypeMatchOptions flags, ConstraintLocatorBuilder locator); @@ -1869,20 +1829,20 @@ class ConstraintSystem { /// /// \returns the result of performing the tuple-to-scalar conversion. SolutionKind matchTupleToScalarTypes(TupleType *tuple1, Type type2, - TypeMatchKind kind, + ConstraintKind kind, TypeMatchOptions flags, ConstraintLocatorBuilder locator); /// \brief Subroutine of \c matchTypes(), which matches up two function /// types. SolutionKind matchFunctionTypes(FunctionType *func1, FunctionType *func2, - TypeMatchKind kind, TypeMatchOptions flags, + ConstraintKind kind, TypeMatchOptions flags, ConstraintLocatorBuilder locator); /// \brief Subroutine of \c matchTypes(), which matches up a value to a /// superclass. SolutionKind matchSuperclassTypes(Type type1, Type type2, - TypeMatchKind kind, TypeMatchOptions flags, + ConstraintKind kind, TypeMatchOptions flags, ConstraintLocatorBuilder locator); /// \brief Subroutine of \c matchTypes(), which matches up two types that @@ -1920,7 +1880,7 @@ class ConstraintSystem { /// the specific types being matched. /// /// \returns the result of attempting to solve this constraint. - SolutionKind matchTypes(Type type1, Type type2, TypeMatchKind kind, + SolutionKind matchTypes(Type type1, Type type2, ConstraintKind kind, TypeMatchOptions flags, ConstraintLocatorBuilder locator); @@ -2058,7 +2018,7 @@ class ConstraintSystem { SolutionKind simplifyRestrictedConstraintImpl( ConversionRestrictionKind restriction, Type type1, Type type2, - TypeMatchKind matchKind, + ConstraintKind matchKind, TypeMatchOptions flags, ConstraintLocatorBuilder locator); @@ -2067,7 +2027,7 @@ class ConstraintSystem { SolutionKind simplifyRestrictedConstraint( ConversionRestrictionKind restriction, Type type1, Type type2, - TypeMatchKind matchKind, + ConstraintKind matchKind, TypeMatchOptions flags, ConstraintLocatorBuilder locator); @@ -2075,7 +2035,7 @@ class ConstraintSystem { /// \brief Simplify a conversion constraint with a fix applied to it. SolutionKind simplifyFixConstraint(Fix fix, Type type1, Type type2, - TypeMatchKind matchKind, + ConstraintKind matchKind, TypeMatchOptions flags, ConstraintLocatorBuilder locator);