Skip to content

Commit 1e3302d

Browse files
committed
Suggest dereferencing on assignment to mutable borrow
1 parent 37ff5d3 commit 1e3302d

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

src/librustc_typeck/check/demand.rs

+29-5
Original file line numberDiff line numberDiff line change
@@ -306,11 +306,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
306306
/// In addition of this check, it also checks between references mutability state. If the
307307
/// expected is mutable but the provided isn't, maybe we could just say "Hey, try with
308308
/// `&mut`!".
309-
pub fn check_ref(&self,
310-
expr: &hir::Expr,
311-
checked_ty: Ty<'tcx>,
312-
expected: Ty<'tcx>)
313-
-> Option<(Span, &'static str, String)> {
309+
pub fn check_ref(
310+
&self,
311+
expr: &hir::Expr,
312+
checked_ty: Ty<'tcx>,
313+
expected: Ty<'tcx>,
314+
) -> Option<(Span, &'static str, String)> {
314315
let cm = self.sess().source_map();
315316
let sp = expr.span;
316317
if !cm.span_to_filename(sp).is_real() {
@@ -397,6 +398,29 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
397398
} else {
398399
String::new()
399400
};
401+
if let Some(hir::Node::Expr(hir::Expr {
402+
node: hir::ExprKind::Assign(left_expr, _),
403+
..
404+
})) = self.tcx.hir().find_by_hir_id(
405+
self.tcx.hir().get_parent_node_by_hir_id(expr.hir_id),
406+
) {
407+
if mutability == hir::Mutability::MutMutable {
408+
// Found the following case:
409+
// fn foo(opt: &mut Option<String>){ opt = None }
410+
// --- ^^^^
411+
// | |
412+
// consider dereferencing here: `*opt` |
413+
// expected mutable reference, found enum `Option`
414+
if let Ok(src) = cm.span_to_snippet(left_expr.span) {
415+
return Some((
416+
left_expr.span,
417+
"consider dereferencing here to assign to the mutable \
418+
borrowed piece of memory",
419+
format!("*{}", src),
420+
));
421+
}
422+
}
423+
}
400424
return Some(match mutability {
401425
hir::Mutability::MutMutable => (
402426
sp,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn change_opt(opt: &mut Option<String>){
2+
opt = None //~ ERROR mismatched types
3+
}
4+
5+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/mut-ref-reassignment.rs:2:11
3+
|
4+
LL | opt = None
5+
| ^^^^ expected mutable reference, found enum `std::option::Option`
6+
|
7+
= note: expected type `&mut std::option::Option<std::string::String>`
8+
found type `std::option::Option<_>`
9+
help: consider dereferencing here to assign to the mutable borrowed piece of memory
10+
|
11+
LL | *opt = None
12+
| ^^^^
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)