]> git.lizzy.rs Git - rust.git/commitdiff
Merge multiple mutable borrows of immutable binding errors
authorEsteban Küber <esteban@kuber.com.ar>
Fri, 30 Dec 2022 06:46:17 +0000 (22:46 -0800)
committerEsteban Küber <esteban@kuber.com.ar>
Sun, 1 Jan 2023 18:09:26 +0000 (10:09 -0800)
Fix #53466.

14 files changed:
compiler/rustc_borrowck/src/borrowck_errors.rs
compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
compiler/rustc_borrowck/src/lib.rs
compiler/rustc_errors/src/diagnostic.rs
compiler/rustc_expand/src/mbe/diagnostics.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
src/test/ui/asm/x86_64/type-check-5.rs
src/test/ui/asm/x86_64/type-check-5.stderr
src/test/ui/borrowck/many-mutable-borrows.rs [new file with mode: 0644]
src/test/ui/borrowck/many-mutable-borrows.stderr [new file with mode: 0644]
src/test/ui/borrowck/mut-borrow-of-mut-ref.rs
src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr
src/test/ui/borrowck/mutability-errors.rs
src/test/ui/borrowck/mutability-errors.stderr

index 01be379120dc7483c088daa4005b744bb386dfb8..e4942f9b666e0e837389503cd2d1099895b318da 100644 (file)
@@ -12,7 +12,7 @@ pub(crate) fn cannot_move_when_borrowed(
         place: &str,
         borrow_place: &str,
         value_place: &str,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         self.infcx.tcx.sess.create_err(crate::session_diagnostics::MoveBorrow {
             place,
             span,
@@ -28,7 +28,7 @@ pub(crate) fn cannot_use_when_mutably_borrowed(
         desc: &str,
         borrow_span: Span,
         borrow_desc: &str,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let mut err = struct_span_err!(
             self,
             span,
@@ -50,7 +50,7 @@ pub(crate) fn cannot_mutably_borrow_multiply(
         old_loan_span: Span,
         old_opt_via: &str,
         old_load_end_span: Option<Span>,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let via =
             |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) };
         let mut err = struct_span_err!(
@@ -98,7 +98,7 @@ pub(crate) fn cannot_uniquely_borrow_by_two_closures(
         desc: &str,
         old_loan_span: Span,
         old_load_end_span: Option<Span>,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let mut err = struct_span_err!(
             self,
             new_loan_span,
@@ -269,7 +269,7 @@ pub(crate) fn cannot_assign(
         &self,
         span: Span,
         desc: &str,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         struct_span_err!(self, span, E0594, "cannot assign to {}", desc)
     }
 
@@ -348,7 +348,7 @@ pub(crate) fn cannot_borrow_path_as_mutable_because(
         span: Span,
         path: &str,
         reason: &str,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{}", path, reason,)
     }
 
@@ -359,7 +359,7 @@ pub(crate) fn cannot_mutate_in_immutable_section(
         immutable_place: &str,
         immutable_section: &str,
         action: &str,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let mut err = struct_span_err!(
             self,
             mutate_span,
@@ -378,7 +378,7 @@ pub(crate) fn cannot_borrow_across_generator_yield(
         &self,
         span: Span,
         yield_span: Span,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let mut err = struct_span_err!(
             self,
             span,
@@ -392,7 +392,7 @@ pub(crate) fn cannot_borrow_across_generator_yield(
     pub(crate) fn cannot_borrow_across_destructor(
         &self,
         borrow_span: Span,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         struct_span_err!(
             self,
             borrow_span,
@@ -405,7 +405,7 @@ pub(crate) fn path_does_not_live_long_enough(
         &self,
         span: Span,
         path: &str,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         struct_span_err!(self, span, E0597, "{} does not live long enough", path,)
     }
 
@@ -415,7 +415,7 @@ pub(crate) fn cannot_return_reference_to_local(
         return_kind: &str,
         reference_desc: &str,
         path_desc: &str,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let mut err = struct_span_err!(
             self,
             span,
@@ -440,7 +440,7 @@ pub(crate) fn cannot_capture_in_long_lived_closure(
         closure_kind: &str,
         borrowed_path: &str,
         capture_span: Span,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         let mut err = struct_span_err!(
             self,
             closure_span,
@@ -458,14 +458,14 @@ pub(crate) fn cannot_capture_in_long_lived_closure(
     pub(crate) fn thread_local_value_does_not_live_long_enough(
         &self,
         span: Span,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         struct_span_err!(self, span, E0712, "thread-local variable borrowed past end of function",)
     }
 
     pub(crate) fn temporary_value_borrowed_for_too_long(
         &self,
         span: Span,
-    ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
         struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",)
     }
 
index 99ca4c637bd2e2c01e0407d1effa455e74292049..b04b11e7c9bda9ec987123a74356d9c4f53bc191 100644 (file)
@@ -180,6 +180,9 @@ pub(crate) fn report_mutability_error(
         // the verbs used in some diagnostic messages.
         let act;
         let acted_on;
+        let mut suggest = true;
+        let mut mut_error = None;
+        let mut count = 1;
 
         let span = match error_access {
             AccessKind::Mutate => {
@@ -194,15 +197,50 @@ pub(crate) fn report_mutability_error(
 
                 let borrow_spans = self.borrow_spans(span, location);
                 let borrow_span = borrow_spans.args_or_use();
-                err = self.cannot_borrow_path_as_mutable_because(borrow_span, &item_msg, &reason);
-                borrow_spans.var_span_label(
-                    &mut err,
-                    format!(
-                        "mutable borrow occurs due to use of {} in closure",
-                        self.describe_any_place(access_place.as_ref()),
-                    ),
-                    "mutable",
-                );
+                match the_place_err {
+                    PlaceRef { local, projection: [] }
+                        if self.body.local_decls[local].can_be_made_mutable() =>
+                    {
+                        let span = self.body.local_decls[local].source_info.span;
+                        mut_error = Some(span);
+                        if let Some((buffer, c)) = self.get_buffered_mut_error(span) {
+                            // We've encountered a second (or more) attempt to mutably borrow an
+                            // immutable binding, so the likely problem is with the binding
+                            // declaration, not the use. We collect these in a single diagnostic
+                            // and make the binding the primary span of the error.
+                            err = buffer;
+                            count = c + 1;
+                            if count == 2 {
+                                err.replace_span_with(span, false);
+                                err.span_label(span, "not mutable");
+                            }
+                            suggest = false;
+                        } else {
+                            err = self.cannot_borrow_path_as_mutable_because(
+                                borrow_span,
+                                &item_msg,
+                                &reason,
+                            );
+                        }
+                    }
+                    _ => {
+                        err = self.cannot_borrow_path_as_mutable_because(
+                            borrow_span,
+                            &item_msg,
+                            &reason,
+                        );
+                    }
+                }
+                if suggest {
+                    borrow_spans.var_span_label(
+                        &mut err,
+                        format!(
+                            "mutable borrow occurs due to use of {} in closure",
+                            self.describe_any_place(access_place.as_ref()),
+                        ),
+                        "mutable",
+                    );
+                }
                 borrow_span
             }
         };
@@ -276,7 +314,9 @@ pub(crate) fn report_mutability_error(
                                 pat_span: _,
                             },
                         )))) => {
-                            err.span_note(sp, "the binding is already a mutable borrow");
+                            if suggest {
+                                err.span_note(sp, "the binding is already a mutable borrow");
+                            }
                         }
                         _ => {
                             err.span_note(
@@ -333,16 +373,20 @@ pub(crate) fn report_mutability_error(
                 let local_decl = &self.body.local_decls[local];
                 assert_eq!(local_decl.mutability, Mutability::Not);
 
-                err.span_label(span, format!("cannot {act}"));
-                err.span_suggestion(
-                    local_decl.source_info.span,
-                    "consider changing this to be mutable",
-                    format!("mut {}", self.local_names[local].unwrap()),
-                    Applicability::MachineApplicable,
-                );
-                let tcx = self.infcx.tcx;
-                if let ty::Closure(id, _) = *the_place_err.ty(self.body, tcx).ty.kind() {
-                    self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err);
+                if count < 10 {
+                    err.span_label(span, format!("cannot {act}"));
+                }
+                if suggest {
+                    err.span_suggestion(
+                        local_decl.source_info.span,
+                        "consider changing this to be mutable",
+                        format!("mut {}", self.local_names[local].unwrap()),
+                        Applicability::MachineApplicable,
+                    );
+                    let tcx = self.infcx.tcx;
+                    if let ty::Closure(id, _) = *the_place_err.ty(self.body, tcx).ty.kind() {
+                        self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err);
+                    }
                 }
             }
 
@@ -615,7 +659,11 @@ pub(crate) fn report_mutability_error(
             }
         }
 
-        self.buffer_error(err);
+        if let Some(span) = mut_error {
+            self.buffer_mut_error(span, err, count);
+        } else {
+            self.buffer_error(err);
+        }
     }
 
     fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diagnostic, span: Span) {
index 168b798788b4c747c7fad8e4db5337b5f36fceaf..ae1bea008b6cede53a067e4a3dddf619752478ce 100644 (file)
@@ -2270,6 +2270,7 @@ pub struct BorrowckErrors<'tcx> {
         /// same primary span come out in a consistent order.
         buffered_move_errors:
             BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorGuaranteed>)>,
+        buffered_mut_errors: FxHashMap<Span, (DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)>,
         /// Diagnostics to be reported buffer.
         buffered: Vec<Diagnostic>,
         /// Set to Some if we emit an error during borrowck
@@ -2281,6 +2282,7 @@ pub fn new(tcx: TyCtxt<'tcx>) -> Self {
             BorrowckErrors {
                 tcx,
                 buffered_move_errors: BTreeMap::new(),
+                buffered_mut_errors: Default::default(),
                 buffered: Default::default(),
                 tainted_by_errors: None,
             }
@@ -2331,12 +2333,34 @@ pub fn buffer_move_error(
             }
         }
 
+        pub fn get_buffered_mut_error(
+            &mut self,
+            span: Span,
+        ) -> Option<(DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)> {
+            self.errors.buffered_mut_errors.remove(&span)
+        }
+
+        pub fn buffer_mut_error(
+            &mut self,
+            span: Span,
+            t: DiagnosticBuilder<'tcx, ErrorGuaranteed>,
+            count: usize,
+        ) {
+            self.errors.buffered_mut_errors.insert(span, (t, count));
+        }
+
         pub fn emit_errors(&mut self) -> Option<ErrorGuaranteed> {
             // Buffer any move errors that we collected and de-duplicated.
             for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) {
                 // We have already set tainted for this error, so just buffer it.
                 diag.buffer(&mut self.errors.buffered);
             }
+            for (_, (mut diag, count)) in std::mem::take(&mut self.errors.buffered_mut_errors) {
+                if count > 10 {
+                    diag.note(&format!("...and {} other attempted mutable borrows", count - 10));
+                }
+                diag.buffer(&mut self.errors.buffered);
+            }
 
             if !self.errors.buffered.is_empty() {
                 self.errors.buffered.sort_by_key(|diag| diag.sort_span);
index 585a54308c62e1c0bf07ab9c1478bd51ec0fca2c..e19a6fe0ee9bff2d5a0a5c28a7ace6c976c2fa9a 100644 (file)
@@ -365,12 +365,12 @@ pub fn span_labels(
         self
     }
 
-    pub fn replace_span_with(&mut self, after: Span) -> &mut Self {
+    pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self {
         let before = self.span.clone();
         self.set_span(after);
         for span_label in before.span_labels() {
             if let Some(label) = span_label.label {
-                if span_label.is_primary {
+                if span_label.is_primary && keep_label {
                     self.span.push_span_label(after, label);
                 } else {
                     self.span.push_span_label(span_label.span, label);
index 40aa64d9d40401719d595629467aaa9aa7544f44..3a38d7a966960bb8857ebe489d959a4cabdbe65f 100644 (file)
@@ -198,12 +198,12 @@ pub(super) fn emit_frag_parse_err(
         );
         if !e.span.is_dummy() {
             // early end of macro arm (#52866)
-            e.replace_span_with(parser.token.span.shrink_to_hi());
+            e.replace_span_with(parser.token.span.shrink_to_hi(), true);
         }
     }
     if e.span.is_dummy() {
         // Get around lack of span in error (#30128)
-        e.replace_span_with(site_span);
+        e.replace_span_with(site_span, true);
         if !parser.sess.source_map().is_imported(arm_span) {
             e.span_label(arm_span, "in this macro arm");
         }
index 06ab0e8d94470cdbbcd258be58665ba73bf597d0..7c21a1047bcbfc5c3a04de884663780a3b56f66f 100644 (file)
@@ -3237,7 +3237,7 @@ fn note_function_argument_obligation(
         })) = call_node
         {
             if Some(rcvr.span) == err.span.primary_span() {
-                err.replace_span_with(path.ident.span);
+                err.replace_span_with(path.ident.span, true);
             }
         }
         if let Some(Node::Expr(hir::Expr {
index 8198df91095f94acd111902c194f58d3cea735f4..1d579ccc90eec1eaaf9eb58209dc79f247c99c80 100644 (file)
@@ -22,11 +22,10 @@ fn main() {
         // Outputs require mutable places
 
         let v: Vec<u64> = vec![0, 1, 2];
+        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
         asm!("{}", in(reg) v[0]);
         asm!("{}", out(reg) v[0]);
-        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
         asm!("{}", inout(reg) v[0]);
-        //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
 
         // Sym operands must point to a function or static
 
index bd90461e52c17d750ea85c353e8c0384ae788a88..af89e5e91174e9e9d10ae65b4e360f3691e5de3d 100644 (file)
@@ -25,24 +25,20 @@ LL |         let mut y: u64 = 0;
    |                        +++
 
 error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
-  --> $DIR/type-check-5.rs:26:29
+  --> $DIR/type-check-5.rs:24:13
    |
 LL |         let v: Vec<u64> = vec![0, 1, 2];
-   |             - help: consider changing this to be mutable: `mut v`
-LL |         asm!("{}", in(reg) v[0]);
-LL |         asm!("{}", out(reg) v[0]);
-   |                             ^ cannot borrow as mutable
-
-error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
-  --> $DIR/type-check-5.rs:28:31
-   |
-LL |         let v: Vec<u64> = vec![0, 1, 2];
-   |             - help: consider changing this to be mutable: `mut v`
+   |             ^
+   |             |
+   |             not mutable
+   |             help: consider changing this to be mutable: `mut v`
 ...
+LL |         asm!("{}", out(reg) v[0]);
+   |                             - cannot borrow as mutable
 LL |         asm!("{}", inout(reg) v[0]);
-   |                               ^ cannot borrow as mutable
+   |                               - cannot borrow as mutable
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0381, E0596.
 For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/many-mutable-borrows.rs b/src/test/ui/borrowck/many-mutable-borrows.rs
new file mode 100644 (file)
index 0000000..3e6ea9d
--- /dev/null
@@ -0,0 +1,18 @@
+fn main() {
+    let v = Vec::new(); //~ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+    v.push(0);
+    v.push(0);
+    v.push(0);
+    v.push(0);
+    v.push(0);
+    v.push(0);
+    v.push(0);
+    v.push(0);
+    v.push(0);
+    v.push(0);
+    v.push(0);
+    v.push(0);
+    v.push(0);
+    v.push(0);
+    v.push(0);
+}
diff --git a/src/test/ui/borrowck/many-mutable-borrows.stderr b/src/test/ui/borrowck/many-mutable-borrows.stderr
new file mode 100644 (file)
index 0000000..25755d9
--- /dev/null
@@ -0,0 +1,32 @@
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+  --> $DIR/many-mutable-borrows.rs:2:9
+   |
+LL |     let v = Vec::new();
+   |         ^
+   |         |
+   |         not mutable
+   |         help: consider changing this to be mutable: `mut v`
+LL |     v.push(0);
+   |     --------- cannot borrow as mutable
+LL |     v.push(0);
+   |     --------- cannot borrow as mutable
+LL |     v.push(0);
+   |     --------- cannot borrow as mutable
+LL |     v.push(0);
+   |     --------- cannot borrow as mutable
+LL |     v.push(0);
+   |     --------- cannot borrow as mutable
+LL |     v.push(0);
+   |     --------- cannot borrow as mutable
+LL |     v.push(0);
+   |     --------- cannot borrow as mutable
+LL |     v.push(0);
+   |     --------- cannot borrow as mutable
+LL |     v.push(0);
+   |     --------- cannot borrow as mutable
+   |
+   = note: ...and 5 other attempted mutable borrows
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
index 7cdb16b282d540253dd756071d02611639dc3ef5..477a2aa48d5dcb42e3eab13b0ab0f5562327dab9 100644 (file)
@@ -2,15 +2,14 @@
 #![crate_type = "rlib"]
 
 pub fn f(b: &mut i32) {
-    //~^ NOTE the binding is already a mutable borrow
+    //~^ ERROR cannot borrow
+    //~| NOTE not mutable
     //~| NOTE the binding is already a mutable borrow
     h(&mut b);
-    //~^ ERROR cannot borrow
-    //~| NOTE cannot borrow as mutable
+    //~^ NOTE cannot borrow as mutable
     //~| HELP try removing `&mut` here
     g(&mut &mut b);
-    //~^ ERROR cannot borrow
-    //~| NOTE cannot borrow as mutable
+    //~^ NOTE cannot borrow as mutable
     //~| HELP try removing `&mut` here
 }
 
index 7782047574ce8e7b6b8ba9b6180c280fdf66d8bc..c6f75b1c0d022f5b7fb83d38a382a7fb4e3efc7a 100644 (file)
@@ -1,8 +1,14 @@
 error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
-  --> $DIR/mut-borrow-of-mut-ref.rs:7:7
+  --> $DIR/mut-borrow-of-mut-ref.rs:4:10
    |
+LL | pub fn f(b: &mut i32) {
+   |          ^ not mutable
+...
 LL |     h(&mut b);
-   |       ^^^^^^ cannot borrow as mutable
+   |       ------ cannot borrow as mutable
+...
+LL |     g(&mut &mut b);
+   |            ------ cannot borrow as mutable
    |
 note: the binding is already a mutable borrow
   --> $DIR/mut-borrow-of-mut-ref.rs:4:13
@@ -14,18 +20,6 @@ help: try removing `&mut` here
 LL -     h(&mut b);
 LL +     h(b);
    |
-
-error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
-  --> $DIR/mut-borrow-of-mut-ref.rs:11:12
-   |
-LL |     g(&mut &mut b);
-   |            ^^^^^^ cannot borrow as mutable
-   |
-note: the binding is already a mutable borrow
-  --> $DIR/mut-borrow-of-mut-ref.rs:4:13
-   |
-LL | pub fn f(b: &mut i32) {
-   |             ^^^^^^^^
 help: try removing `&mut` here
    |
 LL -     g(&mut &mut b);
@@ -33,13 +27,13 @@ LL +     g(&mut b);
    |
 
 error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
-  --> $DIR/mut-borrow-of-mut-ref.rs:18:12
+  --> $DIR/mut-borrow-of-mut-ref.rs:17:12
    |
 LL |     h(&mut &mut b);
    |            ^^^^^^ cannot borrow as mutable
    |
 note: the binding is already a mutable borrow
-  --> $DIR/mut-borrow-of-mut-ref.rs:17:13
+  --> $DIR/mut-borrow-of-mut-ref.rs:16:13
    |
 LL | pub fn g(b: &mut i32) {
    |             ^^^^^^^^
@@ -50,7 +44,7 @@ LL +     h(&mut b);
    |
 
 error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable
-  --> $DIR/mut-borrow-of-mut-ref.rs:35:5
+  --> $DIR/mut-borrow-of-mut-ref.rs:34:5
    |
 LL |     f.bar();
    |     ^^^^^^^ cannot borrow as mutable
@@ -60,6 +54,6 @@ help: consider making the binding mutable
 LL | pub fn baz(mut f: &mut String) {
    |            +++
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0596`.
index 5be0df1376135b91c11276ff0836b04878894188..82116425f06ca478b24ae570c54fd6287b8402bb 100644 (file)
@@ -50,9 +50,9 @@ fn ref_closure(mut x: (i32,)) {
     });
 }
 
-fn imm_local(x: (i32,)) {
-    &mut x; //~ ERROR
-    &mut x.0; //~ ERROR
+fn imm_local(x: (i32,)) { //~ ERROR
+    &mut x;
+    &mut x.0;
 }
 
 fn imm_capture(x: (i32,)) {
index 7a00ace3bb220331d78982298c826e2fc3f4e100..5da8e60db75932f201b113193a099fea4b42e445 100644 (file)
@@ -245,21 +245,17 @@ LL |         &mut x.0;
    |         ^^^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
-  --> $DIR/mutability-errors.rs:54:5
+  --> $DIR/mutability-errors.rs:53:14
    |
 LL | fn imm_local(x: (i32,)) {
-   |              - help: consider changing this to be mutable: `mut x`
-LL |     &mut x;
-   |     ^^^^^^ cannot borrow as mutable
-
-error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
-  --> $DIR/mutability-errors.rs:55:5
-   |
-LL | fn imm_local(x: (i32,)) {
-   |              - help: consider changing this to be mutable: `mut x`
+   |              ^
+   |              |
+   |              not mutable
+   |              help: consider changing this to be mutable: `mut x`
 LL |     &mut x;
+   |     ------ cannot borrow as mutable
 LL |     &mut x.0;
-   |     ^^^^^^^^ cannot borrow as mutable
+   |     -------- cannot borrow as mutable
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
   --> $DIR/mutability-errors.rs:60:9
@@ -357,7 +353,7 @@ error[E0596]: cannot borrow `X.0` as mutable, as `X` is an immutable static item
 LL |     &mut X.0;
    |     ^^^^^^^^ cannot borrow as mutable
 
-error: aborting due to 38 previous errors
+error: aborting due to 37 previous errors
 
 Some errors have detailed explanations: E0594, E0596.
 For more information about an error, try `rustc --explain E0594`.