Merge pull request #5445 from gottesmm/use_bit_for_ownershipqualification_when_deserializing

diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index 51b0276..b19a076 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -1489,7 +1489,7 @@
   void emitRetainValueOperation(SILLocation Loc, SILValue v) {
     assert(!v->getType().isAddress());
     auto &lowering = getTypeLowering(v->getType());
-    return lowering.emitRetainValue(*this, Loc, v);
+    lowering.emitCopyValue(*this, Loc, v);
   }
 
   /// Convenience function for calling TypeLowering.emitRelease on the type
@@ -1497,7 +1497,7 @@
   void emitReleaseValueOperation(SILLocation Loc, SILValue v) {
     assert(!v->getType().isAddress());
     auto &lowering = getTypeLowering(v->getType());
-    lowering.emitReleaseValue(*this, Loc, v);
+    lowering.emitDestroyValue(*this, Loc, v);
   }
 
   SILValue emitTupleExtract(SILLocation Loc, SILValue Operand, unsigned FieldNo,
diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h
index 57dc571..d6e15be 100644
--- a/include/swift/SIL/TypeLowering.h
+++ b/include/swift/SIL/TypeLowering.h
@@ -238,7 +238,7 @@
   /// Emit a lowered 'release_value' operation.
   ///
   /// This type must be loadable.
-  virtual void emitLoweredReleaseValue(SILBuilder &B, SILLocation loc,
+  virtual void emitLoweredDestroyValue(SILBuilder &B, SILLocation loc,
                                        SILValue value,
                                        LoweringStyle loweringStyle) const = 0;
 
@@ -246,24 +246,24 @@
                                     SILValue value,
                                     LoweringStyle loweringStyle) const {
     if (loweringStyle != LoweringStyle::Shallow)
-      return emitLoweredReleaseValue(B, loc, value, loweringStyle);
-    return emitReleaseValue(B, loc, value);
+      return emitLoweredDestroyValue(B, loc, value, loweringStyle);
+    return emitDestroyValue(B, loc, value);
   }
 
   /// Emit a lowered 'release_value' operation.
   ///
   /// This type must be loadable.
-  void emitLoweredReleaseValueShallow(SILBuilder &B, SILLocation loc,
+  void emitLoweredDestroyValueShallow(SILBuilder &B, SILLocation loc,
                                       SILValue value) const {
-    emitLoweredReleaseValue(B, loc, value, LoweringStyle::Shallow);
+    emitLoweredDestroyValue(B, loc, value, LoweringStyle::Shallow);
   }
 
   /// Emit a lowered 'release_value' operation.
   ///
   /// This type must be loadable.
-  void emitLoweredReleaseValueDeepNoEnum(SILBuilder &B, SILLocation loc,
+  void emitLoweredDestroyValueDeepNoEnum(SILBuilder &B, SILLocation loc,
                                          SILValue value) const {
-    emitLoweredReleaseValue(B, loc, value, LoweringStyle::DeepNoEnum);
+    emitLoweredDestroyValue(B, loc, value, LoweringStyle::DeepNoEnum);
   }
 
   /// Given a primitively loaded value of this type (which must be
@@ -274,30 +274,30 @@
   /// example, it performs an unowned_release on a value of [unknown]
   /// type.  It is therefore not necessarily the right thing to do on
   /// a semantic load.
-  virtual void emitReleaseValue(SILBuilder &B, SILLocation loc,
+  virtual void emitDestroyValue(SILBuilder &B, SILLocation loc,
                                 SILValue value) const = 0;
 
   /// Emit a lowered 'retain_value' operation.
   ///
   /// This type must be loadable.
-  virtual void emitLoweredRetainValue(SILBuilder &B, SILLocation loc,
+  virtual void emitLoweredCopyValue(SILBuilder &B, SILLocation loc,
                                     SILValue value,
                                     LoweringStyle style) const = 0;
 
   /// Emit a lowered 'retain_value' operation.
   ///
   /// This type must be loadable.
-  void emitLoweredRetainValueShallow(SILBuilder &B, SILLocation loc,
+  void emitLoweredCopyValueShallow(SILBuilder &B, SILLocation loc,
                                    SILValue value) const {
-    emitLoweredRetainValue(B, loc, value, LoweringStyle::Shallow);
+    emitLoweredCopyValue(B, loc, value, LoweringStyle::Shallow);
   }
 
   /// Emit a lowered 'retain_value' operation.
   ///
   /// This type must be loadable.
   void emitLoweredRetainValueDeepNoEnum(SILBuilder &B, SILLocation loc,
-                                      SILValue value) const {
-    emitLoweredRetainValue(B, loc, value, LoweringStyle::DeepNoEnum);
+                                        SILValue value) const {
+    emitLoweredCopyValue(B, loc, value, LoweringStyle::DeepNoEnum);
   }
 
   /// Given a primitively loaded value of this type (which must be
@@ -307,16 +307,16 @@
   /// with exactly the same semantics.  For example, it performs an
   /// unowned_retain on a value of [unknown] type.  It is therefore
   /// not necessarily the right thing to do on a semantic load.
-  virtual void emitRetainValue(SILBuilder &B, SILLocation loc,
+  virtual void emitCopyValue(SILBuilder &B, SILLocation loc,
                              SILValue value) const = 0;
 
   void emitLoweredCopyChildValue(SILBuilder &B, SILLocation loc,
                                  SILValue value,
                                  LoweringStyle style) const {
     if (style != LoweringStyle::Shallow) {
-      emitLoweredRetainValue(B, loc, value, style);
+      emitLoweredCopyValue(B, loc, value, style);
     } else {
-      emitRetainValue(B, loc, value);
+      emitCopyValue(B, loc, value);
     }
   }
 
diff --git a/lib/SIL/DynamicCasts.cpp b/lib/SIL/DynamicCasts.cpp
index 5020eac..995a50c 100644
--- a/lib/SIL/DynamicCasts.cpp
+++ b/lib/SIL/DynamicCasts.cpp
@@ -781,7 +781,7 @@
     SILValue getOwnedScalar(Source source, const TypeLowering &srcTL) {
       assert(!source.isAddress());
       if (!source.shouldTake())
-        srcTL.emitRetainValue(B, Loc, source.Value);
+        srcTL.emitCopyValue(B, Loc, source.Value);
       return source.Value;
     }
 
@@ -1217,7 +1217,7 @@
     SILValue succValue =
       new (B.getModule()) SILArgument(scalarSuccBB, targetValueType);
     if (!shouldTakeOnSuccess(consumption))
-      targetTL.emitRetainValue(B, loc, succValue);
+      targetTL.emitCopyValue(B, loc, succValue);
     targetTL.emitStoreOfCopy(B, loc, succValue, dest, IsInitialization);
     B.createBranch(loc, indirectSuccBB);
   }
@@ -1225,7 +1225,7 @@
   // Emit the failure block.
   if (shouldDestroyOnFailure(consumption)) {
     B.setInsertionPoint(scalarFailBB);
-    srcTL.emitReleaseValue(B, loc, srcValue);
+    srcTL.emitDestroyValue(B, loc, srcValue);
     B.createBranch(loc, indirectFailBB);
   }
 }
diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp
index 882ba94..ba07be1 100644
--- a/lib/SIL/TypeLowering.cpp
+++ b/lib/SIL/TypeLowering.cpp
@@ -495,12 +495,12 @@
     void emitDestroyAddress(SILBuilder &B, SILLocation loc,
                             SILValue addr) const override {
       SILValue value = B.createLoad(loc, addr);
-      emitReleaseValue(B, loc, value);
+      emitDestroyValue(B, loc, value);
     }
 
     void emitDestroyRValue(SILBuilder &B, SILLocation loc,
                            SILValue value) const override {
-      emitReleaseValue(B, loc, value);
+      emitDestroyValue(B, loc, value);
     }
 
     void emitCopyInto(SILBuilder &B, SILLocation loc,
@@ -533,24 +533,22 @@
       // Trivial
     }
 
-    void emitLoweredReleaseValue(SILBuilder &B, SILLocation loc,
-                                 SILValue value,
+    void emitLoweredDestroyValue(SILBuilder &B, SILLocation loc, SILValue value,
                                  LoweringStyle loweringStyle) const override {
       // Trivial
     }
 
-    void emitLoweredRetainValue(SILBuilder &B, SILLocation loc,
-                              SILValue value,
+    void emitLoweredCopyValue(SILBuilder &B, SILLocation loc, SILValue value,
                               LoweringStyle style) const override {
       // Trivial
     }
 
-    void emitRetainValue(SILBuilder &B, SILLocation loc,
+    void emitCopyValue(SILBuilder &B, SILLocation loc,
                        SILValue value) const override {
       // Trivial
     }
 
-    void emitReleaseValue(SILBuilder &B, SILLocation loc,
+    void emitDestroyValue(SILBuilder &B, SILLocation loc,
                           SILValue value) const override {
       // Trivial
     }
@@ -565,7 +563,8 @@
     SILValue emitLoadOfCopy(SILBuilder &B, SILLocation loc,
                             SILValue addr, IsTake_t isTake) const override {
       SILValue value = B.createLoad(loc, addr);
-      if (!isTake) emitRetainValue(B, loc, value);
+      if (!isTake)
+        emitCopyValue(B, loc, value);
       return value;
     }
 
@@ -575,7 +574,8 @@
       SILValue oldValue;
       if (!isInit) oldValue = B.createLoad(loc, addr);
       B.createStore(loc, newValue, addr);
-      if (!isInit) emitReleaseValue(B, loc, oldValue);
+      if (!isInit)
+        emitDestroyValue(B, loc, oldValue);
     }
   };
 
@@ -657,13 +657,12 @@
         });
     }
 
-    void emitRetainValue(SILBuilder &B, SILLocation loc,
+    void emitCopyValue(SILBuilder &B, SILLocation loc,
                        SILValue aggValue) const override {
       B.createRetainValue(loc, aggValue, Atomicity::Atomic);
     }
 
-    void emitLoweredRetainValue(SILBuilder &B, SILLocation loc,
-                              SILValue aggValue,
+    void emitLoweredCopyValue(SILBuilder &B, SILLocation loc, SILValue aggValue,
                               LoweringStyle style) const override {
       for (auto &child : getChildren(B.getModule())) {
         auto &childLowering = child.getLowering();
@@ -676,22 +675,22 @@
       }
     }
 
-    void emitReleaseValue(SILBuilder &B, SILLocation loc,
+    void emitDestroyValue(SILBuilder &B, SILLocation loc,
                           SILValue aggValue) const override {
       B.emitReleaseValueAndFold(loc, aggValue);
     }
 
-    void emitLoweredReleaseValue(SILBuilder &B, SILLocation loc,
+    void emitLoweredDestroyValue(SILBuilder &B, SILLocation loc,
                                  SILValue aggValue,
                                  LoweringStyle loweringStyle) const override {
       SimpleOperationTy Fn;
 
       switch(loweringStyle) {
       case LoweringStyle::Shallow:
-        Fn = &TypeLowering::emitReleaseValue;
+        Fn = &TypeLowering::emitDestroyValue;
         break;
       case LoweringStyle::DeepNoEnum:
-        Fn = &TypeLowering::emitLoweredReleaseValueDeepNoEnum;
+        Fn = &TypeLowering::emitLoweredDestroyValueDeepNoEnum;
         break;
       }
 
@@ -774,24 +773,22 @@
       : NonTrivialLoadableTypeLowering(SILType::getPrimitiveObjectType(type),
                                        IsNotReferenceCounted) {}
 
-    void emitRetainValue(SILBuilder &B, SILLocation loc,
+    void emitCopyValue(SILBuilder &B, SILLocation loc,
                        SILValue value) const override {
       B.createRetainValue(loc, value, Atomicity::Atomic);
     }
 
-    void emitLoweredRetainValue(SILBuilder &B, SILLocation loc,
-                              SILValue value,
+    void emitLoweredCopyValue(SILBuilder &B, SILLocation loc, SILValue value,
                               LoweringStyle style) const override {
       B.createRetainValue(loc, value, Atomicity::Atomic);
     }
-    
-    void emitReleaseValue(SILBuilder &B, SILLocation loc,
+
+    void emitDestroyValue(SILBuilder &B, SILLocation loc,
                           SILValue value) const override {
       B.emitReleaseValueAndFold(loc, value);
     }
 
-    void emitLoweredReleaseValue(SILBuilder &B, SILLocation loc,
-                                 SILValue value,
+    void emitLoweredDestroyValue(SILBuilder &B, SILLocation loc, SILValue value,
                                  LoweringStyle style) const override {
       assert(style != LoweringStyle::Shallow &&
              "This method should never be called when performing a shallow "
@@ -805,16 +802,14 @@
     LeafLoadableTypeLowering(SILType type, IsReferenceCounted_t isRefCounted)
       : NonTrivialLoadableTypeLowering(type, isRefCounted) {}
 
-    void emitLoweredRetainValue(SILBuilder &B, SILLocation loc,
-                              SILValue value,
+    void emitLoweredCopyValue(SILBuilder &B, SILLocation loc, SILValue value,
                               LoweringStyle style) const override {
-      emitRetainValue(B, loc, value);
+      emitCopyValue(B, loc, value);
     }
 
-    void emitLoweredReleaseValue(SILBuilder &B, SILLocation loc,
-                                 SILValue value,
+    void emitLoweredDestroyValue(SILBuilder &B, SILLocation loc, SILValue value,
                                  LoweringStyle style) const override {
-      emitReleaseValue(B, loc, value);
+      emitDestroyValue(B, loc, value);
     }
   };
 
@@ -825,13 +820,13 @@
     ReferenceTypeLowering(SILType type)
       : LeafLoadableTypeLowering(type, IsReferenceCounted) {}
 
-    void emitRetainValue(SILBuilder &B, SILLocation loc,
+    void emitCopyValue(SILBuilder &B, SILLocation loc,
                        SILValue value) const override {
       if (!isa<FunctionRefInst>(value))
         B.createStrongRetain(loc, value, Atomicity::Atomic);
     }
 
-    void emitReleaseValue(SILBuilder &B, SILLocation loc,
+    void emitDestroyValue(SILBuilder &B, SILLocation loc,
                           SILValue value) const override {
       B.emitStrongReleaseAndFold(loc, value);
     }
@@ -843,12 +838,12 @@
     LoadableUnownedTypeLowering(SILType type)
       : LeafLoadableTypeLowering(type, IsReferenceCounted) {}
 
-    void emitRetainValue(SILBuilder &B, SILLocation loc,
+    void emitCopyValue(SILBuilder &B, SILLocation loc,
                        SILValue value) const override {
       B.createUnownedRetain(loc, value, Atomicity::Atomic);
     }
 
-    void emitReleaseValue(SILBuilder &B, SILLocation loc,
+    void emitDestroyValue(SILBuilder &B, SILLocation loc,
                           SILValue value) const override {
       B.createUnownedRelease(loc, value, Atomicity::Atomic);
     }
@@ -888,24 +883,22 @@
       B.emitDestroyAddrAndFold(loc, value);
     }
 
-    void emitRetainValue(SILBuilder &B, SILLocation loc,
+    void emitCopyValue(SILBuilder &B, SILLocation loc,
                        SILValue value) const override {
       llvm_unreachable("type is not loadable!");
     }
 
-    void emitLoweredRetainValue(SILBuilder &B, SILLocation loc,
-                              SILValue value,
+    void emitLoweredCopyValue(SILBuilder &B, SILLocation loc, SILValue value,
                               LoweringStyle style) const override {
       llvm_unreachable("type is not loadable!");
     }
 
-    void emitReleaseValue(SILBuilder &B, SILLocation loc,
+    void emitDestroyValue(SILBuilder &B, SILLocation loc,
                           SILValue value) const override {
       llvm_unreachable("type is not loadable!");
     }
 
-    void emitLoweredReleaseValue(SILBuilder &B, SILLocation loc,
-                                 SILValue value,
+    void emitLoweredDestroyValue(SILBuilder &B, SILLocation loc, SILValue value,
                                  LoweringStyle style) const override {
       llvm_unreachable("type is not loadable!");
     }
diff --git a/lib/SILGen/ManagedValue.cpp b/lib/SILGen/ManagedValue.cpp
index 8cc6d79..5d4f382 100644
--- a/lib/SILGen/ManagedValue.cpp
+++ b/lib/SILGen/ManagedValue.cpp
@@ -33,7 +33,7 @@
   assert(!lowering.isTrivial() && "trivial value has cleanup?");
   
   if (!lowering.isAddressOnly()) {
-    lowering.emitRetainValue(gen.B, l, getValue());
+    lowering.emitCopyValue(gen.B, l, getValue());
     return gen.emitManagedRValueWithCleanup(getValue(), lowering);
   }
   
@@ -51,7 +51,7 @@
                          IsNotTake, IsInitialization);
     return;
   }
-  lowering.emitRetainValue(gen.B, L, getValue());
+  lowering.emitCopyValue(gen.B, L, getValue());
   gen.B.createStore(L, getValue(), dest);
 }
 
@@ -65,7 +65,7 @@
   
   SILValue result;
   if (!lowering.isAddressOnly()) {
-    lowering.emitRetainValue(gen.B, loc, getValue());
+    lowering.emitCopyValue(gen.B, loc, getValue());
     result = getValue();
   } else {
     result = gen.emitTemporaryAllocation(loc, getType());
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index 4946fa8..ac6686e 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -2422,7 +2422,7 @@
 
     case ResultConvention::Unowned:
       // Unretained. Retain the value.
-      resultTL.emitRetainValue(B, loc, result);
+      resultTL.emitCopyValue(B, loc, result);
       break;
     }
 
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index 056877a..9fd2525 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -898,7 +898,7 @@
     return tmp;
   }
 
-  lowering.emitRetainValue(gen.B, loc, arg);
+  lowering.emitCopyValue(gen.B, loc, arg);
   return arg;
 }
 
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index d33606a..d524b71 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -279,8 +279,8 @@
       selfValue = B.createLoad(cleanupLoc, selfLV);
       
       // Emit a retain of the loaded value, since we return it +1.
-      lowering.emitRetainValue(B, cleanupLoc, selfValue);
-      
+      lowering.emitCopyValue(B, cleanupLoc, selfValue);
+
       // Inject the self value into an optional if the constructor is failable.
       if (ctor->getFailability() != OTK_None) {
         selfValue = B.createEnum(ctor, selfValue,
diff --git a/lib/SILGen/SILGenDynamicCast.cpp b/lib/SILGen/SILGenDynamicCast.cpp
index 9b4ebcc..ac0f673 100644
--- a/lib/SILGen/SILGenDynamicCast.cpp
+++ b/lib/SILGen/SILGenDynamicCast.cpp
@@ -233,7 +233,7 @@
                                         SGFContext ctx) {
       // Retain the result if this is copy-on-success.
       if (!shouldTakeOnSuccess(consumption))
-        origTargetTL.emitRetainValue(SGF.B, Loc, value);
+        origTargetTL.emitCopyValue(SGF.B, Loc, value);
 
       // Enter a cleanup for the +1 result.
       ManagedValue result
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 778922c5..4f2af05 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -59,7 +59,7 @@
     return ManagedValue::forUnmanaged(v);
   assert(!lowering.isAddressOnly() && "cannot retain an unloadable type");
 
-  lowering.emitRetainValue(B, loc, v);
+  lowering.emitCopyValue(B, loc, v);
   return emitManagedRValueWithCleanup(v, lowering);
 }
 
@@ -1356,7 +1356,7 @@
 
   // If it's an object, retain and enter a release cleanup.
   if (valueTy.isObject()) {
-    valueTL.emitRetainValue(B, loc, value.getValue());
+    valueTL.emitCopyValue(B, loc, value.getValue());
     return emitManagedRValueWithCleanup(value.getValue(), valueTL);
   }
 
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 6a2003d..a851953 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -722,7 +722,7 @@
   // must retain them even if we're in a context that can accept a +0 value.
   case ParameterConvention::Direct_Unowned:
     gen.getTypeLowering(paramValue->getType())
-          .emitRetainValue(gen.B, loc, paramValue);
+        .emitCopyValue(gen.B, loc, paramValue);
     SWIFT_FALLTHROUGH;
   case ParameterConvention::Direct_Owned:
     return gen.emitManagedRValueWithCleanup(paramValue);
@@ -2104,7 +2104,7 @@
                        "reabstraction of returns_inner_pointer function");
       SWIFT_FALLTHROUGH;
     case ResultConvention::Unowned:
-      resultTL.emitRetainValue(Gen.B, Loc, resultValue);
+      resultTL.emitCopyValue(Gen.B, Loc, resultValue);
       return Gen.emitManagedRValueWithCleanup(resultValue, resultTL);
     }
     llvm_unreachable("bad result convention!");
diff --git a/lib/SILOptimizer/Analysis/ArraySemantic.cpp b/lib/SILOptimizer/Analysis/ArraySemantic.cpp
index 36b3ff4..2c36a84 100644
--- a/lib/SILOptimizer/Analysis/ArraySemantic.cpp
+++ b/lib/SILOptimizer/Analysis/ArraySemantic.cpp
@@ -665,7 +665,7 @@
   SILBuilderWithScope Builder(SemanticsCall);
   auto &ValLowering = Builder.getModule().getTypeLowering(V->getType());
   if (hasGetElementDirectResult()) {
-    ValLowering.emitRetainValue(Builder, SemanticsCall->getLoc(), V);
+    ValLowering.emitCopyValue(Builder, SemanticsCall->getLoc(), V);
     SemanticsCall->replaceAllUsesWith(V);
   } else {
     auto Dest = SemanticsCall->getArgument(0);
@@ -675,7 +675,7 @@
     if (!ASI)
       return false;
 
-    ValLowering.emitRetainValue(Builder, SemanticsCall->getLoc(), V);
+    ValLowering.emitCopyValue(Builder, SemanticsCall->getLoc(), V);
     ValLowering.emitStoreOfCopy(Builder, SemanticsCall->getLoc(), V, Dest,
                                 IsInitialization_t::IsInitialization);
   }
diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp
index b5a2072..71d9b43 100644
--- a/lib/SILOptimizer/IPO/CapturePromotion.cpp
+++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp
@@ -536,7 +536,7 @@
       SILFunction &F = getBuilder().getFunction();
       auto &typeLowering = F.getModule().getTypeLowering(I->second->getType());
       SILBuilderWithPostProcess<ClosureCloner, 1> B(this, Inst);
-      typeLowering.emitReleaseValue(B, Inst->getLoc(), I->second);
+      typeLowering.emitDestroyValue(B, Inst->getLoc(), I->second);
       return;
     }
   }
diff --git a/lib/SILOptimizer/Transforms/SILLowerAggregateInstrs.cpp b/lib/SILOptimizer/Transforms/SILLowerAggregateInstrs.cpp
index 998373c..78ca089 100644
--- a/lib/SILOptimizer/Transforms/SILLowerAggregateInstrs.cpp
+++ b/lib/SILOptimizer/Transforms/SILLowerAggregateInstrs.cpp
@@ -107,7 +107,7 @@
     //   retain_value %new : $*T
     IsTake_t IsTake = CA->isTakeOfSrc();
     if (IsTake_t::IsNotTake == IsTake) {
-      TL.emitLoweredRetainValue(Builder, CA->getLoc(), New,
+      TL.emitLoweredCopyValue(Builder, CA->getLoc(), New,
                               TypeLowering::LoweringStyle::DeepNoEnum);
     }
 
@@ -116,7 +116,7 @@
     //   *or*
     // release_value %old : $*T
     if (Old) {
-      TL.emitLoweredReleaseValue(Builder, CA->getLoc(), Old,
+      TL.emitLoweredDestroyValue(Builder, CA->getLoc(), Old,
                                  TypeLowering::LoweringStyle::DeepNoEnum);
     }
   }
@@ -146,7 +146,7 @@
     // If we have a type with reference semantics, emit a load/strong release.
     LoadInst *LI = Builder.createLoad(DA->getLoc(), Addr);
     auto &TL = Module.getTypeLowering(Type);
-    TL.emitLoweredReleaseValue(Builder, DA->getLoc(), LI,
+    TL.emitLoweredDestroyValue(Builder, DA->getLoc(), LI,
                                TypeLowering::LoweringStyle::DeepNoEnum);
   }
 
@@ -168,7 +168,7 @@
          "release_value should never be called on a non-loadable type.");
 
   auto &TL = Module.getTypeLowering(Type);
-  TL.emitLoweredReleaseValue(Builder, DV->getLoc(), Value,
+  TL.emitLoweredDestroyValue(Builder, DV->getLoc(), Value,
                              TypeLowering::LoweringStyle::DeepNoEnum);
 
   DEBUG(llvm::dbgs() << "    Expanding Destroy Value: " << *DV);
@@ -191,9 +191,9 @@
          "types.");
 
   auto &TL = Module.getTypeLowering(Type);
-  TL.emitLoweredRetainValue(Builder, CV->getLoc(), Value,
+  TL.emitLoweredCopyValue(Builder, CV->getLoc(), Value,
                           TypeLowering::LoweringStyle::DeepNoEnum);
-  
+
   DEBUG(llvm::dbgs() << "    Expanding Copy Value: " << *CV);
 
   ++NumExpand;
diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp
index 1522164..ced42bf 100644
--- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp
+++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp
@@ -347,7 +347,7 @@
 
   auto Ty = DAI->getOperand()->getType();
   auto &TL = DAI->getModule().getTypeLowering(Ty);
-  TL.emitLoweredReleaseValue(Builder, DAI->getLoc(), NewValue,
+  TL.emitLoweredDestroyValue(Builder, DAI->getLoc(), NewValue,
                              Lowering::TypeLowering::LoweringStyle::DeepNoEnum);
   DAI->eraseFromParent();
 }
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);