Skip to content

Commit

Permalink
Rollup merge of rust-lang#61054 - estebank:mut-ref-reassign, r=zackmd…
Browse files Browse the repository at this point in the history
…avis

Suggest dereferencing on assignment to mutable borrow

Fix rust-lang#33570
  • Loading branch information
Centril authored May 23, 2019
2 parents e0e9c86 + 7fbbcfa commit b9459e7
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 5 deletions.
34 changes: 29 additions & 5 deletions src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,11 +306,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
/// In addition of this check, it also checks between references mutability state. If the
/// expected is mutable but the provided isn't, maybe we could just say "Hey, try with
/// `&mut`!".
pub fn check_ref(&self,
expr: &hir::Expr,
checked_ty: Ty<'tcx>,
expected: Ty<'tcx>)
-> Option<(Span, &'static str, String)> {
pub fn check_ref(
&self,
expr: &hir::Expr,
checked_ty: Ty<'tcx>,
expected: Ty<'tcx>,
) -> Option<(Span, &'static str, String)> {
let cm = self.sess().source_map();
let sp = expr.span;
if !cm.span_to_filename(sp).is_real() {
Expand Down Expand Up @@ -397,6 +398,29 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} else {
String::new()
};
if let Some(hir::Node::Expr(hir::Expr {
node: hir::ExprKind::Assign(left_expr, _),
..
})) = self.tcx.hir().find_by_hir_id(
self.tcx.hir().get_parent_node_by_hir_id(expr.hir_id),
) {
if mutability == hir::Mutability::MutMutable {
// Found the following case:
// fn foo(opt: &mut Option<String>){ opt = None }
// --- ^^^^
// | |
// consider dereferencing here: `*opt` |
// expected mutable reference, found enum `Option`
if let Ok(src) = cm.span_to_snippet(left_expr.span) {
return Some((
left_expr.span,
"consider dereferencing here to assign to the mutable \
borrowed piece of memory",
format!("*{}", src),
));
}
}
}
return Some(match mutability {
hir::Mutability::MutMutable => (
sp,
Expand Down
17 changes: 17 additions & 0 deletions src/test/ui/suggestions/mut-ref-reassignment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
fn suggestion(opt: &mut Option<String>) {
opt = None; //~ ERROR mismatched types
}

fn no_suggestion(opt: &mut Result<String, ()>) {
opt = None //~ ERROR mismatched types
}

fn suggestion2(opt: &mut Option<String>) {
opt = Some(String::new())//~ ERROR mismatched types
}

fn no_suggestion2(opt: &mut Option<String>) {
opt = Some(42)//~ ERROR mismatched types
}

fn main() {}
47 changes: 47 additions & 0 deletions src/test/ui/suggestions/mut-ref-reassignment.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
error[E0308]: mismatched types
--> $DIR/mut-ref-reassignment.rs:2:11
|
LL | opt = None;
| ^^^^ expected mutable reference, found enum `std::option::Option`
|
= note: expected type `&mut std::option::Option<std::string::String>`
found type `std::option::Option<_>`
help: consider dereferencing here to assign to the mutable borrowed piece of memory
|
LL | *opt = None;
| ^^^^

error[E0308]: mismatched types
--> $DIR/mut-ref-reassignment.rs:6:11
|
LL | opt = None
| ^^^^ expected mutable reference, found enum `std::option::Option`
|
= note: expected type `&mut std::result::Result<std::string::String, ()>`
found type `std::option::Option<_>`

error[E0308]: mismatched types
--> $DIR/mut-ref-reassignment.rs:10:11
|
LL | opt = Some(String::new())
| ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `std::option::Option`
|
= note: expected type `&mut std::option::Option<std::string::String>`
found type `std::option::Option<std::string::String>`
help: consider dereferencing here to assign to the mutable borrowed piece of memory
|
LL | *opt = Some(String::new())
| ^^^^

error[E0308]: mismatched types
--> $DIR/mut-ref-reassignment.rs:14:11
|
LL | opt = Some(42)
| ^^^^^^^^ expected mutable reference, found enum `std::option::Option`
|
= note: expected type `&mut std::option::Option<std::string::String>`
found type `std::option::Option<{integer}>`

error: aborting due to 4 previous errors

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

0 comments on commit b9459e7

Please sign in to comment.