diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 8d68179b495c6..a4e687b8f9080 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -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() { @@ -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){ 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, diff --git a/src/test/ui/suggestions/mut-ref-reassignment.rs b/src/test/ui/suggestions/mut-ref-reassignment.rs new file mode 100644 index 0000000000000..b9deaa96dbfc3 --- /dev/null +++ b/src/test/ui/suggestions/mut-ref-reassignment.rs @@ -0,0 +1,5 @@ +fn change_opt(opt: &mut Option){ + opt = None //~ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/suggestions/mut-ref-reassignment.stderr b/src/test/ui/suggestions/mut-ref-reassignment.stderr new file mode 100644 index 0000000000000..d90c13b388279 --- /dev/null +++ b/src/test/ui/suggestions/mut-ref-reassignment.stderr @@ -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` + 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`.