Merge pull request #5443 from gottesmm/rename_typelowering_apis_from_retainrelease_to_copydestroy

diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 7b45f1d..cd989dc 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -620,7 +620,7 @@
 
 // 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 @@
   // 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 @@
 
 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 @@
       // 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 @@
     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::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::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 @@
 // 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 @@
   }
 
   // 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::SolutionKind
 ConstraintSystem::matchSuperclassTypes(Type type1, Type type2,
-                                       TypeMatchKind kind,
+                                       ConstraintKind kind,
                                        TypeMatchOptions flags,
                                        ConstraintLocatorBuilder locator) {
   TypeMatchOptions subflags = getDefaultDecompositionOptions(flags);
@@ -992,7 +1046,7 @@
     if (super1->getClassOrBoundGenericClass() != classDecl2)
       continue;
 
-    return matchTypes(super1, type2, TypeMatchKind::SameType,
+    return matchTypes(super1, type2, ConstraintKind::Equal,
                       subflags, locator);
   }
 
@@ -1016,7 +1070,7 @@
 
     // 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 @@
          "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 @@
     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 @@
   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 @@
 }
 
 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<TypeVariableType>();
 
-  type2 = getFixedTypeRecursive(type2, kind == TypeMatchKind::SameType,
+  type2 = getFixedTypeRecursive(type2, kind == ConstraintKind::Equal,
                                 isArgumentTupleConversion);
   auto desugar2 = type2->getDesugaredType();
   TypeVariableType *typeVar2 = desugar2->getAs<TypeVariableType>();
@@ -1232,9 +1248,8 @@
       // 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 @@
   // 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 @@
       }
 
       // 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 @@
 
         // 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 @@
       return SolutionKind::Solved;
     }
 
-    case TypeMatchKind::BindParamType: {
+    case ConstraintKind::BindParam: {
       if (typeVar2 && !typeVar1) {
         if (auto *iot = dyn_cast<InOutType>(desugar1)) {
           assignFixedType(typeVar2, LValueType::get(iot->getObjectType()));
@@ -1353,8 +1368,8 @@
       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 @@
       }
       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 @@
       }
         
       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 @@
 
   // 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 @@
 
       // Check for CF <-> ObjectiveC bridging.
       if (desugar1->getKind() == TypeKind::Class &&
-          kind >= TypeMatchKind::Subtype) {
+          kind >= ConstraintKind::Subtype) {
         auto class1 = cast<ClassDecl>(nominal1->getDecl());
         auto class2 = cast<ClassDecl>(nominal2->getDecl());
 
@@ -1489,18 +1519,18 @@
       auto meta1 = cast<AnyMetatypeType>(desugar1);
       auto meta2 = cast<AnyMetatypeType>(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<MetatypeType>(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<ExistentialMetatypeType>(meta1)
           && isa<ExistentialMetatypeType>(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 @@
       break;
 
     case TypeKind::LValue:
-      if (kind == TypeMatchKind::BindParamType)
+      if (kind == ConstraintKind::BindParam)
         return SolutionKind::Error;
       return matchTypes(cast<LValueType>(desugar1)->getObjectType(),
                         cast<LValueType>(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<InOutType>(desugar1)->getObjectType(),
                         cast<InOutType>(desugar2)->getObjectType(),
-                        TypeMatchKind::SameType, subflags,
+                        ConstraintKind::Equal, subflags,
                   locator.withPathElement(ConstraintLocator::ArrayElementType));
 
     case TypeKind::UnboundGeneric:
@@ -1565,7 +1595,7 @@
     }
   }
 
-  if (concrete && kind >= TypeMatchKind::Subtype) {
+  if (concrete && kind >= ConstraintKind::Subtype) {
     auto tuple1 = type1->getAs<TupleType>();
     auto tuple2 = type2->getAs<TupleType>();
 
@@ -1594,7 +1624,7 @@
       // 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 @@
       // 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 @@
     }
     
     // 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 @@
     }
   }
   
-  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 @@
     }
 
     // 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 @@
         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 @@
     }
     
     // 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 @@
 
             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 @@
           
           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 @@
     }
   }
 
-  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<InOutType>()) {
       return matchTypes(type1, LValueType::get(iot->getObjectType()),
@@ -1916,7 +1946,7 @@
   // 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<MetatypeType>() && type2->is<ExistentialMetatypeType>()) {
     conversionsOrFixes.push_back(
       ConversionRestrictionKind::MetatypeToExistentialMetatype);
@@ -1926,7 +1956,7 @@
   // 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 @@
   {
     BoundGenericType *boundGenericType2;
     
-    if (concrete && kind >= TypeMatchKind::Subtype &&
+    if (concrete && kind >= ConstraintKind::Subtype &&
         (boundGenericType2 = type2->getAs<BoundGenericType>())) {
       auto decl2 = boundGenericType2->getDecl();
       if (auto optionalKind2 = decl2->classifyAsOptionalType()) {
@@ -1956,7 +1986,7 @@
             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 @@
   // 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 @@
   // 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<LocatorPathElt, 2> parts;
       locator.getLocatorParts(parts);
@@ -1999,11 +2029,11 @@
     }
   }
 
-  if (concrete && kind == TypeMatchKind::BindParamType) {
+  if (concrete && kind == ConstraintKind::BindParam) {
     if (auto *iot = dyn_cast<InOutType>(desugar1)) {
       if (auto *lvt = dyn_cast<LValueType>(desugar2)) {
         return matchTypes(iot->getObjectType(), lvt->getObjectType(),
-                          TypeMatchKind::BindType, subflags,
+                          ConstraintKind::Bind, subflags,
                           locator.withPathElement(
                             ConstraintLocator::ArrayElementType));
       }
@@ -2023,7 +2053,7 @@
   // 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 @@
     auto fixedLocator = getConstraintLocator(locator);
     SmallVector<Constraint *, 2> 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 @@
   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 @@
                                                               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 @@
     }
 
     // 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 @@
     }
 
     // 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 @@
     } else {
       dynamicType2 = MetatypeType::get(type2);
     }
-    return matchTypes(type1, dynamicType2, TypeMatchKind::BindType, subflags,
+    return matchTypes(type1, dynamicType2, ConstraintKind::Bind, subflags,
                       locator);
   }
 
@@ -3355,7 +3385,7 @@
   // the constraint.
   if (auto metatype1 = type1->getAs<ExistentialMetatypeType>())
     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 @@
     if (instanceType1->isTypeVariableOrMember())
       return formUnsolved();
 
-    return matchTypes(instanceType1, type2, TypeMatchKind::BindType, subflags,
+    return matchTypes(instanceType1, type2, ConstraintKind::Bind, subflags,
                       locator);
   }
 
@@ -3441,10 +3471,10 @@
     // 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<PrefixUnaryExpr>(anchor) || isa<PostfixUnaryExpr>(anchor) ||
         isa<BinaryExpr>(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 @@
 
     // 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 @@
   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 @@
                              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::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 @@
   
   // 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 @@
     addContextualScore();
     increaseScore(SK_ValueToOptional);
 
-    assert(matchKind >= TypeMatchKind::Subtype);
+    assert(matchKind >= ConstraintKind::Subtype);
     auto generic2 = type2->castTo<BoundGenericType>();
     assert(generic2->getDecl()->classifyAsOptionalType());
     return matchTypes(type1, generic2->getGenericArgs()[0],
@@ -3704,7 +3679,7 @@
   case ConversionRestrictionKind::ImplicitlyUnwrappedOptionalToOptional:
   case ConversionRestrictionKind::OptionalToOptional: {
     addContextualScore();
-    assert(matchKind >= TypeMatchKind::Subtype);
+    assert(matchKind >= ConstraintKind::Subtype);
     auto generic1 = type1->castTo<BoundGenericType>();
     auto generic2 = type2->castTo<BoundGenericType>();
     assert(generic1->getDecl()->classifyAsOptionalType());
@@ -3726,7 +3701,7 @@
   // conversions on their results.
   case ConversionRestrictionKind::ForceUnchecked: {
     addContextualScore();
-    assert(matchKind >= TypeMatchKind::Conversion);
+    assert(matchKind >= ConstraintKind::Conversion);
     auto boundGenericType1 = type1->castTo<BoundGenericType>();
     assert(boundGenericType1->getDecl()->classifyAsOptionalType()
              == OTK_ImplicitlyUnwrappedOptional);
@@ -3765,7 +3740,7 @@
     auto baseType2 = getBaseTypeForPointer(*this, t2);
 
     return matchTypes(baseType1, baseType2,
-                      TypeMatchKind::BindToPointerType,
+                      ConstraintKind::BindToPointerType,
                       subflags, locator);
   }
       
@@ -3825,7 +3800,7 @@
     // Set up the disjunction for the array or scalar cases.
 
     return matchTypes(baseType1, baseType2,
-                      TypeMatchKind::BindToPointerType,
+                      ConstraintKind::BindToPointerType,
                       subflags, locator);
   }
       
@@ -3838,7 +3813,7 @@
     Type baseType2 = getBaseTypeForPointer(*this, t2);
     
     return matchTypes(baseType1, baseType2,
-                      TypeMatchKind::BindToPointerType,
+                      ConstraintKind::BindToPointerType,
                       subflags, locator);
   }
     
@@ -3935,7 +3910,7 @@
     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 @@
       return SolutionKind::Error;
     }
 
-    return matchTypes(objcClass, type2, TypeMatchKind::Subtype, subflags,
+    return matchTypes(objcClass, type2, ConstraintKind::Subtype, subflags,
                       locator);
   }
 
@@ -4021,11 +3996,11 @@
     }
 
     // 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 @@
       = nativeClass->getAttrs().getAttribute<ObjCBridgedAttr>()->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 <c U
@@ -4057,7 +4032,7 @@
 
     return matchTypes(type1,
                       bridgedObjCClass->getDeclaredInterfaceType(),
-                      TypeMatchKind::Subtype, subflags, locator);
+                      ConstraintKind::Subtype, subflags, locator);
   }
   }
   
@@ -4068,7 +4043,7 @@
 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 @@
 
 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 @@
   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 @@
   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 @@
   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 @@
   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 233bcfd..a6c9442 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -676,6 +676,7 @@
   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 @@
     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 601cbe7..eb97ddd 100644
--- a/lib/Sema/Constraint.cpp
+++ b/lib/Sema/Constraint.cpp
@@ -53,6 +53,7 @@
   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 @@
   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 @@
   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 @@
   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 b2f1783..d082036 100644
--- a/lib/Sema/Constraint.h
+++ b/lib/Sema/Constraint.h
@@ -58,6 +58,8 @@
   /// 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 @@
     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 fe310b7..edf8c9b 100644
--- a/lib/Sema/ConstraintGraph.cpp
+++ b/lib/Sema/ConstraintGraph.cpp
@@ -692,21 +692,22 @@
 /// edge in the graph.
 static bool shouldContractEdge(ConstraintKind kind) {
   switch (kind) {
-    case ConstraintKind::Bind:
-    case ConstraintKind::BindParam:
-    case ConstraintKind::Equal:
-    case ConstraintKind::BindOverload:
+  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;
+  // 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;
+  default:
+    return false;
   }
 }
 
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 70bfacf..704c7ee 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -349,46 +349,6 @@
 
 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 @@
   ///
   /// \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 @@
   ///
   /// \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 @@
   ///
   /// \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 @@
   /// 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 @@
   SolutionKind simplifyRestrictedConstraintImpl(
                  ConversionRestrictionKind restriction,
                  Type type1, Type type2,
-                 TypeMatchKind matchKind,
+                 ConstraintKind matchKind,
                  TypeMatchOptions flags,
                  ConstraintLocatorBuilder locator);
 
@@ -2067,7 +2027,7 @@
   SolutionKind simplifyRestrictedConstraint(
                  ConversionRestrictionKind restriction,
                  Type type1, Type type2,
-                 TypeMatchKind matchKind,
+                 ConstraintKind matchKind,
                  TypeMatchOptions flags,
                  ConstraintLocatorBuilder locator);
 
@@ -2075,7 +2035,7 @@
   /// \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);