diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index ea05b94ee1999..f0090d1b4230a 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -5302,12 +5302,18 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes(
 /// provided set.
 static unsigned countDistinctOverloads(ArrayRef<OverloadChoice> choices) {
   llvm::SmallPtrSet<void *, 4> uniqueChoices;
-  unsigned result = 0;
   for (auto choice : choices) {
-    if (uniqueChoices.insert(choice.getOpaqueChoiceSimple()).second)
-      ++result;
+    uniqueChoices.insert(choice.getOpaqueChoiceSimple());
   }
-  return result;
+  return uniqueChoices.size();
+}
+
+static Type getOverloadChoiceType(ConstraintLocator *overloadLoc,
+                                  const Solution &solution) {
+  auto selectedOverload = solution.overloadChoices.find(overloadLoc);
+  if (selectedOverload == solution.overloadChoices.end())
+    return Type();
+  return solution.simplifyType(selectedOverload->second.adjustedOpenedType);
 }
 
 /// Determine the name of the overload in a set of overload choices.
@@ -5389,6 +5395,25 @@ bool ConstraintSystem::diagnoseAmbiguity(ArrayRef<Solution> solutions) {
     auto &overload = diff.overloads[i];
     auto *locator = overload.locator;
 
+    // If there is only one overload difference, it's the best.
+    if (n == 1) {
+      bestOverload = i;
+      break;
+    }
+
+    // If there are multiple overload sets involved, let's pick the
+    // one that has choices with different types, because that is
+    // most likely the source of ambiguity.
+    {
+      auto overloadTy = getOverloadChoiceType(locator, solutions.front());
+      if (std::all_of(solutions.begin() + 1, solutions.end(),
+                      [&](const Solution &solution) {
+                        return overloadTy->isEqual(
+                          getOverloadChoiceType(locator, solution));
+                      }))
+        continue;
+    }
+
     ASTNode anchor;
 
     // Simplification of member locator would produce a base expression,
diff --git a/test/Constraints/ambiguity_diagnostics.swift b/test/Constraints/ambiguity_diagnostics.swift
new file mode 100644
index 0000000000000..b8d991529bc0e
--- /dev/null
+++ b/test/Constraints/ambiguity_diagnostics.swift
@@ -0,0 +1,50 @@
+// RUN: %target-typecheck-verify-swift -swift-version 5 -disable-availability-checking
+
+protocol View {
+}
+
+extension View {
+  func title<S>(_ title: S) -> some View where S : StringProtocol {
+    EmptyView()
+  }
+
+  func title(_ titleKey: LocalizedString) -> some View {
+    EmptyView()
+  }
+}
+
+extension View {
+  func background<T: ShapeStyle>(_: T) -> some View {
+    EmptyView()
+  }
+}
+
+struct EmptyView : View {}
+
+struct Text : View {
+  init(_: String) {}
+}
+
+protocol ShapeStyle {
+}
+
+struct AnyShapeStyle : ShapeStyle {}
+struct AnyGradient : ShapeStyle {}
+
+struct LocalizedString : ExpressibleByStringLiteral, ExpressibleByExtendedGraphemeClusterLiteral {
+  init(extendedGraphemeClusterLiteral value: String) {}
+  init(stringLiteral: String) {}
+}
+
+func test() {
+  func __findValue(_: String, fallback: LocalizedString) -> LocalizedString { fatalError() }
+  func __findValue<T: ExpressibleByStringLiteral>(_: String, fallback: T) -> T { fatalError() }
+  func __findValue<T: ExpressibleByExtendedGraphemeClusterLiteral>(_: String, fallback: T) -> T { fatalError() }
+
+  func ambiguitySource() -> AnyShapeStyle { fatalError() } // expected-note {{found this candidate}}
+  func ambiguitySource() -> AnyGradient { fatalError() }   // expected-note {{found this candidate}}
+
+  Text("Test")
+    .title(__findValue("someKey", fallback: "<unknown>"))
+    .background(ambiguitySource()) // expected-error {{ambiguous use of 'ambiguitySource()'}}
+}