Skip to content

Commit d23b938

Browse files
committed
[Diagnostics] Implement IgnoreAssignmentDestinationType::diagnoseForAmbiguity
For cases like this: ```swift struct X {} struct Y {} func overloaded<T>(_ value: T) -> T { value } func overloaded<T>(_ value: T) -> Int { 0 } func test(x: inout X, y: Y) { x = overloaded(y) } ``` Solver would record a `IgnoreAssignmentDestinationType` fix per overload, `diagnoseForAmbiguity` could be used to properly diagnose ambiguity cases like that.
1 parent b407f7c commit d23b938

File tree

4 files changed

+44
-5
lines changed

4 files changed

+44
-5
lines changed

lib/Sema/CSFix.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,43 @@ bool IgnoreAssignmentDestinationType::diagnose(const Solution &solution,
11111111
return failure.diagnose(asNote);
11121112
}
11131113

1114+
bool IgnoreAssignmentDestinationType::diagnoseForAmbiguity(
1115+
CommonFixesArray commonFixes) const {
1116+
auto &cs = getConstraintSystem();
1117+
1118+
// If all of the types are the same let's try to diagnose
1119+
// this as if there is no ambiguity.
1120+
if (ContextualMismatch::diagnoseForAmbiguity(commonFixes))
1121+
return true;
1122+
1123+
auto *commonLocator = getLocator();
1124+
auto *assignment = castToExpr<AssignExpr>(commonLocator->getAnchor());
1125+
1126+
auto &solution = *commonFixes.front().first;
1127+
auto *calleeLocator = solution.getCalleeLocator(
1128+
solution.getConstraintLocator(assignment->getSrc()));
1129+
auto overload = solution.getOverloadChoiceIfAvailable(calleeLocator);
1130+
if (!overload)
1131+
return false;
1132+
1133+
auto memberName = overload->choice.getName().getBaseName();
1134+
auto destType = solution.getType(assignment->getDest());
1135+
1136+
auto &DE = cs.getASTContext().Diags;
1137+
// TODO(diagnostics): It might be good to add a tailored diagnostic
1138+
// for cases like this instead of using "contextual" one.
1139+
DE.diagnose(assignment->getSrc()->getLoc(),
1140+
diag::no_candidates_match_result_type,
1141+
memberName.userFacingName(),
1142+
solution.simplifyType(destType)->getRValueType());
1143+
1144+
for (auto &entry : commonFixes) {
1145+
entry.second->diagnose(*entry.first, /*asNote=*/true);
1146+
}
1147+
1148+
return true;
1149+
}
1150+
11141151
IgnoreAssignmentDestinationType *
11151152
IgnoreAssignmentDestinationType::create(ConstraintSystem &cs, Type sourceTy,
11161153
Type destTy,

lib/Sema/CSFix.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,6 +1550,8 @@ class IgnoreAssignmentDestinationType final : public ContextualMismatch {
15501550

15511551
bool diagnose(const Solution &solution, bool asNote = false) const override;
15521552

1553+
bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override;
1554+
15531555
static IgnoreAssignmentDestinationType *create(ConstraintSystem &cs,
15541556
Type sourceTy, Type destTy,
15551557
ConstraintLocator *locator);

test/Generics/deduction.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func useIdentity(_ x: Int, y: Float, i32: Int32) {
2525
// Deduction where the result type and input type can get different results
2626
var xx : X, yy : Y
2727
xx = identity(yy) // expected-error{{cannot assign value of type 'Y' to type 'X'}}
28-
xx = identity2(yy) // expected-error{{no exact matches in call to global function 'identity2'}}
28+
xx = identity2(yy) // expected-error{{no 'identity2' candidates produce the expected contextual result type 'X'}}
2929
}
3030

3131
func twoIdentical<T>(_ x: T, _ y: T) -> T {}
@@ -89,7 +89,7 @@ func testReturnTuple(_ x: Int, y: Float) {
8989
var _ : (Float, Float) = returnTuple(y)
9090

9191
// <rdar://problem/22333090> QoI: Propagate contextual information in a call to operands
92-
var _ : (Int, Float) = returnTuple(y) // expected-error{{cannot convert value of type 'Float' to expected argument type 'Int'}}
92+
var _ : (Int, Float) = returnTuple(y) // expected-error{{conflicting arguments to generic parameter 'T' ('Float' vs. 'Int')}}
9393
}
9494

9595

test/ModuleInterface/Inputs/opaque-result-types-client.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func someTypeIsTheSame() {
2020
a = foo("") // expected-error{{cannot assign value of type 'some Foo' (result of 'foo') to type 'some Foo' (result of 'foo')}}
2121

2222
var b = foo("")
23-
b = foo(0) // expected-error{{cannot assign value of type 'some Foo' (result of 'foo') to type 'some Foo' (result of 'foo')}}
23+
b = foo(0) // expected-error{{no 'foo' candidates produce the expected contextual result type 'some Foo'}}
2424
b = foo("")
2525

2626
var c = foo(MyFoo())
@@ -33,7 +33,7 @@ func someTypeIsTheSame() {
3333

3434
var d = barInt.foo(0)
3535
d = barInt.foo(0)
36-
d = barString.foo(0) // expected-error{{cannot assign}}
36+
d = barString.foo(0) // expected-error{{no 'foo' candidates produce the expected contextual result type 'some Foo'}}
3737
d = getAssocType(barInt)
3838
d = getAssocType(barString) // expected-error{{cannot assign}}
3939

@@ -50,7 +50,7 @@ func someTypeIsTheSame() {
5050
d3 = getAssocSubscriptType(barString) // expected-error{{cannot assign}}
5151

5252
var e = barString.foo(0)
53-
e = barInt.foo(0) // expected-error{{cannot assign}}
53+
e = barInt.foo(0) // expected-error{{no 'foo' candidates produce the expected contextual result type 'some Foo'}}
5454
e = barString.foo(0)
5555
e = getAssocType(barInt) // expected-error{{cannot assign}}
5656
e = getAssocType(barString)

0 commit comments

Comments
 (0)