Skip to content

Commit

Permalink
Suggest dereferencing on assignment to mutable borrow
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed May 22, 2019
1 parent 37ff5d3 commit 1e3302d
Show file tree
Hide file tree
Showing 3 changed files with 50 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
5 changes: 5 additions & 0 deletions src/test/ui/suggestions/mut-ref-reassignment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn change_opt(opt: &mut Option<String>){
opt = None //~ ERROR mismatched types
}

fn main() {}
16 changes: 16 additions & 0 deletions src/test/ui/suggestions/mut-ref-reassignment.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
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: aborting due to previous error

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

0 comments on commit 1e3302d

Please sign in to comment.