From 4e7ec07bb910aef258a848d5fcfa96b3bab7b3b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 26 Mar 2019 19:04:25 -0700 Subject: [PATCH] Account for short-hand field syntax when suggesting borrow --- src/librustc_typeck/check/demand.rs | 48 ++++++++++++++++++++++++----- src/test/ui/deref-suggestion.rs | 14 +++++++++ src/test/ui/deref-suggestion.stderr | 32 ++++++++++++++++--- 3 files changed, 82 insertions(+), 12 deletions(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index b1a249d821be..5939f965269b 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -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) + }, )); } } diff --git a/src/test/ui/deref-suggestion.rs b/src/test/ui/deref-suggestion.rs index 83e54b64f47c..f156766f5288 100644 --- a/src/test/ui/deref-suggestion.rs +++ b/src/test/ui/deref-suggestion.rs @@ -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 } diff --git a/src/test/ui/deref-suggestion.stderr b/src/test/ui/deref-suggestion.stderr index 8f061b3416e1..bd0ebfac5319 100644 --- a/src/test/ui/deref-suggestion.stderr +++ b/src/test/ui/deref-suggestion.stderr @@ -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`.