Skip to content

Commit f12e24e

Browse files
committed
[Diagnostics] Skip overloaded locations where all solutions have the same type
If there are multiple overloads, let's skip locations that produce the same type across all of the solutions, such location is most likely a consequence of ambiguity and not its source. Resolves: rdar://109245375
1 parent 84b212c commit f12e24e

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

lib/Sema/ConstraintSystem.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -5308,6 +5308,14 @@ static unsigned countDistinctOverloads(ArrayRef<OverloadChoice> choices) {
53085308
return uniqueChoices.size();
53095309
}
53105310

5311+
static Type getOverloadChoiceType(ConstraintLocator *overloadLoc,
5312+
const Solution &solution) {
5313+
auto selectedOverload = solution.overloadChoices.find(overloadLoc);
5314+
if (selectedOverload == solution.overloadChoices.end())
5315+
return Type();
5316+
return solution.simplifyType(selectedOverload->second.adjustedOpenedType);
5317+
}
5318+
53115319
/// Determine the name of the overload in a set of overload choices.
53125320
static DeclName getOverloadChoiceName(ArrayRef<OverloadChoice> choices) {
53135321
DeclName name;
@@ -5387,6 +5395,25 @@ bool ConstraintSystem::diagnoseAmbiguity(ArrayRef<Solution> solutions) {
53875395
auto &overload = diff.overloads[i];
53885396
auto *locator = overload.locator;
53895397

5398+
// If there is only one overload difference, it's the best.
5399+
if (n == 1) {
5400+
bestOverload = i;
5401+
break;
5402+
}
5403+
5404+
// If there are multiple overload sets involved, let's pick the
5405+
// one that has choices with different types, because that is
5406+
// most likely the source of ambiguity.
5407+
{
5408+
auto overloadTy = getOverloadChoiceType(locator, solutions.front());
5409+
if (std::all_of(solutions.begin() + 1, solutions.end(),
5410+
[&](const Solution &solution) {
5411+
return overloadTy->isEqual(
5412+
getOverloadChoiceType(locator, solution));
5413+
}))
5414+
continue;
5415+
}
5416+
53905417
ASTNode anchor;
53915418

53925419
// Simplification of member locator would produce a base expression,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// RUN: %target-typecheck-verify-swift -swift-version 5 -disable-availability-checking
2+
3+
protocol View {
4+
}
5+
6+
extension View {
7+
func title<S>(_ title: S) -> some View where S : StringProtocol {
8+
EmptyView()
9+
}
10+
11+
func title(_ titleKey: LocalizedString) -> some View {
12+
EmptyView()
13+
}
14+
}
15+
16+
extension View {
17+
func background<T: ShapeStyle>(_: T) -> some View {
18+
EmptyView()
19+
}
20+
}
21+
22+
struct EmptyView : View {}
23+
24+
struct Text : View {
25+
init(_: String) {}
26+
}
27+
28+
protocol ShapeStyle {
29+
}
30+
31+
struct AnyShapeStyle : ShapeStyle {}
32+
struct AnyGradient : ShapeStyle {}
33+
34+
struct LocalizedString : ExpressibleByStringLiteral, ExpressibleByExtendedGraphemeClusterLiteral {
35+
init(extendedGraphemeClusterLiteral value: String) {}
36+
init(stringLiteral: String) {}
37+
}
38+
39+
func test() {
40+
func __findValue(_: String, fallback: LocalizedString) -> LocalizedString { fatalError() }
41+
func __findValue<T: ExpressibleByStringLiteral>(_: String, fallback: T) -> T { fatalError() }
42+
func __findValue<T: ExpressibleByExtendedGraphemeClusterLiteral>(_: String, fallback: T) -> T { fatalError() }
43+
44+
func ambiguitySource() -> AnyShapeStyle { fatalError() } // expected-note {{found this candidate}}
45+
func ambiguitySource() -> AnyGradient { fatalError() } // expected-note {{found this candidate}}
46+
47+
Text("Test")
48+
.title(__findValue("someKey", fallback: "<unknown>"))
49+
.background(ambiguitySource()) // expected-error {{ambiguous use of 'ambiguitySource()'}}
50+
}

0 commit comments

Comments
 (0)