mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Diagnostics] Correctly diagnose situations when immutable value is passed to inout parameter
Currently the note is going to point to the "callee" but that is
incorrect when the failure is related to an argument of a call.
Detect this situation in `RValueTreatedAsLValueFailure::diagnoseAsNote`
and produce a correct note.
Resolves: rdar://150689994
(cherry picked from commit 6bbc101a98)
This commit is contained in:
@@ -5136,6 +5136,9 @@ ERROR(assignment_bang_has_immutable_subcomponent,none,
|
||||
NOTE(candidate_is_not_assignable,none,
|
||||
"candidate is not assignable: %kind0",
|
||||
(const ValueDecl *))
|
||||
NOTE(candidate_expects_inout_argument,none,
|
||||
"candidate expects in-out value for parameter #%0 but argument is immutable",
|
||||
(unsigned))
|
||||
|
||||
NOTE(change_to_mutating,none,
|
||||
"mark %select{method|%1}0 'mutating' to make 'self' mutable",
|
||||
|
||||
@@ -2049,11 +2049,24 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() {
|
||||
}
|
||||
|
||||
bool RValueTreatedAsLValueFailure::diagnoseAsNote() {
|
||||
auto overload = getCalleeOverloadChoiceIfAvailable(getLocator());
|
||||
auto *locator = getLocator();
|
||||
|
||||
auto overload = getCalleeOverloadChoiceIfAvailable(locator);
|
||||
if (!(overload && overload->choice.isDecl()))
|
||||
return false;
|
||||
|
||||
auto *decl = overload->choice.getDecl();
|
||||
|
||||
if (locator->isLastElement<LocatorPathElt::ArgumentAttribute>()) {
|
||||
auto argConv = locator->findLast<LocatorPathElt::ApplyArgToParam>();
|
||||
if (!argConv)
|
||||
return false;
|
||||
|
||||
emitDiagnosticAt(decl, diag::candidate_expects_inout_argument,
|
||||
argConv->getParamIdx() + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
emitDiagnosticAt(decl, diag::candidate_is_not_assignable, decl);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -349,3 +349,31 @@ do {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
struct S {
|
||||
let x: Int
|
||||
var y: Int
|
||||
}
|
||||
|
||||
func overloaded(_: String) {}
|
||||
// expected-note@-1 3 {{candidate expects value of type 'String' for parameter #1 (got 'Int')}}
|
||||
func overloaded(_: inout Int) {}
|
||||
// expected-note@-1 3 {{candidate expects in-out value for parameter #1 but argument is immutable}}
|
||||
|
||||
func testImmutable(s: S) {
|
||||
overloaded(s.x) // expected-error {{no exact matches in call to local function 'overloaded'}}
|
||||
}
|
||||
|
||||
func testMutable(s: inout S) {
|
||||
overloaded(s.x) // expected-error {{no exact matches in call to local function 'overloaded'}}
|
||||
}
|
||||
|
||||
func testImmutableBase(s: S) {
|
||||
overloaded(s.y) // expected-error {{no exact matches in call to local function 'overloaded'}}
|
||||
}
|
||||
|
||||
func testMissingAddressOf(s: inout S) {
|
||||
overloaded(s.y) // expected-error {{passing value of type 'Int' to an inout parameter requires explicit '&'}}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user