Skip to content

Commit b9459e7

Browse files
authored
Rollup merge of rust-lang#61054 - estebank:mut-ref-reassign, r=zackmdavis
Suggest dereferencing on assignment to mutable borrow Fix rust-lang#33570
2 parents e0e9c86 + 7fbbcfa commit b9459e7

File tree

3 files changed

+93
-5
lines changed

3 files changed

+93
-5
lines changed

src/librustc_typeck/check/demand.rs

Lines changed: 29 additions & 5 deletions
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,
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
fn suggestion(opt: &mut Option<String>) {
2+
opt = None; //~ ERROR mismatched types
3+
}
4+
5+
fn no_suggestion(opt: &mut Result<String, ()>) {
6+
opt = None //~ ERROR mismatched types
7+
}
8+
9+
fn suggestion2(opt: &mut Option<String>) {
10+
opt = Some(String::new())//~ ERROR mismatched types
11+
}
12+
13+
fn no_suggestion2(opt: &mut Option<String>) {
14+
opt = Some(42)//~ ERROR mismatched types
15+
}
16+
17+
fn main() {}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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[E0308]: mismatched types
15+
--> $DIR/mut-ref-reassignment.rs:6:11
16+
|
17+
LL | opt = None
18+
| ^^^^ expected mutable reference, found enum `std::option::Option`
19+
|
20+
= note: expected type `&mut std::result::Result<std::string::String, ()>`
21+
found type `std::option::Option<_>`
22+
23+
error[E0308]: mismatched types
24+
--> $DIR/mut-ref-reassignment.rs:10:11
25+
|
26+
LL | opt = Some(String::new())
27+
| ^^^^^^^^^^^^^^^^^^^ expected mutable reference, found enum `std::option::Option`
28+
|
29+
= note: expected type `&mut std::option::Option<std::string::String>`
30+
found type `std::option::Option<std::string::String>`
31+
help: consider dereferencing here to assign to the mutable borrowed piece of memory
32+
|
33+
LL | *opt = Some(String::new())
34+
| ^^^^
35+
36+
error[E0308]: mismatched types
37+
--> $DIR/mut-ref-reassignment.rs:14:11
38+
|
39+
LL | opt = Some(42)
40+
| ^^^^^^^^ expected mutable reference, found enum `std::option::Option`
41+
|
42+
= note: expected type `&mut std::option::Option<std::string::String>`
43+
found type `std::option::Option<{integer}>`
44+
45+
error: aborting due to 4 previous errors
46+
47+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)