]> git.lizzy.rs Git - rust.git/commitdiff
Account for short-hand field syntax when suggesting borrow
authorEsteban Küber <esteban@kuber.com.ar>
Wed, 27 Mar 2019 02:04:25 +0000 (19:04 -0700)
committerEsteban Küber <esteban@kuber.com.ar>
Thu, 28 Mar 2019 02:44:08 +0000 (19:44 -0700)
src/librustc_typeck/check/demand.rs
src/test/ui/deref-suggestion.rs
src/test/ui/deref-suggestion.stderr

index b1a249d821bec77b279f3d3629d90e2fbadc237d..5939f965269be4df4f5d2668d2907c8a20f184f4 100644 (file)
@@ -277,6 +277,24 @@ pub fn check_ref(&self,
             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 @@ pub fn check_ref(&self,
                         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 @@ pub fn check_ref(&self,
                                                                       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)
+                                        },
                                     ));
                                 }
                             }
index 83e54b64f47c9c79641e416630ae5e3dfd486db9..f156766f528815a58f9caef68545f39200b1b82d 100644 (file)
@@ -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
 }
index 8f061b3416e13f9b4045dba634265c2a6cca8286..bd0ebfac5319d694d88c3746fae31dea21d8a6ac 100644 (file)
@@ -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`.