1
Fork 0

Merge multiple mutable borrows of immutable binding errors

Fix #53466.
This commit is contained in:
Esteban Küber 2022-12-29 22:46:17 -08:00
parent bb6e76df06
commit 5bfcfeee2a
14 changed files with 199 additions and 93 deletions

View file

@ -12,7 +12,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
place: &str, place: &str,
borrow_place: &str, borrow_place: &str,
value_place: &str, value_place: &str,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
self.infcx.tcx.sess.create_err(crate::session_diagnostics::MoveBorrow { self.infcx.tcx.sess.create_err(crate::session_diagnostics::MoveBorrow {
place, place,
span, span,
@ -28,7 +28,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
desc: &str, desc: &str,
borrow_span: Span, borrow_span: Span,
borrow_desc: &str, borrow_desc: &str,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
span, span,
@ -50,7 +50,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
old_loan_span: Span, old_loan_span: Span,
old_opt_via: &str, old_opt_via: &str,
old_load_end_span: Option<Span>, old_load_end_span: Option<Span>,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let via = let via =
|msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) }; |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) };
let mut err = struct_span_err!( let mut err = struct_span_err!(
@ -98,7 +98,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
desc: &str, desc: &str,
old_loan_span: Span, old_loan_span: Span,
old_load_end_span: Option<Span>, old_load_end_span: Option<Span>,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
new_loan_span, new_loan_span,
@ -269,7 +269,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
&self, &self,
span: Span, span: Span,
desc: &str, desc: &str,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
struct_span_err!(self, span, E0594, "cannot assign to {}", desc) struct_span_err!(self, span, E0594, "cannot assign to {}", desc)
} }
@ -348,7 +348,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
span: Span, span: Span,
path: &str, path: &str,
reason: &str, reason: &str,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{}", path, reason,) struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{}", path, reason,)
} }
@ -359,7 +359,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
immutable_place: &str, immutable_place: &str,
immutable_section: &str, immutable_section: &str,
action: &str, action: &str,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
mutate_span, mutate_span,
@ -378,7 +378,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
&self, &self,
span: Span, span: Span,
yield_span: Span, yield_span: Span,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
span, span,
@ -392,7 +392,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
pub(crate) fn cannot_borrow_across_destructor( pub(crate) fn cannot_borrow_across_destructor(
&self, &self,
borrow_span: Span, borrow_span: Span,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
struct_span_err!( struct_span_err!(
self, self,
borrow_span, borrow_span,
@ -405,7 +405,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
&self, &self,
span: Span, span: Span,
path: &str, path: &str,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
struct_span_err!(self, span, E0597, "{} does not live long enough", path,) struct_span_err!(self, span, E0597, "{} does not live long enough", path,)
} }
@ -415,7 +415,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
return_kind: &str, return_kind: &str,
reference_desc: &str, reference_desc: &str,
path_desc: &str, path_desc: &str,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
span, span,
@ -440,7 +440,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
closure_kind: &str, closure_kind: &str,
borrowed_path: &str, borrowed_path: &str,
capture_span: Span, capture_span: Span,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self, self,
closure_span, closure_span,
@ -458,14 +458,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
pub(crate) fn thread_local_value_does_not_live_long_enough( pub(crate) fn thread_local_value_does_not_live_long_enough(
&self, &self,
span: Span, span: Span,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
struct_span_err!(self, span, E0712, "thread-local variable borrowed past end of function",) struct_span_err!(self, span, E0712, "thread-local variable borrowed past end of function",)
} }
pub(crate) fn temporary_value_borrowed_for_too_long( pub(crate) fn temporary_value_borrowed_for_too_long(
&self, &self,
span: Span, span: Span,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",) struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",)
} }

View file

@ -180,6 +180,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// the verbs used in some diagnostic messages. // the verbs used in some diagnostic messages.
let act; let act;
let acted_on; let acted_on;
let mut suggest = true;
let mut mut_error = None;
let mut count = 1;
let span = match error_access { let span = match error_access {
AccessKind::Mutate => { AccessKind::Mutate => {
@ -194,7 +197,41 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let borrow_spans = self.borrow_spans(span, location); let borrow_spans = self.borrow_spans(span, location);
let borrow_span = borrow_spans.args_or_use(); let borrow_span = borrow_spans.args_or_use();
err = self.cannot_borrow_path_as_mutable_because(borrow_span, &item_msg, &reason); 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( borrow_spans.var_span_label(
&mut err, &mut err,
format!( format!(
@ -203,6 +240,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
), ),
"mutable", "mutable",
); );
}
borrow_span borrow_span
} }
}; };
@ -276,8 +314,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
pat_span: _, pat_span: _,
}, },
)))) => { )))) => {
if suggest {
err.span_note(sp, "the binding is already a mutable borrow"); err.span_note(sp, "the binding is already a mutable borrow");
} }
}
_ => { _ => {
err.span_note( err.span_note(
decl.source_info.span, decl.source_info.span,
@ -333,7 +373,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let local_decl = &self.body.local_decls[local]; let local_decl = &self.body.local_decls[local];
assert_eq!(local_decl.mutability, Mutability::Not); assert_eq!(local_decl.mutability, Mutability::Not);
if count < 10 {
err.span_label(span, format!("cannot {act}")); err.span_label(span, format!("cannot {act}"));
}
if suggest {
err.span_suggestion( err.span_suggestion(
local_decl.source_info.span, local_decl.source_info.span,
"consider changing this to be mutable", "consider changing this to be mutable",
@ -345,6 +388,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err); self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err);
} }
} }
}
// Also suggest adding mut for upvars // Also suggest adding mut for upvars
PlaceRef { PlaceRef {
@ -615,8 +659,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
} }
} }
if let Some(span) = mut_error {
self.buffer_mut_error(span, err, count);
} else {
self.buffer_error(err); self.buffer_error(err);
} }
}
fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diagnostic, span: Span) { fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diagnostic, span: Span) {
let Some(adt) = ty.ty_adt_def() else { return }; let Some(adt) = ty.ty_adt_def() else { return };

View file

@ -2270,6 +2270,7 @@ mod error {
/// same primary span come out in a consistent order. /// same primary span come out in a consistent order.
buffered_move_errors: buffered_move_errors:
BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorGuaranteed>)>, BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorGuaranteed>)>,
buffered_mut_errors: FxHashMap<Span, (DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)>,
/// Diagnostics to be reported buffer. /// Diagnostics to be reported buffer.
buffered: Vec<Diagnostic>, buffered: Vec<Diagnostic>,
/// Set to Some if we emit an error during borrowck /// Set to Some if we emit an error during borrowck
@ -2281,6 +2282,7 @@ mod error {
BorrowckErrors { BorrowckErrors {
tcx, tcx,
buffered_move_errors: BTreeMap::new(), buffered_move_errors: BTreeMap::new(),
buffered_mut_errors: Default::default(),
buffered: Default::default(), buffered: Default::default(),
tainted_by_errors: None, tainted_by_errors: None,
} }
@ -2331,12 +2333,34 @@ mod 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> { pub fn emit_errors(&mut self) -> Option<ErrorGuaranteed> {
// Buffer any move errors that we collected and de-duplicated. // Buffer any move errors that we collected and de-duplicated.
for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) { for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) {
// We have already set tainted for this error, so just buffer it. // We have already set tainted for this error, so just buffer it.
diag.buffer(&mut self.errors.buffered); 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() { if !self.errors.buffered.is_empty() {
self.errors.buffered.sort_by_key(|diag| diag.sort_span); self.errors.buffered.sort_by_key(|diag| diag.sort_span);

View file

@ -365,12 +365,12 @@ impl Diagnostic {
self 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(); let before = self.span.clone();
self.set_span(after); self.set_span(after);
for span_label in before.span_labels() { for span_label in before.span_labels() {
if let Some(label) = span_label.label { 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); self.span.push_span_label(after, label);
} else { } else {
self.span.push_span_label(span_label.span, label); self.span.push_span_label(span_label.span, label);

View file

@ -198,12 +198,12 @@ pub(super) fn emit_frag_parse_err(
); );
if !e.span.is_dummy() { if !e.span.is_dummy() {
// early end of macro arm (#52866) // 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() { if e.span.is_dummy() {
// Get around lack of span in error (#30128) // 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) { if !parser.sess.source_map().is_imported(arm_span) {
e.span_label(arm_span, "in this macro arm"); e.span_label(arm_span, "in this macro arm");
} }

View file

@ -3237,7 +3237,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
})) = call_node })) = call_node
{ {
if Some(rcvr.span) == err.span.primary_span() { 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 { if let Some(Node::Expr(hir::Expr {

View file

@ -22,11 +22,10 @@ fn main() {
// Outputs require mutable places // Outputs require mutable places
let v: Vec<u64> = vec![0, 1, 2]; 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!("{}", in(reg) v[0]);
asm!("{}", out(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]); 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 // Sym operands must point to a function or static

View 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 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]; 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]); | not mutable
| ^ cannot borrow as mutable | help: consider changing this to be mutable: `mut v`
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`
... ...
LL | asm!("{}", out(reg) v[0]);
| - cannot borrow as mutable
LL | asm!("{}", inout(reg) v[0]); 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. Some errors have detailed explanations: E0381, E0596.
For more information about an error, try `rustc --explain E0381`. For more information about an error, try `rustc --explain E0381`.

View file

@ -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);
}

View file

@ -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`.

View file

@ -2,15 +2,14 @@
#![crate_type = "rlib"] #![crate_type = "rlib"]
pub fn f(b: &mut i32) { 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 //~| NOTE the binding is already a mutable borrow
h(&mut b); h(&mut b);
//~^ ERROR cannot borrow //~^ NOTE cannot borrow as mutable
//~| NOTE cannot borrow as mutable
//~| HELP try removing `&mut` here //~| HELP try removing `&mut` here
g(&mut &mut b); g(&mut &mut b);
//~^ ERROR cannot borrow //~^ NOTE cannot borrow as mutable
//~| NOTE cannot borrow as mutable
//~| HELP try removing `&mut` here //~| HELP try removing `&mut` here
} }

View file

@ -1,8 +1,14 @@
error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable 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); 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 note: the binding is already a mutable borrow
--> $DIR/mut-borrow-of-mut-ref.rs:4:13 --> $DIR/mut-borrow-of-mut-ref.rs:4:13
@ -14,18 +20,6 @@ help: try removing `&mut` here
LL - h(&mut b); LL - h(&mut b);
LL + h(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 help: try removing `&mut` here
| |
LL - g(&mut &mut b); 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 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); LL | h(&mut &mut b);
| ^^^^^^ cannot borrow as mutable | ^^^^^^ cannot borrow as mutable
| |
note: the binding is already a mutable borrow 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) { 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 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(); LL | f.bar();
| ^^^^^^^ cannot borrow as mutable | ^^^^^^^ cannot borrow as mutable
@ -60,6 +54,6 @@ help: consider making the binding mutable
LL | pub fn baz(mut f: &mut String) { 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`. For more information about this error, try `rustc --explain E0596`.

View file

@ -50,9 +50,9 @@ fn ref_closure(mut x: (i32,)) {
}); });
} }
fn imm_local(x: (i32,)) { fn imm_local(x: (i32,)) { //~ ERROR
&mut x; //~ ERROR &mut x;
&mut x.0; //~ ERROR &mut x.0;
} }
fn imm_capture(x: (i32,)) { fn imm_capture(x: (i32,)) {

View file

@ -245,21 +245,17 @@ LL | &mut x.0;
| ^^^^^^^^ cannot borrow as mutable | ^^^^^^^^ cannot borrow as mutable
error[E0596]: cannot borrow `x` as mutable, as it is not declared 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,)) { LL | fn imm_local(x: (i32,)) {
| - help: consider changing this to be mutable: `mut x` | ^
LL | &mut x; | |
| ^^^^^^ cannot borrow as mutable | not mutable
| help: consider changing this to be mutable: `mut x`
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`
LL | &mut x; LL | &mut x;
| ------ cannot borrow as mutable
LL | &mut x.0; 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 error[E0594]: cannot assign to `x`, as it is not declared as mutable
--> $DIR/mutability-errors.rs:60:9 --> $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; LL | &mut X.0;
| ^^^^^^^^ cannot borrow as mutable | ^^^^^^^^ 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. Some errors have detailed explanations: E0594, E0596.
For more information about an error, try `rustc --explain E0594`. For more information about an error, try `rustc --explain E0594`.