Rollup merge of #59455 - estebank:borrow-sugg-shorthand-field, r=davidtwco
Account for short-hand field syntax when suggesting borrow Fix #52965.
This commit is contained in:
commit
41e64b6c5c
3 changed files with 125 additions and 20 deletions
|
|
@ -270,6 +270,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
None
|
||||
}
|
||||
|
||||
fn is_hir_id_from_struct_pattern_shorthand_field(&self, hir_id: hir::HirId, sp: Span) -> bool {
|
||||
let cm = self.sess().source_map();
|
||||
let parent_id = self.tcx.hir().get_parent_node_by_hir_id(hir_id);
|
||||
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 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// This function is used to determine potential "simple" improvements or users' errors and
|
||||
/// provide them useful help. For example:
|
||||
///
|
||||
|
|
@ -299,6 +319,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let is_struct_pat_shorthand_field = self.is_hir_id_from_struct_pattern_shorthand_field(
|
||||
expr.hir_id,
|
||||
sp,
|
||||
);
|
||||
|
||||
match (&expected.sty, &checked_ty.sty) {
|
||||
(&ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.sty, &check.sty) {
|
||||
(&ty::Str, &ty::Array(arr, _)) |
|
||||
|
|
@ -337,12 +362,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// bar(&x); // error, expected &mut
|
||||
// ```
|
||||
let ref_ty = match mutability {
|
||||
hir::Mutability::MutMutable => self.tcx.mk_mut_ref(
|
||||
self.tcx.mk_region(ty::ReStatic),
|
||||
checked_ty),
|
||||
hir::Mutability::MutImmutable => self.tcx.mk_imm_ref(
|
||||
self.tcx.mk_region(ty::ReStatic),
|
||||
checked_ty),
|
||||
hir::Mutability::MutMutable => {
|
||||
self.tcx.mk_mut_ref(self.tcx.mk_region(ty::ReStatic), checked_ty)
|
||||
}
|
||||
hir::Mutability::MutImmutable => {
|
||||
self.tcx.mk_imm_ref(self.tcx.mk_region(ty::ReStatic), checked_ty)
|
||||
}
|
||||
};
|
||||
if self.can_coerce(ref_ty, expected) {
|
||||
if let Ok(src) = cm.span_to_snippet(sp) {
|
||||
|
|
@ -363,14 +388,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
if let Some(sugg) = self.can_use_as_ref(expr) {
|
||||
return Some(sugg);
|
||||
}
|
||||
let field_name = if is_struct_pat_shorthand_field {
|
||||
format!("{}: ", sugg_expr)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
return Some(match mutability {
|
||||
hir::Mutability::MutMutable => {
|
||||
(sp, "consider mutably borrowing here", format!("&mut {}",
|
||||
sugg_expr))
|
||||
}
|
||||
hir::Mutability::MutImmutable => {
|
||||
(sp, "consider borrowing here", format!("&{}", sugg_expr))
|
||||
}
|
||||
hir::Mutability::MutMutable => (
|
||||
sp,
|
||||
"consider mutably borrowing here",
|
||||
format!("{}&mut {}", field_name, sugg_expr),
|
||||
),
|
||||
hir::Mutability::MutImmutable => (
|
||||
sp,
|
||||
"consider borrowing here",
|
||||
format!("{}&{}", field_name, sugg_expr),
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -411,12 +444,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,14 @@ fn main() {
|
|||
foo4(&0);
|
||||
assert_eq!(3i32, &3i32);
|
||||
//~^ ERROR mismatched types
|
||||
let u = 3;
|
||||
let s = S { u };
|
||||
//~^ ERROR mismatched types
|
||||
let s = S { u: u };
|
||||
//~^ ERROR mismatched types
|
||||
let i = &4;
|
||||
let r = R { i };
|
||||
//~^ ERROR mismatched types
|
||||
let r = R { i: 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,54 @@ 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:41:20
|
||||
|
|
||||
LL | let s = S { u: u };
|
||||
| ^
|
||||
| |
|
||||
| expected &u32, found integer
|
||||
| help: consider borrowing here: `&u`
|
||||
|
|
||||
= note: expected type `&u32`
|
||||
found type `{integer}`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/deref-suggestion.rs:44: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[E0308]: mismatched types
|
||||
--> $DIR/deref-suggestion.rs:46:20
|
||||
|
|
||||
LL | let r = R { i: i };
|
||||
| ^
|
||||
| |
|
||||
| expected u32, found &{integer}
|
||||
| help: consider dereferencing the borrow: `*i`
|
||||
|
|
||||
= note: expected type `u32`
|
||||
found type `&{integer}`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue