Skip to content
Permalink
Browse files

Account for short-hand field syntax when suggesting borrow

  • Loading branch information...
estebank committed Mar 27, 2019
1 parent 33ef0ba commit 4e7ec07bb910aef258a848d5fcfa96b3bab7b3b4
Showing with 82 additions and 12 deletions.
  1. +40 −8 src/librustc_typeck/check/demand.rs
  2. +14 −0 src/test/ui/deref-suggestion.rs
  3. +28 −4 src/test/ui/deref-suggestion.stderr
@@ -277,6 +277,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
return None;
}

let parent_id = self.tcx.hir().get_parent_node_by_hir_id(expr.hir_id);
let mut is_struct_pat_shorthand_field = false;
if let Some(parent) = self.tcx.hir().find_by_hir_id(parent_id) {
// Account for fields
if let Node::Expr(hir::Expr {
node: hir::ExprKind::Struct(_, fields, ..), ..
}) = parent {
if let Ok(src) = cm.span_to_snippet(sp) {
for field in fields {
if field.ident.as_str() == src.as_str() && field.is_shorthand {
is_struct_pat_shorthand_field = true;
break;
}
}
}
}
};

match (&expected.sty, &checked_ty.sty) {
(&ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.sty, &check.sty) {
(&ty::Str, &ty::Array(arr, _)) |
@@ -341,14 +359,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if let Some(sugg) = self.can_use_as_ref(expr) {
return Some(sugg);
}
return Some(match mutability {
hir::Mutability::MutMutable => {
(sp, "consider mutably borrowing here", format!("&mut {}",
sugg_expr))
return Some(match (mutability, is_struct_pat_shorthand_field) {
(hir::Mutability::MutMutable, false) => {
(sp, "consider mutably borrowing here",
format!("&mut {}", sugg_expr))
}
hir::Mutability::MutImmutable => {
(hir::Mutability::MutImmutable, false) => {
(sp, "consider borrowing here", format!("&{}", sugg_expr))
}
(hir::Mutability::MutMutable, true) => {
(sp, "consider mutably borrowing here",
format!("{}: &mut {}", sugg_expr, sugg_expr))
}
(hir::Mutability::MutImmutable, true) => {
(sp, "consider borrowing here",
format!("{}: &{}", sugg_expr, sugg_expr))
}
});
}
}
@@ -389,12 +415,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
checked,
sp) {
// do not suggest if the span comes from a macro (#52783)
if let (Ok(code),
true) = (cm.span_to_snippet(sp), sp == expr.span) {
if let (Ok(code), true) = (
cm.span_to_snippet(sp),
sp == expr.span,
) {
return Some((
sp,
"consider dereferencing the borrow",
format!("*{}", code),
if is_struct_pat_shorthand_field {
format!("{}: *{}", code, code)
} else {
format!("*{}", code)
},
));
}
}
@@ -15,6 +15,14 @@ fn foo4(u: &u32) {
//~^ ERROR mismatched types
}

struct S<'a> {
u: &'a u32,
}

struct R {
i: u32,
}

fn main() {
let s = String::new();
let r_s = &s;
@@ -27,4 +35,10 @@ fn main() {
foo4(&0);
assert_eq!(3i32, &3i32);
//~^ ERROR mismatched types
let u = 3;
let s = S { u };
//~^ ERROR mismatched types
let i = &4;
let r = R { i };
//~^ ERROR mismatched types
}
@@ -23,7 +23,7 @@ LL | foo3(u);
found type `&u32`

error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:22:9
--> $DIR/deref-suggestion.rs:30:9
|
LL | foo(&"aaa".to_owned());
| ^^^^^^^^^^^^^^^^^
@@ -35,7 +35,7 @@ LL | foo(&"aaa".to_owned());
found type `&std::string::String`

error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:24:9
--> $DIR/deref-suggestion.rs:32:9
|
LL | foo(&mut "aaa".to_owned());
| ^^^^^^^^^^^^^^^^^^^^^
@@ -59,7 +59,7 @@ LL | foo3(borrow!(0));
found type `&{integer}`

error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:28:5
--> $DIR/deref-suggestion.rs:36:5
|
LL | assert_eq!(3i32, &3i32);
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found &i32
@@ -68,6 +68,30 @@ LL | assert_eq!(3i32, &3i32);
found type `&i32`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: aborting due to 6 previous errors
error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:39:17
|
LL | let s = S { u };
| ^
| |
| expected &u32, found integer
| help: consider borrowing here: `u: &u`
|
= note: expected type `&u32`
found type `{integer}`

error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:42:17
|
LL | let r = R { i };
| ^
| |
| expected u32, found &{integer}
| help: consider dereferencing the borrow: `i: *i`
|
= note: expected type `u32`
found type `&{integer}`

error: aborting due to 8 previous errors

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

0 comments on commit 4e7ec07

Please sign in to comment.
You can’t perform that action at this time.