about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2018-07-30 15:41:39 -0700
committerEsteban Küber <esteban@kuber.com.ar>2018-07-30 15:41:39 -0700
commitc883edfbc6b669bea4264f5a79e2bee0e5766c38 (patch)
tree37fd644b15542b1910e213ecdd473d99c28c214f
parent70cac59031d5c33962a1f53cdca9359c0dcd1f9f (diff)
downloadrust-c883edfbc6b669bea4264f5a79e2bee0e5766c38.tar.gz
rust-c883edfbc6b669bea4264f5a79e2bee0e5766c38.zip
Include lifetime in mutability suggestion in NLL messages
-rw-r--r--src/librustc_mir/borrow_check/mutability_errors.rs54
-rw-r--r--src/test/ui/did_you_mean/issue-39544.nll.stderr6
-rw-r--r--src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr4
-rw-r--r--src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr4
-rw-r--r--src/test/ui/span/mut-arg-hint.nll.stderr2
-rw-r--r--src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr4
6 files changed, 53 insertions, 21 deletions
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index 571a1188d49..310ddb5e78a 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -307,7 +307,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                 let local_decl = &self.mir.local_decls[*local];
                 let suggestion = match local_decl.is_user_variable.as_ref().unwrap() {
                     ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf) => {
-                        Some(suggest_ampmut_self(local_decl))
+                        Some(suggest_ampmut_self(self.tcx, local_decl))
                     }
 
                     ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
@@ -418,8 +418,22 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
     }
 }
 
-fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(local_decl: &mir::LocalDecl<'tcx>) -> (Span, String) {
-    (local_decl.source_info.span, "&mut self".to_string())
+fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(
+    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+    local_decl: &mir::LocalDecl<'tcx>,
+) -> (Span, String) {
+    let sp = local_decl.source_info.span;
+    (sp, match tcx.sess.codemap().span_to_snippet(sp) {
+        Ok(snippet) => {
+            let lt_pos = snippet.find('\'');
+            if let Some(lt_pos) = lt_pos {
+                format!("&{}mut self", &snippet[lt_pos..snippet.len() - 4])
+            } else {
+                "&mut self".to_string()
+            }
+        }
+        _ => "&mut self".to_string()
+    })
 }
 
 // When we want to suggest a user change a local variable to be a `&mut`, there
@@ -447,9 +461,15 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>(
     let locations = mir.find_assignments(local);
     if locations.len() > 0 {
         let assignment_rhs_span = mir.source_info(locations[0]).span;
-        let snippet = tcx.sess.codemap().span_to_snippet(assignment_rhs_span);
-        if let Ok(src) = snippet {
-            if src.starts_with('&') {
+        if let Ok(src) = tcx.sess.codemap().span_to_snippet(assignment_rhs_span) {
+            if let (true, Some(ws_pos)) = (
+                src.starts_with("&'"),
+                src.find(|c: char| -> bool { c.is_whitespace() }),
+            ) {
+                let lt_name = &src[1..ws_pos];
+                let ty = &src[ws_pos..];
+                return (assignment_rhs_span, format!("&{} mut {}", lt_name, ty));
+            } else if src.starts_with('&') {
                 let borrowed_expr = src[1..].to_string();
                 return (assignment_rhs_span, format!("&mut {}", borrowed_expr));
             }
@@ -466,13 +486,25 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>(
         None => local_decl.source_info.span,
     };
 
+    if let Ok(src) = tcx.sess.codemap().span_to_snippet(highlight_span) {
+        if let (true, Some(ws_pos)) = (
+            src.starts_with("&'"),
+            src.find(|c: char| -> bool { c.is_whitespace() }),
+        ) {
+            let lt_name = &src[1..ws_pos];
+            let ty = &src[ws_pos..];
+            return (highlight_span, format!("&{} mut{}", lt_name, ty));
+        }
+    }
+
     let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
     assert_eq!(ty_mut.mutbl, hir::MutImmutable);
-    if local_decl.ty.is_region_ptr() {
-        (highlight_span, format!("&mut {}", ty_mut.ty))
-    } else {
-        (highlight_span, format!("*mut {}", ty_mut.ty))
-    }
+    (highlight_span,
+     if local_decl.ty.is_region_ptr() {
+         format!("&mut {}", ty_mut.ty)
+     } else {
+         format!("*mut {}", ty_mut.ty)
+     })
 }
 
 fn is_closure_or_generator(ty: ty::Ty) -> bool {
diff --git a/src/test/ui/did_you_mean/issue-39544.nll.stderr b/src/test/ui/did_you_mean/issue-39544.nll.stderr
index 00e4cc6b0c3..8c848b33241 100644
--- a/src/test/ui/did_you_mean/issue-39544.nll.stderr
+++ b/src/test/ui/did_you_mean/issue-39544.nll.stderr
@@ -10,7 +10,7 @@ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:26:17
    |
 LL |     fn foo<'z>(&'z self) {
-   |                -------- help: consider changing this to be a mutable reference: `&mut self`
+   |                -------- help: consider changing this to be a mutable reference: `&'z mut self`
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
@@ -35,7 +35,7 @@ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:35:17
    |
 LL |     fn foo2<'a>(&'a self, other: &Z) {
-   |                 -------- help: consider changing this to be a mutable reference: `&mut self`
+   |                 -------- help: consider changing this to be a mutable reference: `&'a mut self`
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
@@ -52,7 +52,7 @@ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
   --> $DIR/issue-39544.rs:40:17
    |
 LL |     fn foo3<'a>(self: &'a Self, other: &Z) {
-   |                       -------- help: consider changing this to be a mutable reference: `&mut Z`
+   |                       -------- help: consider changing this to be a mutable reference: `&'a mut Self`
 LL |         let _ = &mut self.x; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr
index 366bfc8fa20..4a693a3b05d 100644
--- a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr
+++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.nll.stderr
@@ -26,7 +26,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:102:5
    |
 LL | fn assign_field2<'a>(x: &'a Own<Point>) {
-   |                         -------------- help: consider changing this to be a mutable reference: `&mut Own<Point>`
+   |                         -------------- help: consider changing this to be a mutable reference: `&'a mut Own<Point>`
 LL |     x.y = 3; //~ ERROR cannot borrow
    |     ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
@@ -58,7 +58,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:143:6
    |
 LL | fn assign_method2<'a>(x: &'a Own<Point>) {
-   |                          -------------- help: consider changing this to be a mutable reference: `&mut Own<Point>`
+   |                          -------------- help: consider changing this to be a mutable reference: `&'a mut Own<Point>`
 LL |     *x.y_mut() = 3; //~ ERROR cannot borrow
    |      ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr
index 69bf246ff3f..44a5062cb4d 100644
--- a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr
+++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.nll.stderr
@@ -10,7 +10,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:51:11
    |
 LL | fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
-   |                             -------------- help: consider changing this to be a mutable reference: `&mut Own<isize>`
+   |                             -------------- help: consider changing this to be a mutable reference: `&'a mut Own<isize>`
 LL |     &mut **x //~ ERROR cannot borrow
    |           ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
@@ -26,7 +26,7 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:63:6
    |
 LL | fn assign2<'a>(x: &'a Own<isize>) {
-   |                   -------------- help: consider changing this to be a mutable reference: `&mut Own<isize>`
+   |                   -------------- help: consider changing this to be a mutable reference: `&'a mut Own<isize>`
 LL |     **x = 3; //~ ERROR cannot borrow
    |      ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
diff --git a/src/test/ui/span/mut-arg-hint.nll.stderr b/src/test/ui/span/mut-arg-hint.nll.stderr
index f264ea1f916..f42cf6500e2 100644
--- a/src/test/ui/span/mut-arg-hint.nll.stderr
+++ b/src/test/ui/span/mut-arg-hint.nll.stderr
@@ -10,7 +10,7 @@ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
   --> $DIR/mut-arg-hint.rs:18:5
    |
 LL | pub fn foo<'a>(mut a: &'a String) {
-   |                       ---------- help: consider changing this to be a mutable reference: `&mut std::string::String`
+   |                       ---------- help: consider changing this to be a mutable reference: `&'a mut String`
 LL |     a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content
    |     ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
diff --git a/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr b/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr
index 215faf6c73c..56897baeb4e 100644
--- a/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr
+++ b/src/test/ui/trivial-bounds-inconsistent-copy-reborrow.nll.stderr
@@ -2,7 +2,7 @@ error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference
   --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:16:5
    |
 LL | fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
-   |                        --------------- help: consider changing this to be a mutable reference: `&mut &mut i32`
+   |                        --------------- help: consider changing this to be a mutable reference: `&'a mut &'a mut i32`
 LL |     *t //~ ERROR
    |     ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable
 
@@ -10,7 +10,7 @@ error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference
   --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:20:6
    |
 LL | fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
-   |                             --------------- help: consider changing this to be a mutable reference: `&mut &mut i32`
+   |                             --------------- help: consider changing this to be a mutable reference: `&'a mut &'a mut i32`
 LL |     {*t} //~ ERROR
    |      ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable