Skip to content

Commit

Permalink
[borrowck] Fix help on mutating &self in async fns
Browse files Browse the repository at this point in the history
Previously, when rustc was provided an async function that tried to
mutate through a shared reference to an implicit self (as shown in the
ui test), rustc would suggest modifying the parameter signature
to `&mut` + the fully qualified name of the ty (in the case of the repro
`S`). If a user modified their code to match the suggestion, the
compiler would not accept it.

This commit modifies the suggestion so that when rustc is provided the
ui test that is also attached in this commit, it suggests (correctly)
`&mut self`. We try to be careful about distinguishing between implicit
and explicit self annotations, since the latter seem to be handled
correctly already.

Fixes #93093
  • Loading branch information
alyssaverkade committed Jan 23, 2022
1 parent ecf7299 commit b885700
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 6 deletions.
32 changes: 26 additions & 6 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,12 +488,32 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// don't create labels for compiler-generated spans
Some(_) => None,
None => {
let (span, suggestion) = suggest_ampmut(
self.infcx.tcx,
local_decl,
opt_assignment_rhs_span,
*opt_ty_info,
);
let (span, suggestion) = if name != kw::SelfLower {
suggest_ampmut(
self.infcx.tcx,
local_decl,
opt_assignment_rhs_span,
*opt_ty_info,
)
} else {
match local_decl.local_info.as_deref() {
Some(LocalInfo::User(ClearCrossCrate::Set(
mir::BindingForm::Var(mir::VarBindingForm {
opt_ty_info: None,
..
}),
))) => {
suggest_ampmut_self(self.infcx.tcx, local_decl)
}
// explicit self (eg `self: &'a Self`)
_ => suggest_ampmut(
self.infcx.tcx,
local_decl,
opt_assignment_rhs_span,
*opt_ty_info,
),
}
};
Some((true, span, suggestion))
}
}
Expand Down
14 changes: 14 additions & 0 deletions src/test/ui/borrowck/issue-93093.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// edition:2018
struct S {
foo: usize,
}
impl S {
async fn bar(&self) { //~ HELP consider changing this to be a mutable reference
//~| SUGGESTION &mut self
self.foo += 1; //~ ERROR cannot assign to `self.foo`, which is behind a `&` reference [E0594]
}
}

fn main() {
S { foo: 1 }.bar();
}
12 changes: 12 additions & 0 deletions src/test/ui/borrowck/issue-93093.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0594]: cannot assign to `self.foo`, which is behind a `&` reference
--> $DIR/issue-93093.rs:8:9
|
LL | async fn bar(&self) {
| ----- help: consider changing this to be a mutable reference: `&mut self`
LL |
LL | self.foo += 1;
| ^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written

error: aborting due to previous error

For more information about this error, try `rustc --explain E0594`.

0 comments on commit b885700

Please sign in to comment.