Rollup merge of #61054 - estebank:mut-ref-reassign, r=zackmdavis

Suggest dereferencing on assignment to mutable borrow

Fix #33570
This commit is contained in:
Mazdak Farrokhzad 2019-05-24 01:30:20 +02:00 committed by GitHub
commit b9459e7e4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 93 additions and 5 deletions

View File

@ -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<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,

View File

@ -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() {}

View File

@ -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`.