Skip to content

Commit 4e7ec07

Browse files
committed
Account for short-hand field syntax when suggesting borrow
1 parent 33ef0ba commit 4e7ec07

File tree

3 files changed

+82
-12
lines changed

3 files changed

+82
-12
lines changed

src/librustc_typeck/check/demand.rs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
277277
return None;
278278
}
279279

280+
let parent_id = self.tcx.hir().get_parent_node_by_hir_id(expr.hir_id);
281+
let mut is_struct_pat_shorthand_field = false;
282+
if let Some(parent) = self.tcx.hir().find_by_hir_id(parent_id) {
283+
// Account for fields
284+
if let Node::Expr(hir::Expr {
285+
node: hir::ExprKind::Struct(_, fields, ..), ..
286+
}) = parent {
287+
if let Ok(src) = cm.span_to_snippet(sp) {
288+
for field in fields {
289+
if field.ident.as_str() == src.as_str() && field.is_shorthand {
290+
is_struct_pat_shorthand_field = true;
291+
break;
292+
}
293+
}
294+
}
295+
}
296+
};
297+
280298
match (&expected.sty, &checked_ty.sty) {
281299
(&ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.sty, &check.sty) {
282300
(&ty::Str, &ty::Array(arr, _)) |
@@ -341,14 +359,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
341359
if let Some(sugg) = self.can_use_as_ref(expr) {
342360
return Some(sugg);
343361
}
344-
return Some(match mutability {
345-
hir::Mutability::MutMutable => {
346-
(sp, "consider mutably borrowing here", format!("&mut {}",
347-
sugg_expr))
362+
return Some(match (mutability, is_struct_pat_shorthand_field) {
363+
(hir::Mutability::MutMutable, false) => {
364+
(sp, "consider mutably borrowing here",
365+
format!("&mut {}", sugg_expr))
348366
}
349-
hir::Mutability::MutImmutable => {
367+
(hir::Mutability::MutImmutable, false) => {
350368
(sp, "consider borrowing here", format!("&{}", sugg_expr))
351369
}
370+
(hir::Mutability::MutMutable, true) => {
371+
(sp, "consider mutably borrowing here",
372+
format!("{}: &mut {}", sugg_expr, sugg_expr))
373+
}
374+
(hir::Mutability::MutImmutable, true) => {
375+
(sp, "consider borrowing here",
376+
format!("{}: &{}", sugg_expr, sugg_expr))
377+
}
352378
});
353379
}
354380
}
@@ -389,12 +415,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
389415
checked,
390416
sp) {
391417
// do not suggest if the span comes from a macro (#52783)
392-
if let (Ok(code),
393-
true) = (cm.span_to_snippet(sp), sp == expr.span) {
418+
if let (Ok(code), true) = (
419+
cm.span_to_snippet(sp),
420+
sp == expr.span,
421+
) {
394422
return Some((
395423
sp,
396424
"consider dereferencing the borrow",
397-
format!("*{}", code),
425+
if is_struct_pat_shorthand_field {
426+
format!("{}: *{}", code, code)
427+
} else {
428+
format!("*{}", code)
429+
},
398430
));
399431
}
400432
}

src/test/ui/deref-suggestion.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ fn foo4(u: &u32) {
1515
//~^ ERROR mismatched types
1616
}
1717

18+
struct S<'a> {
19+
u: &'a u32,
20+
}
21+
22+
struct R {
23+
i: u32,
24+
}
25+
1826
fn main() {
1927
let s = String::new();
2028
let r_s = &s;
@@ -27,4 +35,10 @@ fn main() {
2735
foo4(&0);
2836
assert_eq!(3i32, &3i32);
2937
//~^ ERROR mismatched types
38+
let u = 3;
39+
let s = S { u };
40+
//~^ ERROR mismatched types
41+
let i = &4;
42+
let r = R { i };
43+
//~^ ERROR mismatched types
3044
}

src/test/ui/deref-suggestion.stderr

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ LL | foo3(u);
2323
found type `&u32`
2424

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

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

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

71-
error: aborting due to 6 previous errors
71+
error[E0308]: mismatched types
72+
--> $DIR/deref-suggestion.rs:39:17
73+
|
74+
LL | let s = S { u };
75+
| ^
76+
| |
77+
| expected &u32, found integer
78+
| help: consider borrowing here: `u: &u`
79+
|
80+
= note: expected type `&u32`
81+
found type `{integer}`
82+
83+
error[E0308]: mismatched types
84+
--> $DIR/deref-suggestion.rs:42:17
85+
|
86+
LL | let r = R { i };
87+
| ^
88+
| |
89+
| expected u32, found &{integer}
90+
| help: consider dereferencing the borrow: `i: *i`
91+
|
92+
= note: expected type `u32`
93+
found type `&{integer}`
94+
95+
error: aborting due to 8 previous errors
7296

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

0 commit comments

Comments
 (0)