diff --git a/lib/AST/TypeJoinMeet.cpp b/lib/AST/TypeJoinMeet.cpp
index ae0bc61c0251c..a1af594424502 100644
--- a/lib/AST/TypeJoinMeet.cpp
+++ b/lib/AST/TypeJoinMeet.cpp
@@ -314,7 +314,7 @@ CanType TypeJoin::visitFunctionType(CanType second) {
   auto secondExtInfo = secondFnTy->getExtInfo();
 
   // FIXME: Properly handle these attributes.
-  if (firstExtInfo.withNoEscape(false) != secondExtInfo.withNoEscape(false))
+  if (firstExtInfo != secondExtInfo)
     return Unimplemented;
 
   if (!AnyFunctionType::equalParams(firstFnTy->getParams(),
diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp
index e890299c4cf6d..a129fc838c681 100644
--- a/lib/Sema/CSBindings.cpp
+++ b/lib/Sema/CSBindings.cpp
@@ -81,7 +81,7 @@ ConstraintSystem::determineBestBindings() {
           continue;
 
         bindings.addPotentialBinding(
-            {type, AllowedBindingKind::Supertypes, binding.BindingSource});
+            binding.withSameSource(type, AllowedBindingKind::Supertypes));
       }
     }
 
@@ -143,8 +143,8 @@ void ConstraintSystem::PotentialBindings::addPotentialBinding(
       !binding.BindingType->hasUnresolvedType() &&
       !binding.BindingType->hasTypeVariable() &&
       !binding.BindingType->hasUnboundGenericType() &&
-      !binding.DefaultedProtocol && !binding.isDefaultableBinding() &&
-      allowJoinMeet) {
+      !binding.hasDefaultedLiteralProtocol() &&
+      !binding.isDefaultableBinding() && allowJoinMeet) {
     if (lastSupertypeIndex) {
       auto &lastBinding = Bindings[*lastSupertypeIndex];
       auto lastType = lastBinding.BindingType->getWithoutSpecifierType();
@@ -164,7 +164,7 @@ void ConstraintSystem::PotentialBindings::addPotentialBinding(
     lastSupertypeIndex = Bindings.size();
   }
 
-  if (auto *literalProtocol = binding.DefaultedProtocol)
+  if (auto *literalProtocol = binding.getDefaultedLiteralProtocol())
     foundLiteralBinding(literalProtocol);
 
   // If the type variable can't bind to an lvalue, make sure the
@@ -371,7 +371,7 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint(
     kind = AllowedBindingKind::Exact;
   }
 
-  return PotentialBinding{type, kind, constraint->getKind()};
+  return PotentialBinding{type, kind, constraint};
 }
 
 /// Retrieve the set of potential type bindings for the given
@@ -466,9 +466,8 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
               path.back().getKind() == ConstraintLocator::ClosureResult &&
               binding->Kind == AllowedBindingKind::Supertypes &&
               exactTypes.insert(voidType).second) {
-            result.addPotentialBinding(
-                {voidType, binding->Kind, constraint->getKind()},
-                /*allowJoinMeet=*/false);
+            result.addPotentialBinding({voidType, binding->Kind, constraint},
+                                       /*allowJoinMeet=*/false);
           }
         }
       }
@@ -551,9 +550,8 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
         if (!exactTypes.insert(defaultType->getCanonicalType()).second)
           continue;
 
-        literalBindings.push_back({defaultType, AllowedBindingKind::Subtypes,
-                                   constraint->getKind(),
-                                   constraint->getProtocol()});
+        literalBindings.push_back(
+            {defaultType, AllowedBindingKind::Subtypes, constraint});
         continue;
       }
 
@@ -578,9 +576,8 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
 
       if (!matched) {
         exactTypes.insert(defaultType->getCanonicalType());
-        literalBindings.push_back({defaultType, AllowedBindingKind::Subtypes,
-                                   constraint->getKind(),
-                                   constraint->getProtocol()});
+        literalBindings.push_back(
+            {defaultType, AllowedBindingKind::Subtypes, constraint});
       }
 
       break;
@@ -677,7 +674,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
       // might be covered by non-defaulted bindings.
       bool updatedBindingType = false;
       for (auto &literalBinding : literalBindings) {
-        auto *protocol = literalBinding.DefaultedProtocol;
+        auto *protocol = literalBinding.getDefaultedLiteralProtocol();
 
         assert(protocol);
 
@@ -716,7 +713,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
     }
 
     for (auto &literalBinding : literalBindings) {
-      auto *protocol = literalBinding.DefaultedProtocol;
+      auto *protocol = literalBinding.getDefaultedLiteralProtocol();
       // For any literal type that has been covered, skip them.
       if (coveredLiteralProtocols.count(protocol) == 0)
         result.addPotentialBinding(std::move(literalBinding));
@@ -729,9 +726,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
     if (!exactTypes.insert(type->getCanonicalType()).second)
       continue;
 
-    result.addPotentialBinding({type, AllowedBindingKind::Exact,
-                                constraint->getKind(), nullptr,
-                                constraint->getLocator()});
+    result.addPotentialBinding({type, AllowedBindingKind::Exact, constraint});
   }
 
   // If there are no bindings, typeVar may be a hole.
@@ -745,9 +740,8 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) const {
     if (locator->isLastElement<LocatorPathElt::MemberRefBase>())
       result.PotentiallyIncomplete = true;
 
-    result.addPotentialBinding({getASTContext().TheUnresolvedType,
-        AllowedBindingKind::Exact, ConstraintKind::Defaultable, nullptr,
-        typeVar->getImpl().getLocator()});
+    result.addPotentialBinding(
+        PotentialBinding::forHole(getASTContext(), locator));
   }
 
   // Determine if the bindings only constrain the type variable from above with
@@ -918,11 +912,11 @@ bool TypeVarBindingProducer::computeNext() {
 
     // If we have a protocol with a default type, look for alternative
     // types to the default.
-    if (NumTries == 0 && binding.DefaultedProtocol) {
-      auto knownKind = *(binding.DefaultedProtocol->getKnownProtocolKind());
+    if (NumTries == 0 && binding.hasDefaultedLiteralProtocol()) {
+      auto knownKind =
+          *(binding.getDefaultedLiteralProtocol()->getKnownProtocolKind());
       for (auto altType : CS.getAlternativeLiteralTypes(knownKind)) {
-        addNewBinding({altType, BindingKind::Subtypes, binding.BindingSource,
-                       binding.DefaultedProtocol});
+        addNewBinding(binding.withSameSource(altType, BindingKind::Subtypes));
       }
     }
 
@@ -939,10 +933,10 @@ bool TypeVarBindingProducer::computeNext() {
         if (auto otherTypeVar = objTy->getAs<TypeVariableType>()) {
           if (TypeVar->getImpl().canBindToLValue() ==
               otherTypeVar->getImpl().canBindToLValue()) {
-            addNewBinding({objTy, binding.Kind, binding.BindingSource});
+            addNewBinding(binding.withSameSource(objTy, binding.Kind));
           }
         } else {
-          addNewBinding({objTy, binding.Kind, binding.BindingSource});
+          addNewBinding(binding.withSameSource(objTy, binding.Kind));
         }
       }
     }
@@ -953,7 +947,7 @@ bool TypeVarBindingProducer::computeNext() {
     for (auto supertype : enumerateDirectSupertypes(type)) {
       // If we're not allowed to try this binding, skip it.
       if (auto simplifiedSuper = CS.checkTypeOfBinding(TypeVar, supertype))
-        addNewBinding({*simplifiedSuper, binding.Kind, binding.BindingSource});
+        addNewBinding(binding.withType(*simplifiedSuper));
     }
   }
 
@@ -968,12 +962,13 @@ bool TypeVarBindingProducer::computeNext() {
 
 bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
   auto type = Binding.BindingType;
-  auto *locator = TypeVar->getImpl().getLocator();
+  auto *srcLocator = Binding.getLocator();
+  auto *dstLocator = TypeVar->getImpl().getLocator();
 
-  if (Binding.DefaultedProtocol) {
-    type = cs.openUnboundGenericType(type, locator);
+  if (Binding.hasDefaultedLiteralProtocol()) {
+    type = cs.openUnboundGenericType(type, dstLocator);
     type = type->reconstituteSugar(/*recursive=*/false);
-  } else if (Binding.BindingSource == ConstraintKind::ArgumentConversion &&
+  } else if (srcLocator->isLastElement<LocatorPathElt::ApplyArgToParam>() &&
              !type->hasTypeVariable() && cs.isCollectionType(type)) {
     // If the type binding comes from the argument conversion, let's
     // instead of binding collection types directly, try to bind
@@ -984,27 +979,27 @@ bool TypeVariableBinding::attempt(ConstraintSystem &cs) const {
     auto UGT = UnboundGenericType::get(BGT->getDecl(), BGT->getParent(),
                                        BGT->getASTContext());
 
-    type = cs.openUnboundGenericType(UGT, locator);
+    type = cs.openUnboundGenericType(UGT, dstLocator);
     type = type->reconstituteSugar(/*recursive=*/false);
   }
 
-  // FIXME: We want the locator that indicates where the binding came
-  // from.
-  cs.addConstraint(ConstraintKind::Bind, TypeVar, type, locator);
+  cs.addConstraint(ConstraintKind::Bind, TypeVar, type, srcLocator);
 
   // If this was from a defaultable binding note that.
   if (Binding.isDefaultableBinding()) {
-    cs.DefaultedConstraints.push_back(Binding.DefaultableBinding);
-
-    if (locator->isForGenericParameter() && type->isHole()) {
-      // Drop `generic parameter` locator element so that all missing
-      // generic parameters related to the same path can be coalesced later.
-      auto path = locator->getPath();
-      auto genericParam = locator->getGenericParameter();
-      auto *fix = DefaultGenericArgument::create(cs, genericParam,
-          cs.getConstraintLocator(locator->getAnchor(), path.drop_back()));
-      if (cs.recordFix(fix))
-        return true;
+    cs.DefaultedConstraints.push_back(srcLocator);
+
+    if (type->isHole()) {
+      if (auto *GP = TypeVar->getImpl().getGenericParameter()) {
+        auto path = dstLocator->getPath();
+        // Drop `generic parameter` locator element so that all missing
+        // generic parameters related to the same path can be coalesced later.
+        auto *fix = DefaultGenericArgument::create(
+            cs, GP,
+            cs.getConstraintLocator(dstLocator->getAnchor(), path.drop_back()));
+        if (cs.recordFix(fix))
+          return true;
+      }
     }
   }
 
diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp
index cb9804d868c83..56a2bbc21829a 100644
--- a/lib/Sema/CSDiagnostics.cpp
+++ b/lib/Sema/CSDiagnostics.cpp
@@ -897,27 +897,23 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseAsError() {
   if (diagnoseParameterUse())
     return true;
 
-  if (ConvertTo) {
-    emitDiagnostic(anchor->getLoc(), diag::converting_noescape_to_type,
-                   ConvertTo);
-    return true;
+  if (auto *typeVar = getRawFromType()->getAs<TypeVariableType>()) {
+    if (auto *GP = typeVar->getImpl().getGenericParameter()) {
+      emitDiagnostic(anchor->getLoc(), diag::converting_noescape_to_type, GP);
+      return true;
+    }
   }
 
-  auto *loc = getLocator();
-  if (auto gpElt = loc->getLastElementAs<LocatorPathElt::GenericParameter>()) {
-    auto *paramTy = gpElt->getType();
-    emitDiagnostic(anchor->getLoc(), diag::converting_noescape_to_type,
-                  paramTy);
-  } else {
-    emitDiagnostic(anchor->getLoc(), diag::unknown_escaping_use_of_noescape);
-  }
+  emitDiagnostic(anchor->getLoc(), diag::converting_noescape_to_type,
+                 getToType());
   return true;
 }
 
 bool NoEscapeFuncToTypeConversionFailure::diagnoseParameterUse() const {
+  auto convertTo = getToType();
   // If the other side is not a function, we have common case diagnostics
   // which handle function-to-type conversion diagnostics.
-  if (!ConvertTo || !ConvertTo->is<FunctionType>())
+  if (!convertTo->is<FunctionType>())
     return false;
 
   auto *anchor = getAnchor();
@@ -943,7 +939,9 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseParameterUse() const {
                          diag::converting_noespace_param_to_generic_type,
                          PD->getName(), paramInterfaceTy);
 
-          emitDiagnostic(decl, diag::generic_parameters_always_escaping);
+          auto declLoc = decl->getLoc();
+          if (declLoc.isValid())
+            emitDiagnostic(decl, diag::generic_parameters_always_escaping);
         };
 
         // If this is a situation when non-escaping parameter is passed
@@ -2032,6 +2030,9 @@ bool ContextualFailure::diagnoseAsError() {
     return true;
   }
 
+  auto fromType = getFromType();
+  auto toType = getToType();
+
   Diag<Type, Type> diagnostic;
   switch (path.back().getKind()) {
   case ConstraintLocator::ClosureResult: {
@@ -2040,9 +2041,8 @@ bool ContextualFailure::diagnoseAsError() {
         closure->getExplicitResultTypeLoc().getTypeRepr()) {
       auto resultRepr = closure->getExplicitResultTypeLoc().getTypeRepr();
       emitDiagnostic(resultRepr->getStartLoc(),
-                     diag::incorrect_explicit_closure_result, getFromType(),
-                     getToType())
-          .fixItReplace(resultRepr->getSourceRange(), getToType().getString());
+                     diag::incorrect_explicit_closure_result, fromType, toType)
+          .fixItReplace(resultRepr->getSourceRange(), toType.getString());
       return true;
     }
 
@@ -2071,22 +2071,21 @@ bool ContextualFailure::diagnoseAsError() {
       return true;
 
     if (CTP == CTP_ForEachStmt) {
-      if (FromType->isAnyExistentialType()) {
+      if (fromType->isAnyExistentialType()) {
         emitDiagnostic(anchor->getLoc(), diag::type_cannot_conform,
-                       /*isExistentialType=*/true, FromType, ToType);
+                       /*isExistentialType=*/true, fromType, toType);
         return true;
       }
 
       emitDiagnostic(
           anchor->getLoc(),
           diag::foreach_sequence_does_not_conform_to_expected_protocol,
-          FromType, ToType, bool(FromType->getOptionalObjectType()))
+          fromType, toType, bool(fromType->getOptionalObjectType()))
           .highlight(anchor->getSourceRange());
       return true;
     }
 
-    auto contextualType = getToType();
-    if (auto msg = getDiagnosticFor(CTP, contextualType->isExistentialType())) {
+    if (auto msg = getDiagnosticFor(CTP, toType->isExistentialType())) {
       diagnostic = *msg;
       break;
     }
@@ -2102,11 +2101,11 @@ bool ContextualFailure::diagnoseAsError() {
       return false;
 
     auto *choice = overload->choice.getDecl();
-    auto fnType = FromType->getAs<FunctionType>();
+    auto fnType = fromType->getAs<FunctionType>();
     if (!fnType) {
       emitDiagnostic(anchor->getLoc(),
                      diag::expected_result_in_contextual_member,
-                     choice->getFullName(), FromType, ToType);
+                     choice->getFullName(), fromType, toType);
       return true;
     }
 
@@ -2151,7 +2150,8 @@ bool ContextualFailure::diagnoseAsError() {
     return false;
   }
 
-  auto diag = emitDiagnostic(anchor->getLoc(), diagnostic, FromType, ToType);
+  auto diag =
+      emitDiagnostic(anchor->getLoc(), diagnostic, fromType, toType);
   diag.highlight(anchor->getSourceRange());
 
   (void)tryFixIts(diag);
@@ -2357,12 +2357,13 @@ bool ContextualFailure::diagnoseMissingFunctionCall() const {
   if (getLocator()->isLastElement<LocatorPathElt::RValueAdjustment>())
     return false;
 
-  auto *srcFT = FromType->getAs<FunctionType>();
+  auto *srcFT = getFromType()->getAs<FunctionType>();
   if (!srcFT || !srcFT->getParams().empty())
     return false;
 
-  if (ToType->is<AnyFunctionType>() ||
-      !TypeChecker::isConvertibleTo(srcFT->getResult(), ToType, getDC()))
+  auto toType = getToType();
+  if (toType->is<AnyFunctionType>() ||
+      !TypeChecker::isConvertibleTo(srcFT->getResult(), toType, getDC()))
     return false;
 
   auto *anchor = getAnchor();
@@ -2663,7 +2664,10 @@ bool ContextualFailure::tryRawRepresentableFixIts(
 
 bool ContextualFailure::tryIntegerCastFixIts(
     InFlightDiagnostic &diagnostic) const {
-  if (!isIntegerType(FromType) || !isIntegerType(ToType))
+  auto fromType = getFromType();
+  auto toType = getToType();
+
+  if (!isIntegerType(fromType) || !isIntegerType(toType))
     return false;
 
   auto getInnerCastedExpr = [&](Expr *expr) -> Expr * {
@@ -2684,7 +2688,7 @@ bool ContextualFailure::tryIntegerCastFixIts(
   auto *anchor = getAnchor();
   if (Expr *innerE = getInnerCastedExpr(anchor)) {
     Type innerTy = getType(innerE);
-    if (TypeChecker::isConvertibleTo(innerTy, ToType, getDC())) {
+    if (TypeChecker::isConvertibleTo(innerTy, toType, getDC())) {
       // Remove the unnecessary cast.
       diagnostic.fixItRemoveChars(anchor->getLoc(), innerE->getStartLoc())
           .fixItRemove(anchor->getEndLoc());
@@ -2693,7 +2697,7 @@ bool ContextualFailure::tryIntegerCastFixIts(
   }
 
   // Add a wrapping integer cast.
-  std::string convWrapBefore = ToType.getString();
+  std::string convWrapBefore = toType.getString();
   convWrapBefore += "(";
   std::string convWrapAfter = ")";
   SourceRange exprRange = anchor->getSourceRange();
@@ -2715,8 +2719,8 @@ bool ContextualFailure::trySequenceSubsequenceFixIts(
 
   // Substring -> String conversion
   // Wrap in String.init
-  if (FromType->isEqual(Substring)) {
-    if (ToType->isEqual(String)) {
+  if (getFromType()->isEqual(Substring)) {
+    if (getToType()->isEqual(String)) {
       auto *anchor = getAnchor()->getSemanticsProvidingExpr();
       auto range = anchor->getSourceRange();
       diagnostic.fixItInsert(range.Start, "String(");
@@ -2775,10 +2779,11 @@ bool ContextualFailure::tryProtocolConformanceFixIt(
   if (!nominal)
     return false;
 
+  auto fromType = getFromType();
   // We need to get rid of optionals and parens as it's not relevant when
   // printing the diagnostic and the fix-it.
   auto unwrappedToType =
-      ToType->lookThroughAllOptionalTypes()->getWithoutParens();
+      getToType()->lookThroughAllOptionalTypes()->getWithoutParens();
 
   // If the protocol requires a class & we don't have one (maybe the context
   // is a struct), then bail out instead of offering a broken fix-it later on.
@@ -2789,13 +2794,13 @@ bool ContextualFailure::tryProtocolConformanceFixIt(
     requiresClass = layout.requiresClass();
   }
 
-  if (requiresClass && !FromType->is<ClassType>()) {
+  if (requiresClass && !fromType->is<ClassType>()) {
     return false;
   }
 
   // We can only offer a fix-it if we're assigning to a protocol type and
   // the type we're assigning is the same as the innermost type context.
-  bool shouldOfferFixIt = nominal->getSelfTypeInContext()->isEqual(FromType) &&
+  bool shouldOfferFixIt = nominal->getSelfTypeInContext()->isEqual(fromType) &&
                           unwrappedToType->isExistentialType();
   if (!shouldOfferFixIt)
     return false;
@@ -2805,7 +2810,7 @@ bool ContextualFailure::tryProtocolConformanceFixIt(
   // Let's build a list of protocols that the context does not conform to.
   SmallVector<std::string, 8> missingProtoTypeStrings;
   for (auto protocol : layout.getProtocols()) {
-    if (!TypeChecker::conformsToProtocol(FromType, protocol->getDecl(), getDC(),
+    if (!TypeChecker::conformsToProtocol(fromType, protocol->getDecl(), getDC(),
                                          ConformanceCheckFlags::InExpression)) {
       missingProtoTypeStrings.push_back(protocol->getString());
     }
@@ -2833,7 +2838,7 @@ bool ContextualFailure::tryProtocolConformanceFixIt(
   // TODO: Maybe also insert the requirement stubs?
   auto conformanceDiag = emitDiagnostic(
       getAnchor()->getLoc(), diag::assign_protocol_conformance_fix_it,
-      unwrappedToType, nominal->getDescriptiveKind(), FromType);
+      unwrappedToType, nominal->getDescriptiveKind(), fromType);
   if (nominal->getInherited().size() > 0) {
     auto lastInherited = nominal->getInherited().back().getLoc();
     auto lastInheritedEndLoc =
diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h
index 67cc1ddcc342b..e314546d0a0ad 100644
--- a/lib/Sema/CSDiagnostics.h
+++ b/lib/Sema/CSDiagnostics.h
@@ -585,26 +585,6 @@ class LabelingFailure final : public FailureDiagnostic {
   bool diagnoseAsNote() override;
 };
 
-/// Diagnose errors related to converting function type which
-/// isn't explicitly '@escaping' to some other type.
-class NoEscapeFuncToTypeConversionFailure final : public FailureDiagnostic {
-  Type ConvertTo;
-
-public:
-  NoEscapeFuncToTypeConversionFailure(ConstraintSystem &cs,
-                                      ConstraintLocator *locator,
-                                      Type toType = Type())
-      : FailureDiagnostic(cs, locator), ConvertTo(toType) {}
-
-  bool diagnoseAsError() override;
-
-private:
-  /// Emit tailored diagnostics for no-escape parameter conversions e.g.
-  /// passing such parameter as an @escaping argument, or trying to
-  /// assign it to a variable which expects @escaping function.
-  bool diagnoseParameterUse() const;
-};
-
 /// Diagnose failures related to attempting member access on optional base
 /// type without optional chaining or force-unwrapping it first.
 class MemberAccessOnOptionalBaseFailure final : public FailureDiagnostic {
@@ -694,7 +674,7 @@ class AssignmentFailure final : public FailureDiagnostic {
 /// e.g. argument/parameter, closure result, conversions etc.
 class ContextualFailure : public FailureDiagnostic {
   ContextualTypePurpose CTP;
-  Type FromType, ToType;
+  Type RawFromType, RawToType;
 
 public:
   ContextualFailure(ConstraintSystem &cs, Type lhs, Type rhs,
@@ -702,15 +682,18 @@ class ContextualFailure : public FailureDiagnostic {
       : ContextualFailure(cs, cs.getContextualTypePurpose(), lhs, rhs,
                           locator) {}
 
-  ContextualFailure(ConstraintSystem &cs,
-                    ContextualTypePurpose purpose, Type lhs, Type rhs,
-                    ConstraintLocator *locator)
-      : FailureDiagnostic(cs, locator), CTP(purpose),
-        FromType(resolve(lhs)), ToType(resolve(rhs)) {}
+  ContextualFailure(ConstraintSystem &cs, ContextualTypePurpose purpose,
+                    Type lhs, Type rhs, ConstraintLocator *locator)
+      : FailureDiagnostic(cs, locator), CTP(purpose), RawFromType(lhs),
+        RawToType(rhs) {}
+
+  Type getFromType() const { return resolve(RawFromType); }
 
-  Type getFromType() const { return FromType; }
+  Type getToType() const { return resolve(RawToType); }
 
-  Type getToType() const { return ToType; }
+  Type getRawFromType() const { return RawFromType; }
+
+  Type getRawToType() const { return RawToType; }
 
   bool diagnoseAsError() override;
 
@@ -791,7 +774,7 @@ class ContextualFailure : public FailureDiagnostic {
                                             Type contextualType);
 
 private:
-  Type resolve(Type rawType) {
+  Type resolve(Type rawType) const {
     return resolveType(rawType)->getWithoutSpecifierType();
   }
 
@@ -816,6 +799,23 @@ class ContextualFailure : public FailureDiagnostic {
   getDiagnosticFor(ContextualTypePurpose context, bool forProtocol);
 };
 
+/// Diagnose errors related to converting function type which
+/// isn't explicitly '@escaping' to some other type.
+class NoEscapeFuncToTypeConversionFailure final : public ContextualFailure {
+public:
+  NoEscapeFuncToTypeConversionFailure(ConstraintSystem &cs, Type fromType,
+                                      Type toType, ConstraintLocator *locator)
+      : ContextualFailure(cs, fromType, toType, locator) {}
+
+  bool diagnoseAsError() override;
+
+private:
+  /// Emit tailored diagnostics for no-escape parameter conversions e.g.
+  /// passing such parameter as an @escaping argument, or trying to
+  /// assign it to a variable which expects @escaping function.
+  bool diagnoseParameterUse() const;
+};
+
 /// Diagnose failures related to use of the unwrapped optional types,
 /// which require some type of force-unwrap e.g. "!" or "try!".
 class MissingOptionalUnwrapFailure final : public ContextualFailure {
diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp
index f06cc25a28b6f..e038e43eabe07 100644
--- a/lib/Sema/CSFix.cpp
+++ b/lib/Sema/CSFix.cpp
@@ -159,16 +159,16 @@ CoerceToCheckedCast *CoerceToCheckedCast::attempt(ConstraintSystem &cs,
 }
 
 bool MarkExplicitlyEscaping::diagnose(bool asNote) const {
-  NoEscapeFuncToTypeConversionFailure failure(getConstraintSystem(),
-                                              getLocator(), ConvertTo);
+  auto &cs = getConstraintSystem();
+  NoEscapeFuncToTypeConversionFailure failure(cs, getFromType(), getToType(),
+                                              getLocator());
   return failure.diagnose(asNote);
 }
 
 MarkExplicitlyEscaping *
-MarkExplicitlyEscaping::create(ConstraintSystem &cs, ConstraintLocator *locator,
-                               Type convertingTo) {
-  return new (cs.getAllocator())
-      MarkExplicitlyEscaping(cs, locator, convertingTo);
+MarkExplicitlyEscaping::create(ConstraintSystem &cs, Type lhs, Type rhs,
+                               ConstraintLocator *locator) {
+  return new (cs.getAllocator()) MarkExplicitlyEscaping(cs, lhs, rhs, locator);
 }
 
 bool RelabelArguments::diagnose(bool asNote) const {
diff --git a/lib/Sema/CSFix.h b/lib/Sema/CSFix.h
index e31bc01dcff3c..4b739c3a4461a 100644
--- a/lib/Sema/CSFix.h
+++ b/lib/Sema/CSFix.h
@@ -322,27 +322,6 @@ class TreatRValueAsLValue final : public ConstraintFix {
                                      ConstraintLocator *locator);
 };
 
-/// Mark function type as explicitly '@escaping'.
-class MarkExplicitlyEscaping final : public ConstraintFix {
-  /// Sometimes function type has to be marked as '@escaping'
-  /// to be converted to some other generic type.
-  Type ConvertTo;
-
-  MarkExplicitlyEscaping(ConstraintSystem &cs, ConstraintLocator *locator,
-                         Type convertingTo = Type())
-      : ConstraintFix(cs, FixKind::ExplicitlyEscaping, locator),
-        ConvertTo(convertingTo) {}
-
-public:
-  std::string getName() const override { return "add @escaping"; }
-
-  bool diagnose(bool asNote = false) const override;
-
-  static MarkExplicitlyEscaping *create(ConstraintSystem &cs,
-                                        ConstraintLocator *locator,
-                                        Type convertingTo = Type());
-};
-
 /// Arguments have labeling failures - missing/extraneous or incorrect
 /// labels attached to the, fix it by suggesting proper labels.
 class RelabelArguments final
@@ -496,6 +475,22 @@ class ContextualMismatch : public ConstraintFix {
                                     ConstraintLocator *locator);
 };
 
+/// Mark function type as explicitly '@escaping'.
+class MarkExplicitlyEscaping final : public ContextualMismatch {
+  MarkExplicitlyEscaping(ConstraintSystem &cs, Type lhs, Type rhs,
+                         ConstraintLocator *locator)
+      : ContextualMismatch(cs, FixKind::ExplicitlyEscaping, lhs, rhs, locator) {
+  }
+
+public:
+  std::string getName() const override { return "add @escaping"; }
+
+  bool diagnose(bool asNote = false) const override;
+
+  static MarkExplicitlyEscaping *create(ConstraintSystem &cs, Type lhs,
+                                        Type rhs, ConstraintLocator *locator);
+};
+
 /// Introduce a '!' to force an optional unwrap.
 class ForceOptional final : public ContextualMismatch {
   ForceOptional(ConstraintSystem &cs, Type fromType, Type toType,
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index ebe4d6c145eec..60cfaf48ed40a 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -1548,8 +1548,8 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
     if (!shouldAttemptFixes())
       return getTypeMatchFailure(locator);
 
-    auto *fix = MarkExplicitlyEscaping::create(
-        *this, getConstraintLocator(locator), func2);
+    auto *fix = MarkExplicitlyEscaping::create(*this, func1, func2,
+                                               getConstraintLocator(locator));
 
     if (recordFix(fix))
       return getTypeMatchFailure(locator);
@@ -2084,9 +2084,8 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
       return getTypeMatchSuccess();
 
     if (shouldAttemptFixes()) {
-      auto &ctx = getASTContext();
-      auto *fix = MarkExplicitlyEscaping::create(
-          *this, getConstraintLocator(locator), ctx.TheAnyType);
+      auto *fix = MarkExplicitlyEscaping::create(*this, type1, type2,
+                                                 getConstraintLocator(locator));
       if (!recordFix(fix))
         return getTypeMatchSuccess();
     }
@@ -2348,8 +2347,8 @@ ConstraintSystem::matchTypesBindTypeVar(
   // but we still have a non-escaping type, fail.
   if (!typeVar->getImpl().canBindToNoEscape() && type->isNoEscape()) {
     if (shouldAttemptFixes()) {
-      auto *fix = MarkExplicitlyEscaping::create(
-          *this, getConstraintLocator(locator));
+      auto *fix = MarkExplicitlyEscaping::create(*this, typeVar, type,
+                                                 getConstraintLocator(locator));
       if (recordFix(fix))
         return getTypeMatchFailure(locator);
 
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index acf0092439bbf..06542222c4212 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -3288,28 +3288,64 @@ class ConstraintSystem {
     /// The kind of bindings permitted.
     AllowedBindingKind Kind;
 
-    /// The kind of the constraint this binding came from.
-    ConstraintKind BindingSource;
-
-    /// The defaulted protocol associated with this binding.
-    ProtocolDecl *DefaultedProtocol;
-
-    /// If this is a binding that comes from a \c Defaultable constraint,
-    /// the locator of that constraint.
-    ConstraintLocator *DefaultableBinding = nullptr;
+  protected:
+    /// The source of the type information.
+    ///
+    /// Determines whether this binding represents a "hole" in
+    /// constraint system. Such bindings have no originating constraint
+    /// because they are synthetic, they have a locator instead.
+    PointerUnion<Constraint *, ConstraintLocator *> BindingSource;
 
     PotentialBinding(Type type, AllowedBindingKind kind,
-                     ConstraintKind bindingSource,
-                     ProtocolDecl *defaultedProtocol = nullptr,
-                     ConstraintLocator *defaultableBinding = nullptr)
+                     PointerUnion<Constraint *, ConstraintLocator *> source)
+        : BindingType(type->getWithoutParens()), Kind(kind),
+          BindingSource(source) {}
+
+  public:
+    PotentialBinding(Type type, AllowedBindingKind kind, Constraint *source)
         : BindingType(type->getWithoutParens()), Kind(kind),
-          BindingSource(bindingSource), DefaultedProtocol(defaultedProtocol),
-          DefaultableBinding(defaultableBinding) {}
+          BindingSource(source) {}
+
+    bool isDefaultableBinding() const {
+      if (auto *constraint = BindingSource.dyn_cast<Constraint *>())
+        return constraint->getKind() == ConstraintKind::Defaultable;
+      // If binding source is not constraint - it's a hole, which is
+      // a last resort default binding for a type variable.
+      return true;
+    }
+
+    bool hasDefaultedLiteralProtocol() const {
+      return bool(getDefaultedLiteralProtocol());
+    }
+
+    ProtocolDecl *getDefaultedLiteralProtocol() const {
+      auto *constraint = BindingSource.dyn_cast<Constraint *>();
+      if (!constraint)
+        return nullptr;
 
-    bool isDefaultableBinding() const { return DefaultableBinding != nullptr; }
+      return constraint->getKind() == ConstraintKind::LiteralConformsTo
+                 ? constraint->getProtocol()
+                 : nullptr;
+    }
+
+    ConstraintLocator *getLocator() const {
+      if (auto *constraint = BindingSource.dyn_cast<Constraint *>())
+        return constraint->getLocator();
+      return BindingSource.get<ConstraintLocator *>();
+    }
 
     PotentialBinding withType(Type type) const {
-      return {type, Kind, BindingSource, DefaultedProtocol, DefaultableBinding};
+      return {type, Kind, BindingSource};
+    }
+
+    PotentialBinding withSameSource(Type type, AllowedBindingKind kind) const {
+      return {type, kind, BindingSource};
+    }
+
+    static PotentialBinding forHole(ASTContext &ctx,
+                                    ConstraintLocator *locator) {
+      return {ctx.TheUnresolvedType, AllowedBindingKind::Exact,
+              /*source=*/locator};
     }
   };
 
@@ -3464,9 +3500,8 @@ class ConstraintSystem {
                      out << "(supertypes of) ";
                      break;
                    }
-                   if (binding.DefaultedProtocol)
-                     out << "(default from "
-                         << binding.DefaultedProtocol->getName() << ") ";
+                   if (auto *literal = binding.getDefaultedLiteralProtocol())
+                     out << "(default from " << literal->getName() << ") ";
                    out << type.getString(PO);
                  },
                  [&]() { out << "; "; });
@@ -4196,7 +4231,9 @@ class TypeVariableBinding {
 
   bool isDefaultable() const { return Binding.isDefaultableBinding(); }
 
-  bool hasDefaultedProtocol() const { return Binding.DefaultedProtocol; }
+  bool hasDefaultedProtocol() const {
+    return Binding.hasDefaultedLiteralProtocol();
+  }
 
   bool attempt(ConstraintSystem &cs) const;
 
diff --git a/test/Constraints/function.swift b/test/Constraints/function.swift
index 596bf9d52a34f..be6b85bde7f12 100644
--- a/test/Constraints/function.swift
+++ b/test/Constraints/function.swift
@@ -85,7 +85,7 @@ sr590(())
 sr590((1, 2))
 
 // SR-2657: Poor diagnostics when function arguments should be '@escaping'.
-private class SR2657BlockClass<T> { // expected-note 3 {{generic parameters are always considered '@escaping'}}
+private class SR2657BlockClass<T> { // expected-note 4 {{generic parameters are always considered '@escaping'}}
   let f: T
   init(f: T) { self.f = f }
 }
@@ -94,7 +94,7 @@ func takesAny(_: Any) {}
 
 func foo(block: () -> (), other: () -> Int) {
   let _ = SR2657BlockClass(f: block)
-  // expected-error@-1 {{converting non-escaping value to 'T' may allow it to escape}}
+  // expected-error@-1 {{converting non-escaping parameter 'block' to generic parameter 'T' may allow it to escape}}
   let _ = SR2657BlockClass<()->()>(f: block)
   // expected-error@-1 {{converting non-escaping parameter 'block' to generic parameter 'T' may allow it to escape}}
   let _: SR2657BlockClass<()->()> = SR2657BlockClass(f: block)
diff --git a/test/Constraints/suspicious_bit_casts.swift b/test/Constraints/suspicious_bit_casts.swift
index 5e5148d791b4d..baaf382d1230f 100644
--- a/test/Constraints/suspicious_bit_casts.swift
+++ b/test/Constraints/suspicious_bit_casts.swift
@@ -2,7 +2,7 @@
 
 func escapeByBitCast(f: () -> ()) -> () -> () {
   return unsafeBitCast(f, to: (() -> ()).self)
-  // expected-error@-1 {{converting non-escaping value to 'T' may allow it to escape}}
+  // expected-error@-1 {{converting non-escaping parameter 'f' to generic parameter 'T' may allow it to escape}}
 }
 
 func changeFnRep(f: @escaping () -> ()) -> @convention(block) () -> () {
diff --git a/test/Sema/type_join.swift b/test/Sema/type_join.swift
index 96d9724029f9e..ad6d2b78cdc27 100644
--- a/test/Sema/type_join.swift
+++ b/test/Sema/type_join.swift
@@ -31,7 +31,7 @@ protocol FakeExpressibleByFloatLiteral {}
 protocol FakeBinaryFloatingPoint : FakeFloatingPoint, FakeExpressibleByFloatLiteral {}
 
 func expectEqualType<T>(_: T.Type, _: T.Type) {}
-func commonSupertype<T>(_: T, _: T) -> T {}
+func commonSupertype<T>(_: T, _: T) -> T {} // expected-note 2 {{generic parameters are always considered '@escaping'}}
 
 expectEqualType(Builtin.type_join(Int.self, Int.self), Int.self)
 expectEqualType(Builtin.type_join_meta(D.self, C.self), C.self)
@@ -90,9 +90,9 @@ func joinFunctions(
 ) {
   _ = commonSupertype(escaping, escaping)
   _ = commonSupertype(nonescaping, escaping)
-  // expected-error@-1 {{converting non-escaping value to 'T' may allow it to escape}}
+  // expected-error@-1 {{converting non-escaping parameter 'nonescaping' to generic parameter 'T' may allow it to escape}}
   _ = commonSupertype(escaping, nonescaping)
-  // expected-error@-1 {{converting non-escaping value to 'T' may allow it to escape}}
+  // expected-error@-1 {{converting non-escaping parameter 'nonescaping' to generic parameter 'T' may allow it to escape}}
   let x: Int = 1
   // FIXME: We emit these diagnostics here because we refuse to allow
   //        Any to be inferred for the generic type. That's pretty
diff --git a/test/attr/attr_autoclosure.swift b/test/attr/attr_autoclosure.swift
index 10bb792144eda..4c136c330414e 100644
--- a/test/attr/attr_autoclosure.swift
+++ b/test/attr/attr_autoclosure.swift
@@ -183,10 +183,10 @@ func passAutoClosureToEnumCase(_ fn: @autoclosure () -> Int) {
 func rdar_20591571() {
   func foo(_ g: @autoclosure () -> Int) {
     typealias G = ()->Int
-    let _ = unsafeBitCast(g, to: G.self) // expected-error {{converting non-escaping value to 'T' may allow it to escape}}
+    let _ = unsafeBitCast(g, to: G.self) // expected-error {{converting non-escaping parameter 'g' to generic parameter 'T' may allow it to escape}}
   }
 
-  func id<T>(_: T) -> T {}
+  func id<T>(_: T) -> T {} // expected-note {{eneric parameters are always considered '@escaping'}}
   func same<T>(_: T, _: T) {}
   // expected-note@-1 2 {{generic parameters are always considered '@escaping'}}
 
@@ -198,7 +198,7 @@ func rdar_20591571() {
     var _ = efn
     let _ = efn
 
-    _ = id(fn)          // expected-error {{converting non-escaping value to 'T' may allow it to escape}}
+    _ = id(fn)          // expected-error {{converting non-escaping parameter 'fn' to generic parameter 'T' may allow it to escape}}
     _ = same(fn, { 3 }) // expected-error {{converting non-escaping parameter 'fn' to generic parameter 'T' may allow it to escape}}
     _ = same({ 3 }, fn) // expected-error {{converting non-escaping parameter 'fn' to generic parameter 'T' may allow it to escape}}
 
@@ -251,7 +251,7 @@ func overloaded_autoclj(_: @autoclosure () -> Int) {}
 
 func autoclosure_param_returning_func_type() {
   func foo(_ fn: @autoclosure () -> (() -> Int)) {}
-  func generic_foo<T>(_ fn: @autoclosure () -> T) {}
+  func generic_foo<T>(_ fn: @autoclosure () -> T) {} // expected-note {{generic parameters are always considered '@escaping'}}
 
   func bar_1(_ fn: @autoclosure @escaping () -> Int) { foo(fn) } // Ok
   func bar_2(_ fn: @autoclosure () -> Int) { foo(fn) } // expected-note {{parameter 'fn' is implicitly non-escaping}}
@@ -259,7 +259,7 @@ func autoclosure_param_returning_func_type() {
   func baz_1(_ fn: @autoclosure @escaping () -> Int) { generic_foo(fn) }   // Ok (T is inferred as () -> Int)
   func baz_2(_ fn: @autoclosure @escaping () -> Int) { generic_foo(fn()) } // Ok (T is inferred as Int)
   func baz_3(_ fn: @autoclosure () -> Int) { generic_foo(fn) } // Fails because fn is not marked as @escaping
-  // expected-error@-1 {{converting non-escaping value to 'T' may allow it to escape}}
+  // expected-error@-1 {{converting non-escaping parameter 'fn' to generic parameter 'T' may allow it to escape}}
 
   // Let's make sure using `fn` as value works fine in presence of overloading
   func biz_1(_ fn: @autoclosure @escaping () -> Int) { overloaded_autoclj(fn) }   // Ok
diff --git a/test/attr/attr_noescape.swift b/test/attr/attr_noescape.swift
index d5244fc324dcd..d22bccde0f388 100644
--- a/test/attr/attr_noescape.swift
+++ b/test/attr/attr_noescape.swift
@@ -11,7 +11,7 @@ func takesGenericClosure<T>(_ a : Int, _ fn : @noescape () -> T) {} // expected-
 
 var globalAny: Any = 0
 
-func assignToGlobal<T>(_ t: T) {
+func assignToGlobal<T>(_ t: T) { // expected-note {{generic parameters are always considered '@escaping'}}
   globalAny = t
 }
 
@@ -23,7 +23,7 @@ func takesVariadic(_ fns: () -> Int...) {
   doesEscape(fns[0]) // Okay - variadic-of-function parameters are escaping
 }
 
-func takesNoEscapeClosure(_ fn : () -> Int) {
+func takesNoEscapeClosure(_ fn : () -> Int) { // expected-note 2 {{parameter 'fn' is implicitly non-escaping}} {{34-34=@escaping }}
   // expected-note@-1 5{{parameter 'fn' is implicitly non-escaping}} {{34-34=@escaping }}
   takesNoEscapeClosure { 4 }  // ok
 
@@ -36,14 +36,14 @@ func takesNoEscapeClosure(_ fn : () -> Int) {
   takesGenericClosure(4, fn)       // ok
   takesGenericClosure(4) { fn() }  // ok.
 
-  _ = [fn] // expected-error {{converting non-escaping value to 'Element' may allow it to escape}}
+  _ = [fn] // expected-error {{using non-escaping parameter 'fn' in a context expecting an @escaping closure}}
   _ = [doesEscape(fn)] // expected-error {{passing non-escaping parameter 'fn' to function expecting an @escaping closure}}
-  _ = [1 : fn] // expected-error {{converting non-escaping value to 'Value' may allow it to escape}}
+  _ = [1 : fn] // expected-error {{using non-escaping parameter 'fn' in a context expecting an @escaping closure}}
   _ = [1 : doesEscape(fn)] // expected-error {{passing non-escaping parameter 'fn' to function expecting an @escaping closure}}
   _ = "\(doesEscape(fn))" // expected-error {{passing non-escaping parameter 'fn' to function expecting an @escaping closure}}
   _ = "\(takesArray([fn]))" // expected-error {{using non-escaping parameter 'fn' in a context expecting an @escaping closure}}
 
-  assignToGlobal(fn) // expected-error {{converting non-escaping value to 'T' may allow it to escape}}
+  assignToGlobal(fn) // expected-error {{converting non-escaping parameter 'fn' to generic parameter 'T' may allow it to escape}}
   assignToGlobal((fn, fn)) // expected-error {{converting non-escaping value to 'T' may allow it to escape}}
 }
 
diff --git a/test/expr/primary/keypath/keypath-objc.swift b/test/expr/primary/keypath/keypath-objc.swift
index 27f638daa35b0..e8a5988f02bc8 100644
--- a/test/expr/primary/keypath/keypath-objc.swift
+++ b/test/expr/primary/keypath/keypath-objc.swift
@@ -160,7 +160,7 @@ class SR_10146_3 {
   }
 
   func doNotCrash_1(_ obj: AnyObject, _ kp: KeyPath<AnyObject, Int>) {
-    let _ = obj[keyPath: \.abc] // expected-error 2{{the root type of a Swift key path cannot be 'AnyObject'}}
+    let _ = obj[keyPath: \.abc] // expected-error {{the root type of a Swift key path cannot be 'AnyObject'}}
     let _ = obj[keyPath: kp] // expected-error {{the root type of a Swift key path cannot be 'AnyObject'}}
   }
 }