Rollup merge of #57102 - davidtwco:issue-57100, r=nikomatsakis
NLL: Add union justifications to conflicting borrows. Fixes #57100. This PR adds justifications to error messages for conflicting borrows of union fields. Where previously an error message would say ``cannot borrow `u.b` as mutable..``, it now says ``cannot borrow `u` (via `u.b`) as mutable..``. r? @pnkfelix
This commit is contained in:
commit
ca1e379090
16 changed files with 366 additions and 153 deletions
|
@ -557,12 +557,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
|
||||||
if new_loan.loan_path.has_fork(&old_loan.loan_path) && common.is_some() {
|
if new_loan.loan_path.has_fork(&old_loan.loan_path) && common.is_some() {
|
||||||
let nl = self.bccx.loan_path_to_string(&common.unwrap());
|
let nl = self.bccx.loan_path_to_string(&common.unwrap());
|
||||||
let ol = nl.clone();
|
let ol = nl.clone();
|
||||||
let new_loan_msg = format!(" (via `{}`)",
|
let new_loan_msg = self.bccx.loan_path_to_string(&new_loan.loan_path);
|
||||||
self.bccx.loan_path_to_string(
|
let old_loan_msg = self.bccx.loan_path_to_string(&old_loan.loan_path);
|
||||||
&new_loan.loan_path));
|
|
||||||
let old_loan_msg = format!(" (via `{}`)",
|
|
||||||
self.bccx.loan_path_to_string(
|
|
||||||
&old_loan.loan_path));
|
|
||||||
(nl, ol, new_loan_msg, old_loan_msg)
|
(nl, ol, new_loan_msg, old_loan_msg)
|
||||||
} else {
|
} else {
|
||||||
(self.bccx.loan_path_to_string(&new_loan.loan_path),
|
(self.bccx.loan_path_to_string(&new_loan.loan_path),
|
||||||
|
|
|
@ -327,10 +327,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
"closure"
|
"closure"
|
||||||
};
|
};
|
||||||
|
|
||||||
let desc_place = self.describe_place(place).unwrap_or_else(|| "_".to_owned());
|
let (desc_place, msg_place, msg_borrow, union_type_name) =
|
||||||
let tcx = self.infcx.tcx;
|
self.describe_place_for_conflicting_borrow(place, &issued_borrow.borrowed_place);
|
||||||
|
|
||||||
let first_borrow_desc;
|
|
||||||
|
|
||||||
let explanation = self.explain_why_borrow_contains_point(context, issued_borrow, None);
|
let explanation = self.explain_why_borrow_contains_point(context, issued_borrow, None);
|
||||||
let second_borrow_desc = if explanation.is_explained() {
|
let second_borrow_desc = if explanation.is_explained() {
|
||||||
|
@ -340,6 +338,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: supply non-"" `opt_via` when appropriate
|
// FIXME: supply non-"" `opt_via` when appropriate
|
||||||
|
let tcx = self.infcx.tcx;
|
||||||
|
let first_borrow_desc;
|
||||||
let mut err = match (
|
let mut err = match (
|
||||||
gen_borrow_kind,
|
gen_borrow_kind,
|
||||||
"immutable",
|
"immutable",
|
||||||
|
@ -353,12 +353,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
tcx.cannot_reborrow_already_borrowed(
|
tcx.cannot_reborrow_already_borrowed(
|
||||||
span,
|
span,
|
||||||
&desc_place,
|
&desc_place,
|
||||||
"",
|
&msg_place,
|
||||||
lft,
|
lft,
|
||||||
issued_span,
|
issued_span,
|
||||||
"it",
|
"it",
|
||||||
rgt,
|
rgt,
|
||||||
"",
|
&msg_borrow,
|
||||||
None,
|
None,
|
||||||
Origin::Mir,
|
Origin::Mir,
|
||||||
)
|
)
|
||||||
|
@ -368,12 +368,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
tcx.cannot_reborrow_already_borrowed(
|
tcx.cannot_reborrow_already_borrowed(
|
||||||
span,
|
span,
|
||||||
&desc_place,
|
&desc_place,
|
||||||
"",
|
&msg_place,
|
||||||
lft,
|
lft,
|
||||||
issued_span,
|
issued_span,
|
||||||
"it",
|
"it",
|
||||||
rgt,
|
rgt,
|
||||||
"",
|
&msg_borrow,
|
||||||
None,
|
None,
|
||||||
Origin::Mir,
|
Origin::Mir,
|
||||||
)
|
)
|
||||||
|
@ -384,9 +384,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
tcx.cannot_mutably_borrow_multiply(
|
tcx.cannot_mutably_borrow_multiply(
|
||||||
span,
|
span,
|
||||||
&desc_place,
|
&desc_place,
|
||||||
"",
|
&msg_place,
|
||||||
issued_span,
|
issued_span,
|
||||||
"",
|
&msg_borrow,
|
||||||
None,
|
None,
|
||||||
Origin::Mir,
|
Origin::Mir,
|
||||||
)
|
)
|
||||||
|
@ -510,12 +510,118 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if union_type_name != "" {
|
||||||
|
err.note(&format!(
|
||||||
|
"`{}` is a field of the union `{}`, so it overlaps the field `{}`",
|
||||||
|
msg_place, union_type_name, msg_borrow,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
explanation
|
explanation
|
||||||
.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, first_borrow_desc);
|
.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, first_borrow_desc);
|
||||||
|
|
||||||
err.buffer(&mut self.errors_buffer);
|
err.buffer(&mut self.errors_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the description of the root place for a conflicting borrow and the full
|
||||||
|
/// descriptions of the places that caused the conflict.
|
||||||
|
///
|
||||||
|
/// In the simplest case, where there are no unions involved, if a mutable borrow of `x` is
|
||||||
|
/// attempted while a shared borrow is live, then this function will return:
|
||||||
|
///
|
||||||
|
/// ("x", "", "")
|
||||||
|
///
|
||||||
|
/// In the simple union case, if a mutable borrow of a union field `x.z` is attempted while
|
||||||
|
/// a shared borrow of another field `x.y`, then this function will return:
|
||||||
|
///
|
||||||
|
/// ("x", "x.z", "x.y")
|
||||||
|
///
|
||||||
|
/// In the more complex union case, where the union is a field of a struct, then if a mutable
|
||||||
|
/// borrow of a union field in a struct `x.u.z` is attempted while a shared borrow of
|
||||||
|
/// another field `x.u.y`, then this function will return:
|
||||||
|
///
|
||||||
|
/// ("x.u", "x.u.z", "x.u.y")
|
||||||
|
///
|
||||||
|
/// This is used when creating error messages like below:
|
||||||
|
///
|
||||||
|
/// > cannot borrow `a.u` (via `a.u.z.c`) as immutable because it is also borrowed as
|
||||||
|
/// > mutable (via `a.u.s.b`) [E0502]
|
||||||
|
pub(super) fn describe_place_for_conflicting_borrow(
|
||||||
|
&self,
|
||||||
|
first_borrowed_place: &Place<'tcx>,
|
||||||
|
second_borrowed_place: &Place<'tcx>,
|
||||||
|
) -> (String, String, String, String) {
|
||||||
|
// Define a small closure that we can use to check if the type of a place
|
||||||
|
// is a union.
|
||||||
|
let is_union = |place: &Place<'tcx>| -> bool {
|
||||||
|
place.ty(self.mir, self.infcx.tcx)
|
||||||
|
.to_ty(self.infcx.tcx)
|
||||||
|
.ty_adt_def()
|
||||||
|
.map(|adt| adt.is_union())
|
||||||
|
.unwrap_or(false)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Start with an empty tuple, so we can use the functions on `Option` to reduce some
|
||||||
|
// code duplication (particularly around returning an empty description in the failure
|
||||||
|
// case).
|
||||||
|
Some(())
|
||||||
|
.filter(|_| {
|
||||||
|
// If we have a conflicting borrow of the same place, then we don't want to add
|
||||||
|
// an extraneous "via x.y" to our diagnostics, so filter out this case.
|
||||||
|
first_borrowed_place != second_borrowed_place
|
||||||
|
})
|
||||||
|
.and_then(|_| {
|
||||||
|
// We're going to want to traverse the first borrowed place to see if we can find
|
||||||
|
// field access to a union. If we find that, then we will keep the place of the
|
||||||
|
// union being accessed and the field that was being accessed so we can check the
|
||||||
|
// second borrowed place for the same union and a access to a different field.
|
||||||
|
let mut current = first_borrowed_place;
|
||||||
|
while let Place::Projection(box PlaceProjection { base, elem }) = current {
|
||||||
|
match elem {
|
||||||
|
ProjectionElem::Field(field, _) if is_union(base) => {
|
||||||
|
return Some((base, field));
|
||||||
|
},
|
||||||
|
_ => current = base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
})
|
||||||
|
.and_then(|(target_base, target_field)| {
|
||||||
|
// With the place of a union and a field access into it, we traverse the second
|
||||||
|
// borrowed place and look for a access to a different field of the same union.
|
||||||
|
let mut current = second_borrowed_place;
|
||||||
|
while let Place::Projection(box PlaceProjection { base, elem }) = current {
|
||||||
|
match elem {
|
||||||
|
ProjectionElem::Field(field, _) if {
|
||||||
|
is_union(base) && field != target_field && base == target_base
|
||||||
|
} => {
|
||||||
|
let desc_base = self.describe_place(base)
|
||||||
|
.unwrap_or_else(|| "_".to_owned());
|
||||||
|
let desc_first = self.describe_place(first_borrowed_place)
|
||||||
|
.unwrap_or_else(|| "_".to_owned());
|
||||||
|
let desc_second = self.describe_place(second_borrowed_place)
|
||||||
|
.unwrap_or_else(|| "_".to_owned());
|
||||||
|
|
||||||
|
// Also compute the name of the union type, eg. `Foo` so we
|
||||||
|
// can add a helpful note with it.
|
||||||
|
let ty = base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
|
||||||
|
|
||||||
|
return Some((desc_base, desc_first, desc_second, ty.to_string()));
|
||||||
|
},
|
||||||
|
_ => current = base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
// If we didn't find a field access into a union, or both places match, then
|
||||||
|
// only return the description of the first place.
|
||||||
|
let desc_place = self.describe_place(first_borrowed_place)
|
||||||
|
.unwrap_or_else(|| "_".to_owned());
|
||||||
|
(desc_place, "".to_string(), "".to_string(), "".to_string())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Reports StorageDeadOrDrop of `place` conflicts with `borrow`.
|
/// Reports StorageDeadOrDrop of `place` conflicts with `borrow`.
|
||||||
///
|
///
|
||||||
/// This means that some data referenced by `borrow` needs to live
|
/// This means that some data referenced by `borrow` needs to live
|
||||||
|
|
|
@ -138,13 +138,15 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
|
||||||
old_load_end_span: Option<Span>,
|
old_load_end_span: Option<Span>,
|
||||||
o: Origin,
|
o: Origin,
|
||||||
) -> DiagnosticBuilder<'cx> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
|
let via = |msg: &str|
|
||||||
|
if msg.is_empty() { msg.to_string() } else { format!(" (via `{}`)", msg) };
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
self,
|
self,
|
||||||
new_loan_span,
|
new_loan_span,
|
||||||
E0499,
|
E0499,
|
||||||
"cannot borrow `{}`{} as mutable more than once at a time{OGN}",
|
"cannot borrow `{}`{} as mutable more than once at a time{OGN}",
|
||||||
desc,
|
desc,
|
||||||
opt_via,
|
via(opt_via),
|
||||||
OGN = o
|
OGN = o
|
||||||
);
|
);
|
||||||
if old_loan_span == new_loan_span {
|
if old_loan_span == new_loan_span {
|
||||||
|
@ -164,11 +166,11 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
|
||||||
} else {
|
} else {
|
||||||
err.span_label(
|
err.span_label(
|
||||||
old_loan_span,
|
old_loan_span,
|
||||||
format!("first mutable borrow occurs here{}", old_opt_via),
|
format!("first mutable borrow occurs here{}", via(old_opt_via)),
|
||||||
);
|
);
|
||||||
err.span_label(
|
err.span_label(
|
||||||
new_loan_span,
|
new_loan_span,
|
||||||
format!("second mutable borrow occurs here{}", opt_via),
|
format!("second mutable borrow occurs here{}", via(opt_via)),
|
||||||
);
|
);
|
||||||
if let Some(old_load_end_span) = old_load_end_span {
|
if let Some(old_load_end_span) = old_load_end_span {
|
||||||
err.span_label(old_load_end_span, "first borrow ends here");
|
err.span_label(old_load_end_span, "first borrow ends here");
|
||||||
|
@ -292,27 +294,46 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
|
||||||
old_load_end_span: Option<Span>,
|
old_load_end_span: Option<Span>,
|
||||||
o: Origin,
|
o: Origin,
|
||||||
) -> DiagnosticBuilder<'cx> {
|
) -> DiagnosticBuilder<'cx> {
|
||||||
|
let via = |msg: &str|
|
||||||
|
if msg.is_empty() { msg.to_string() } else { format!(" (via `{}`)", msg) };
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
self,
|
self,
|
||||||
span,
|
span,
|
||||||
E0502,
|
E0502,
|
||||||
"cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}",
|
"cannot borrow `{}`{} as {} because {} is also borrowed \
|
||||||
|
as {}{}{OGN}",
|
||||||
desc_new,
|
desc_new,
|
||||||
msg_new,
|
via(msg_new),
|
||||||
kind_new,
|
kind_new,
|
||||||
noun_old,
|
noun_old,
|
||||||
kind_old,
|
kind_old,
|
||||||
msg_old,
|
via(msg_old),
|
||||||
OGN = o
|
OGN = o
|
||||||
);
|
);
|
||||||
err.span_label(span, format!("{} borrow occurs here{}", kind_new, msg_new));
|
|
||||||
err.span_label(
|
if msg_new == "" {
|
||||||
old_span,
|
// If `msg_new` is empty, then this isn't a borrow of a union field.
|
||||||
format!("{} borrow occurs here{}", kind_old, msg_old),
|
err.span_label(span, format!("{} borrow occurs here", kind_new));
|
||||||
);
|
err.span_label(old_span, format!("{} borrow occurs here", kind_old));
|
||||||
|
} else {
|
||||||
|
// If `msg_new` isn't empty, then this a borrow of a union field.
|
||||||
|
err.span_label(
|
||||||
|
span,
|
||||||
|
format!(
|
||||||
|
"{} borrow of `{}` -- which overlaps with `{}` -- occurs here",
|
||||||
|
kind_new, msg_new, msg_old,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
err.span_label(
|
||||||
|
old_span,
|
||||||
|
format!("{} borrow occurs here{}", kind_old, via(msg_old)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(old_load_end_span) = old_load_end_span {
|
if let Some(old_load_end_span) = old_load_end_span {
|
||||||
err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old));
|
err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.cancel_if_wrong_origin(err, o)
|
self.cancel_if_wrong_origin(err, o)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ error[E0502]: cannot borrow `foo` (via `foo.bar2`) as immutable because `foo` is
|
||||||
LL | let bar1 = &mut foo.bar1;
|
LL | let bar1 = &mut foo.bar1;
|
||||||
| -------- mutable borrow occurs here (via `foo.bar1`)
|
| -------- mutable borrow occurs here (via `foo.bar1`)
|
||||||
LL | let _foo1 = &foo.bar2; //~ ERROR cannot borrow
|
LL | let _foo1 = &foo.bar2; //~ ERROR cannot borrow
|
||||||
| ^^^^^^^^ immutable borrow occurs here (via `foo.bar2`)
|
| ^^^^^^^^ immutable borrow of `foo.bar2` -- which overlaps with `foo.bar1` -- occurs here
|
||||||
LL | *bar1;
|
LL | *bar1;
|
||||||
LL | }
|
LL | }
|
||||||
| - mutable borrow ends here
|
| - mutable borrow ends here
|
||||||
|
|
|
@ -61,7 +61,7 @@ error[E0502]: cannot borrow `a` (via `a.y`) as immutable because `a` is also bor
|
||||||
LL | let _x = &mut a.x;
|
LL | let _x = &mut a.x;
|
||||||
| --- mutable borrow occurs here (via `a.x`)
|
| --- mutable borrow occurs here (via `a.x`)
|
||||||
LL | let _y = &a.y; //[ast]~ ERROR cannot borrow
|
LL | let _y = &a.y; //[ast]~ ERROR cannot borrow
|
||||||
| ^^^ immutable borrow occurs here (via `a.y`)
|
| ^^^ immutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
|
||||||
...
|
...
|
||||||
LL | }
|
LL | }
|
||||||
| - mutable borrow ends here
|
| - mutable borrow ends here
|
||||||
|
@ -72,7 +72,7 @@ error[E0502]: cannot borrow `a` (via `a.y`) as mutable because `a` is also borro
|
||||||
LL | let _x = &a.x;
|
LL | let _x = &a.x;
|
||||||
| --- immutable borrow occurs here (via `a.x`)
|
| --- immutable borrow occurs here (via `a.x`)
|
||||||
LL | let _y = &mut a.y; //[ast]~ ERROR cannot borrow
|
LL | let _y = &mut a.y; //[ast]~ ERROR cannot borrow
|
||||||
| ^^^ mutable borrow occurs here (via `a.y`)
|
| ^^^ mutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
|
||||||
...
|
...
|
||||||
LL | }
|
LL | }
|
||||||
| - immutable borrow ends here
|
| - immutable borrow ends here
|
||||||
|
|
|
@ -83,14 +83,14 @@ fn borrow_after_mut_borrow() {
|
||||||
let mut a: Box<_> = box A { x: box 0, y: 1 };
|
let mut a: Box<_> = box A { x: box 0, y: 1 };
|
||||||
let _x = &mut a.x;
|
let _x = &mut a.x;
|
||||||
let _y = &a.y; //[ast]~ ERROR cannot borrow
|
let _y = &a.y; //[ast]~ ERROR cannot borrow
|
||||||
//[ast]~^ immutable borrow occurs here (via `a.y`)
|
//[ast]~^ immutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
|
||||||
use_mut(_x);
|
use_mut(_x);
|
||||||
}
|
}
|
||||||
fn mut_borrow_after_borrow() {
|
fn mut_borrow_after_borrow() {
|
||||||
let mut a: Box<_> = box A { x: box 0, y: 1 };
|
let mut a: Box<_> = box A { x: box 0, y: 1 };
|
||||||
let _x = &a.x;
|
let _x = &a.x;
|
||||||
let _y = &mut a.y; //[ast]~ ERROR cannot borrow
|
let _y = &mut a.y; //[ast]~ ERROR cannot borrow
|
||||||
//[ast]~^ mutable borrow occurs here (via `a.y`)
|
//[ast]~^ mutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
|
||||||
use_imm(_x);
|
use_imm(_x);
|
||||||
}
|
}
|
||||||
fn copy_after_move_nested() {
|
fn copy_after_move_nested() {
|
||||||
|
|
|
@ -1,132 +1,127 @@
|
||||||
error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable
|
error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable
|
||||||
--> $DIR/borrowck-union-borrow.rs:27:23
|
--> $DIR/borrowck-union-borrow.rs:25:23
|
||||||
|
|
|
|
||||||
LL | let ra = &u.a;
|
LL | let ra = &u.a;
|
||||||
| ---- immutable borrow occurs here
|
| ---- immutable borrow occurs here
|
||||||
LL | let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
|
LL | let rma = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
|
||||||
| ^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^ mutable borrow occurs here
|
||||||
LL | //[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
|
|
||||||
LL | drop(ra);
|
LL | drop(ra);
|
||||||
| -- immutable borrow later used here
|
| -- immutable borrow later used here
|
||||||
|
|
||||||
error[E0506]: cannot assign to `u.a` because it is borrowed
|
error[E0506]: cannot assign to `u.a` because it is borrowed
|
||||||
--> $DIR/borrowck-union-borrow.rs:33:13
|
--> $DIR/borrowck-union-borrow.rs:30:13
|
||||||
|
|
|
|
||||||
LL | let ra = &u.a;
|
LL | let ra = &u.a;
|
||||||
| ---- borrow of `u.a` occurs here
|
| ---- borrow of `u.a` occurs here
|
||||||
LL | u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
|
LL | u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
|
||||||
| ^^^^^^^ assignment to borrowed `u.a` occurs here
|
| ^^^^^^^ assignment to borrowed `u.a` occurs here
|
||||||
LL | //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
|
|
||||||
LL | drop(ra);
|
LL | drop(ra);
|
||||||
| -- borrow later used here
|
| -- borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `u.b` as mutable because it is also borrowed as immutable
|
error[E0502]: cannot borrow `u` (via `u.b`) as mutable because it is also borrowed as immutable (via `u.a`)
|
||||||
--> $DIR/borrowck-union-borrow.rs:50:23
|
--> $DIR/borrowck-union-borrow.rs:46:23
|
||||||
|
|
|
|
||||||
LL | let ra = &u.a;
|
LL | let ra = &u.a;
|
||||||
| ---- immutable borrow occurs here
|
| ---- immutable borrow occurs here (via `u.a`)
|
||||||
LL | let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
|
LL | let rmb = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
|
||||||
| ^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^ mutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here
|
||||||
LL | //[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable
|
|
||||||
LL | drop(ra);
|
LL | drop(ra);
|
||||||
| -- immutable borrow later used here
|
| -- immutable borrow later used here
|
||||||
|
|
|
||||||
|
= note: `u.b` is a field of the union `U`, so it overlaps the field `u.a`
|
||||||
|
|
||||||
error[E0506]: cannot assign to `u.b` because it is borrowed
|
error[E0506]: cannot assign to `u.b` because it is borrowed
|
||||||
--> $DIR/borrowck-union-borrow.rs:56:13
|
--> $DIR/borrowck-union-borrow.rs:51:13
|
||||||
|
|
|
|
||||||
LL | let ra = &u.a;
|
LL | let ra = &u.a;
|
||||||
| ---- borrow of `u.b` occurs here
|
| ---- borrow of `u.b` occurs here
|
||||||
LL | u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
|
LL | u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
|
||||||
| ^^^^^^^ assignment to borrowed `u.b` occurs here
|
| ^^^^^^^ assignment to borrowed `u.b` occurs here
|
||||||
LL | //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
|
|
||||||
LL | drop(ra);
|
LL | drop(ra);
|
||||||
| -- borrow later used here
|
| -- borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable
|
||||||
--> $DIR/borrowck-union-borrow.rs:63:22
|
--> $DIR/borrowck-union-borrow.rs:57:22
|
||||||
|
|
|
|
||||||
LL | let rma = &mut u.a;
|
LL | let rma = &mut u.a;
|
||||||
| -------- mutable borrow occurs here
|
| -------- mutable borrow occurs here
|
||||||
LL | let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
|
LL | let ra = &u.a; //~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
|
||||||
| ^^^^ immutable borrow occurs here
|
| ^^^^ immutable borrow occurs here
|
||||||
LL | //[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
|
|
||||||
LL | drop(rma);
|
LL | drop(rma);
|
||||||
| --- mutable borrow later used here
|
| --- mutable borrow later used here
|
||||||
|
|
||||||
error[E0503]: cannot use `u.a` because it was mutably borrowed
|
error[E0503]: cannot use `u.a` because it was mutably borrowed
|
||||||
--> $DIR/borrowck-union-borrow.rs:69:21
|
--> $DIR/borrowck-union-borrow.rs:62:21
|
||||||
|
|
|
|
||||||
LL | let ra = &mut u.a;
|
LL | let ra = &mut u.a;
|
||||||
| -------- borrow of `u.a` occurs here
|
| -------- borrow of `u.a` occurs here
|
||||||
LL | let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
|
LL | let a = u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed
|
||||||
| ^^^ use of borrowed `u.a`
|
| ^^^ use of borrowed `u.a`
|
||||||
LL | //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
|
|
||||||
LL | drop(ra);
|
LL | drop(ra);
|
||||||
| -- borrow later used here
|
| -- borrow later used here
|
||||||
|
|
||||||
error[E0499]: cannot borrow `u.a` as mutable more than once at a time
|
error[E0499]: cannot borrow `u.a` as mutable more than once at a time
|
||||||
--> $DIR/borrowck-union-borrow.rs:75:24
|
--> $DIR/borrowck-union-borrow.rs:67:24
|
||||||
|
|
|
|
||||||
LL | let rma = &mut u.a;
|
LL | let rma = &mut u.a;
|
||||||
| -------- first mutable borrow occurs here
|
| -------- first mutable borrow occurs here
|
||||||
LL | let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time
|
LL | let rma2 = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable more than once at a time
|
||||||
| ^^^^^^^^ second mutable borrow occurs here
|
| ^^^^^^^^ second mutable borrow occurs here
|
||||||
LL | //[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time
|
|
||||||
LL | drop(rma);
|
LL | drop(rma);
|
||||||
| --- first borrow later used here
|
| --- first borrow later used here
|
||||||
|
|
||||||
error[E0506]: cannot assign to `u.a` because it is borrowed
|
error[E0506]: cannot assign to `u.a` because it is borrowed
|
||||||
--> $DIR/borrowck-union-borrow.rs:81:13
|
--> $DIR/borrowck-union-borrow.rs:72:13
|
||||||
|
|
|
|
||||||
LL | let rma = &mut u.a;
|
LL | let rma = &mut u.a;
|
||||||
| -------- borrow of `u.a` occurs here
|
| -------- borrow of `u.a` occurs here
|
||||||
LL | u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
|
LL | u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
|
||||||
| ^^^^^^^ assignment to borrowed `u.a` occurs here
|
| ^^^^^^^ assignment to borrowed `u.a` occurs here
|
||||||
LL | //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
|
|
||||||
LL | drop(rma);
|
LL | drop(rma);
|
||||||
| --- borrow later used here
|
| --- borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `u.b` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `u` (via `u.b`) as immutable because it is also borrowed as mutable (via `u.a`)
|
||||||
--> $DIR/borrowck-union-borrow.rs:88:22
|
--> $DIR/borrowck-union-borrow.rs:78:22
|
||||||
|
|
|
|
||||||
LL | let rma = &mut u.a;
|
LL | let rma = &mut u.a;
|
||||||
| -------- mutable borrow occurs here
|
| -------- mutable borrow occurs here (via `u.a`)
|
||||||
LL | let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
|
LL | let rb = &u.b; //~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
|
||||||
| ^^^^ immutable borrow occurs here
|
| ^^^^ immutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here
|
||||||
LL | //[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable
|
|
||||||
LL | drop(rma);
|
LL | drop(rma);
|
||||||
| --- mutable borrow later used here
|
| --- mutable borrow later used here
|
||||||
|
|
|
||||||
|
= note: `u.b` is a field of the union `U`, so it overlaps the field `u.a`
|
||||||
|
|
||||||
error[E0503]: cannot use `u.b` because it was mutably borrowed
|
error[E0503]: cannot use `u.b` because it was mutably borrowed
|
||||||
--> $DIR/borrowck-union-borrow.rs:94:21
|
--> $DIR/borrowck-union-borrow.rs:83:21
|
||||||
|
|
|
|
||||||
LL | let ra = &mut u.a;
|
LL | let ra = &mut u.a;
|
||||||
| -------- borrow of `u.a` occurs here
|
| -------- borrow of `u.a` occurs here
|
||||||
LL | let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed
|
LL | let b = u.b; //~ ERROR cannot use `u.b` because it was mutably borrowed
|
||||||
| ^^^ use of borrowed `u.a`
|
| ^^^ use of borrowed `u.a`
|
||||||
...
|
LL |
|
||||||
LL | drop(ra);
|
LL | drop(ra);
|
||||||
| -- borrow later used here
|
| -- borrow later used here
|
||||||
|
|
||||||
error[E0499]: cannot borrow `u.b` as mutable more than once at a time
|
error[E0499]: cannot borrow `u` (via `u.b`) as mutable more than once at a time
|
||||||
--> $DIR/borrowck-union-borrow.rs:101:24
|
--> $DIR/borrowck-union-borrow.rs:89:24
|
||||||
|
|
|
|
||||||
LL | let rma = &mut u.a;
|
LL | let rma = &mut u.a;
|
||||||
| -------- first mutable borrow occurs here
|
| -------- first mutable borrow occurs here (via `u.a`)
|
||||||
LL | let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
|
LL | let rmb2 = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
|
||||||
| ^^^^^^^^ second mutable borrow occurs here
|
| ^^^^^^^^ second mutable borrow occurs here (via `u.b`)
|
||||||
LL | //[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time
|
|
||||||
LL | drop(rma);
|
LL | drop(rma);
|
||||||
| --- first borrow later used here
|
| --- first borrow later used here
|
||||||
|
|
|
||||||
|
= note: `u.b` is a field of the union `U`, so it overlaps the field `u.a`
|
||||||
|
|
||||||
error[E0506]: cannot assign to `u.b` because it is borrowed
|
error[E0506]: cannot assign to `u.b` because it is borrowed
|
||||||
--> $DIR/borrowck-union-borrow.rs:107:13
|
--> $DIR/borrowck-union-borrow.rs:94:13
|
||||||
|
|
|
|
||||||
LL | let rma = &mut u.a;
|
LL | let rma = &mut u.a;
|
||||||
| -------- borrow of `u.b` occurs here
|
| -------- borrow of `u.b` occurs here
|
||||||
LL | u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
|
LL | u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
|
||||||
| ^^^^^^^ assignment to borrowed `u.b` occurs here
|
| ^^^^^^^ assignment to borrowed `u.b` occurs here
|
||||||
LL | //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
|
|
||||||
LL | drop(rma);
|
LL | drop(rma);
|
||||||
| --- borrow later used here
|
| --- borrow later used here
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
// revisions: ast mir
|
|
||||||
//[mir]compile-flags: -Z borrowck=mir
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
union U {
|
union U {
|
||||||
|
@ -24,14 +22,12 @@ fn main() {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let ra = &u.a;
|
let ra = &u.a;
|
||||||
let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
|
let rma = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
|
||||||
//[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
|
|
||||||
drop(ra);
|
drop(ra);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let ra = &u.a;
|
let ra = &u.a;
|
||||||
u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
|
u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
|
||||||
//[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
|
|
||||||
drop(ra);
|
drop(ra);
|
||||||
}
|
}
|
||||||
// Imm borrow, other field
|
// Imm borrow, other field
|
||||||
|
@ -47,65 +43,55 @@ fn main() {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let ra = &u.a;
|
let ra = &u.a;
|
||||||
let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
|
let rmb = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
|
||||||
//[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable
|
|
||||||
drop(ra);
|
drop(ra);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let ra = &u.a;
|
let ra = &u.a;
|
||||||
u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
|
u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
|
||||||
//[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
|
|
||||||
drop(ra);
|
drop(ra);
|
||||||
}
|
}
|
||||||
// Mut borrow, same field
|
// Mut borrow, same field
|
||||||
{
|
{
|
||||||
let rma = &mut u.a;
|
let rma = &mut u.a;
|
||||||
let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
|
let ra = &u.a; //~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
|
||||||
//[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
|
|
||||||
drop(rma);
|
drop(rma);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let ra = &mut u.a;
|
let ra = &mut u.a;
|
||||||
let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
|
let a = u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed
|
||||||
//[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
|
|
||||||
drop(ra);
|
drop(ra);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let rma = &mut u.a;
|
let rma = &mut u.a;
|
||||||
let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time
|
let rma2 = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable more than once at a time
|
||||||
//[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time
|
|
||||||
drop(rma);
|
drop(rma);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let rma = &mut u.a;
|
let rma = &mut u.a;
|
||||||
u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
|
u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
|
||||||
//[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
|
|
||||||
drop(rma);
|
drop(rma);
|
||||||
}
|
}
|
||||||
// Mut borrow, other field
|
// Mut borrow, other field
|
||||||
{
|
{
|
||||||
let rma = &mut u.a;
|
let rma = &mut u.a;
|
||||||
let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
|
let rb = &u.b; //~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
|
||||||
//[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable
|
|
||||||
drop(rma);
|
drop(rma);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let ra = &mut u.a;
|
let ra = &mut u.a;
|
||||||
let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed
|
let b = u.b; //~ ERROR cannot use `u.b` because it was mutably borrowed
|
||||||
//[mir]~^ ERROR cannot use `u.b` because it was mutably borrowed
|
|
||||||
|
|
||||||
drop(ra);
|
drop(ra);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let rma = &mut u.a;
|
let rma = &mut u.a;
|
||||||
let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
|
let rmb2 = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
|
||||||
//[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time
|
|
||||||
drop(rma);
|
drop(rma);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let rma = &mut u.a;
|
let rma = &mut u.a;
|
||||||
u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
|
u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
|
||||||
//[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
|
|
||||||
drop(rma);
|
drop(rma);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,115 +1,115 @@
|
||||||
error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable
|
error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable
|
||||||
--> $DIR/borrowck-union-borrow.rs:27:28
|
--> $DIR/borrowck-union-borrow.rs:25:28
|
||||||
|
|
|
|
||||||
LL | let ra = &u.a;
|
LL | let ra = &u.a;
|
||||||
| --- immutable borrow occurs here
|
| --- immutable borrow occurs here
|
||||||
LL | let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
|
LL | let rma = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
|
||||||
| ^^^ mutable borrow occurs here
|
| ^^^ mutable borrow occurs here
|
||||||
...
|
LL | drop(ra);
|
||||||
LL | }
|
LL | }
|
||||||
| - immutable borrow ends here
|
| - immutable borrow ends here
|
||||||
|
|
||||||
error[E0506]: cannot assign to `u.a` because it is borrowed
|
error[E0506]: cannot assign to `u.a` because it is borrowed
|
||||||
--> $DIR/borrowck-union-borrow.rs:33:13
|
--> $DIR/borrowck-union-borrow.rs:30:13
|
||||||
|
|
|
|
||||||
LL | let ra = &u.a;
|
LL | let ra = &u.a;
|
||||||
| --- borrow of `u.a` occurs here
|
| --- borrow of `u.a` occurs here
|
||||||
LL | u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
|
LL | u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
|
||||||
| ^^^^^^^ assignment to borrowed `u.a` occurs here
|
| ^^^^^^^ assignment to borrowed `u.a` occurs here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
|
error[E0502]: cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
|
||||||
--> $DIR/borrowck-union-borrow.rs:50:28
|
--> $DIR/borrowck-union-borrow.rs:46:28
|
||||||
|
|
|
|
||||||
LL | let ra = &u.a;
|
LL | let ra = &u.a;
|
||||||
| --- immutable borrow occurs here (via `u.a`)
|
| --- immutable borrow occurs here (via `u.a`)
|
||||||
LL | let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
|
LL | let rmb = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
|
||||||
| ^^^ mutable borrow occurs here (via `u.b`)
|
| ^^^ mutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here
|
||||||
...
|
LL | drop(ra);
|
||||||
LL | }
|
LL | }
|
||||||
| - immutable borrow ends here
|
| - immutable borrow ends here
|
||||||
|
|
||||||
error[E0506]: cannot assign to `u.b` because it is borrowed
|
error[E0506]: cannot assign to `u.b` because it is borrowed
|
||||||
--> $DIR/borrowck-union-borrow.rs:56:13
|
--> $DIR/borrowck-union-borrow.rs:51:13
|
||||||
|
|
|
|
||||||
LL | let ra = &u.a;
|
LL | let ra = &u.a;
|
||||||
| --- borrow of `u.b` occurs here
|
| --- borrow of `u.b` occurs here
|
||||||
LL | u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
|
LL | u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
|
||||||
| ^^^^^^^ assignment to borrowed `u.b` occurs here
|
| ^^^^^^^ assignment to borrowed `u.b` occurs here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable
|
||||||
--> $DIR/borrowck-union-borrow.rs:63:23
|
--> $DIR/borrowck-union-borrow.rs:57:23
|
||||||
|
|
|
|
||||||
LL | let rma = &mut u.a;
|
LL | let rma = &mut u.a;
|
||||||
| --- mutable borrow occurs here
|
| --- mutable borrow occurs here
|
||||||
LL | let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
|
LL | let ra = &u.a; //~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
|
||||||
| ^^^ immutable borrow occurs here
|
| ^^^ immutable borrow occurs here
|
||||||
...
|
LL | drop(rma);
|
||||||
LL | }
|
LL | }
|
||||||
| - mutable borrow ends here
|
| - mutable borrow ends here
|
||||||
|
|
||||||
error[E0503]: cannot use `u.a` because it was mutably borrowed
|
error[E0503]: cannot use `u.a` because it was mutably borrowed
|
||||||
--> $DIR/borrowck-union-borrow.rs:69:17
|
--> $DIR/borrowck-union-borrow.rs:62:17
|
||||||
|
|
|
|
||||||
LL | let ra = &mut u.a;
|
LL | let ra = &mut u.a;
|
||||||
| --- borrow of `u.a` occurs here
|
| --- borrow of `u.a` occurs here
|
||||||
LL | let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
|
LL | let a = u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed
|
||||||
| ^ use of borrowed `u.a`
|
| ^ use of borrowed `u.a`
|
||||||
|
|
||||||
error[E0499]: cannot borrow `u.a` as mutable more than once at a time
|
error[E0499]: cannot borrow `u.a` as mutable more than once at a time
|
||||||
--> $DIR/borrowck-union-borrow.rs:75:29
|
--> $DIR/borrowck-union-borrow.rs:67:29
|
||||||
|
|
|
|
||||||
LL | let rma = &mut u.a;
|
LL | let rma = &mut u.a;
|
||||||
| --- first mutable borrow occurs here
|
| --- first mutable borrow occurs here
|
||||||
LL | let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time
|
LL | let rma2 = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable more than once at a time
|
||||||
| ^^^ second mutable borrow occurs here
|
| ^^^ second mutable borrow occurs here
|
||||||
...
|
LL | drop(rma);
|
||||||
LL | }
|
LL | }
|
||||||
| - first borrow ends here
|
| - first borrow ends here
|
||||||
|
|
||||||
error[E0506]: cannot assign to `u.a` because it is borrowed
|
error[E0506]: cannot assign to `u.a` because it is borrowed
|
||||||
--> $DIR/borrowck-union-borrow.rs:81:13
|
--> $DIR/borrowck-union-borrow.rs:72:13
|
||||||
|
|
|
|
||||||
LL | let rma = &mut u.a;
|
LL | let rma = &mut u.a;
|
||||||
| --- borrow of `u.a` occurs here
|
| --- borrow of `u.a` occurs here
|
||||||
LL | u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
|
LL | u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
|
||||||
| ^^^^^^^ assignment to borrowed `u.a` occurs here
|
| ^^^^^^^ assignment to borrowed `u.a` occurs here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
|
error[E0502]: cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
|
||||||
--> $DIR/borrowck-union-borrow.rs:88:23
|
--> $DIR/borrowck-union-borrow.rs:78:23
|
||||||
|
|
|
|
||||||
LL | let rma = &mut u.a;
|
LL | let rma = &mut u.a;
|
||||||
| --- mutable borrow occurs here (via `u.a`)
|
| --- mutable borrow occurs here (via `u.a`)
|
||||||
LL | let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
|
LL | let rb = &u.b; //~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
|
||||||
| ^^^ immutable borrow occurs here (via `u.b`)
|
| ^^^ immutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here
|
||||||
...
|
LL | drop(rma);
|
||||||
LL | }
|
LL | }
|
||||||
| - mutable borrow ends here
|
| - mutable borrow ends here
|
||||||
|
|
||||||
error[E0503]: cannot use `u.b` because it was mutably borrowed
|
error[E0503]: cannot use `u.b` because it was mutably borrowed
|
||||||
--> $DIR/borrowck-union-borrow.rs:94:17
|
--> $DIR/borrowck-union-borrow.rs:83:17
|
||||||
|
|
|
|
||||||
LL | let ra = &mut u.a;
|
LL | let ra = &mut u.a;
|
||||||
| --- borrow of `u.a` occurs here
|
| --- borrow of `u.a` occurs here
|
||||||
LL | let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed
|
LL | let b = u.b; //~ ERROR cannot use `u.b` because it was mutably borrowed
|
||||||
| ^ use of borrowed `u.a`
|
| ^ use of borrowed `u.a`
|
||||||
|
|
||||||
error[E0499]: cannot borrow `u` (via `u.b`) as mutable more than once at a time
|
error[E0499]: cannot borrow `u` (via `u.b`) as mutable more than once at a time
|
||||||
--> $DIR/borrowck-union-borrow.rs:101:29
|
--> $DIR/borrowck-union-borrow.rs:89:29
|
||||||
|
|
|
|
||||||
LL | let rma = &mut u.a;
|
LL | let rma = &mut u.a;
|
||||||
| --- first mutable borrow occurs here (via `u.a`)
|
| --- first mutable borrow occurs here (via `u.a`)
|
||||||
LL | let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
|
LL | let rmb2 = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
|
||||||
| ^^^ second mutable borrow occurs here (via `u.b`)
|
| ^^^ second mutable borrow occurs here (via `u.b`)
|
||||||
...
|
LL | drop(rma);
|
||||||
LL | }
|
LL | }
|
||||||
| - first borrow ends here
|
| - first borrow ends here
|
||||||
|
|
||||||
error[E0506]: cannot assign to `u.b` because it is borrowed
|
error[E0506]: cannot assign to `u.b` because it is borrowed
|
||||||
--> $DIR/borrowck-union-borrow.rs:107:13
|
--> $DIR/borrowck-union-borrow.rs:94:13
|
||||||
|
|
|
|
||||||
LL | let rma = &mut u.a;
|
LL | let rma = &mut u.a;
|
||||||
| --- borrow of `u.b` occurs here
|
| --- borrow of `u.b` occurs here
|
||||||
LL | u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
|
LL | u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
|
||||||
| ^^^^^^^ assignment to borrowed `u.b` occurs here
|
| ^^^^^^^ assignment to borrowed `u.b` occurs here
|
||||||
|
|
||||||
error: aborting due to 12 previous errors
|
error: aborting due to 12 previous errors
|
|
@ -13,7 +13,7 @@ error[E0502]: cannot borrow `foo` (via `foo.b`) as immutable because `foo` is al
|
||||||
--> $DIR/issue-17263.rs:21:32
|
--> $DIR/issue-17263.rs:21:32
|
||||||
|
|
|
|
||||||
LL | let (c, d) = (&mut foo.a, &foo.b);
|
LL | let (c, d) = (&mut foo.a, &foo.b);
|
||||||
| ----- ^^^^^ immutable borrow occurs here (via `foo.b`)
|
| ----- ^^^^^ immutable borrow of `foo.b` -- which overlaps with `foo.a` -- occurs here
|
||||||
| |
|
| |
|
||||||
| mutable borrow occurs here (via `foo.a`)
|
| mutable borrow occurs here (via `foo.a`)
|
||||||
...
|
...
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
|
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default)]
|
#[derive(Clone, Copy, Default)]
|
||||||
struct S {
|
struct S {
|
||||||
a: u8,
|
a: u8,
|
||||||
|
@ -25,8 +27,7 @@ fn main() {
|
||||||
*mref = 22;
|
*mref = 22;
|
||||||
|
|
||||||
let nref = &u.z.c;
|
let nref = &u.z.c;
|
||||||
//~^ ERROR cannot borrow `u.z.c` as immutable because it is also borrowed as mutable [E0502]
|
//~^ ERROR cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`) [E0502]
|
||||||
println!("{} {}", mref, nref)
|
println!("{} {}", mref, nref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
error[E0502]: cannot borrow `u.z.c` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`)
|
||||||
--> $DIR/issue-45157.rs:27:20
|
--> $DIR/issue-45157.rs:29:20
|
||||||
|
|
|
|
||||||
LL | let mref = &mut u.s.a;
|
LL | let mref = &mut u.s.a;
|
||||||
| ---------- mutable borrow occurs here
|
| ---------- mutable borrow occurs here (via `u.s.a`)
|
||||||
...
|
...
|
||||||
LL | let nref = &u.z.c;
|
LL | let nref = &u.z.c;
|
||||||
| ^^^^^^ immutable borrow occurs here
|
| ^^^^^^ immutable borrow of `u.z.c` -- which overlaps with `u.s.a` -- occurs here
|
||||||
LL | //~^ ERROR cannot borrow `u.z.c` as immutable because it is also borrowed as mutable [E0502]
|
LL | //~^ ERROR cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`) [E0502]
|
||||||
LL | println!("{} {}", mref, nref)
|
LL | println!("{} {}", mref, nref)
|
||||||
| ---- mutable borrow later used here
|
| ---- mutable borrow later used here
|
||||||
|
|
|
||||||
|
= note: `u.z.c` is a field of the union `U`, so it overlaps the field `u.s.a`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
69
src/test/ui/nll/issue-57100.rs
Normal file
69
src/test/ui/nll/issue-57100.rs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#![allow(unused)]
|
||||||
|
#![feature(nll)]
|
||||||
|
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
|
// This tests the error messages for borrows of union fields when the unions are embedded in other
|
||||||
|
// structs or unions.
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Default)]
|
||||||
|
struct Leaf {
|
||||||
|
l1_u8: u8,
|
||||||
|
l2_u8: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
union First {
|
||||||
|
f1_leaf: Leaf,
|
||||||
|
f2_leaf: Leaf,
|
||||||
|
f3_union: Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
union Second {
|
||||||
|
s1_leaf: Leaf,
|
||||||
|
s2_leaf: Leaf,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Root {
|
||||||
|
r1_u8: u8,
|
||||||
|
r2_union: First,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Borrow a different field of the nested union.
|
||||||
|
fn nested_union() {
|
||||||
|
unsafe {
|
||||||
|
let mut r = Root {
|
||||||
|
r1_u8: 3,
|
||||||
|
r2_union: First { f3_union: Second { s2_leaf: Leaf { l1_u8: 8, l2_u8: 4 } } }
|
||||||
|
};
|
||||||
|
|
||||||
|
let mref = &mut r.r2_union.f3_union.s1_leaf.l1_u8;
|
||||||
|
// ^^^^^^^
|
||||||
|
*mref = 22;
|
||||||
|
let nref = &r.r2_union.f3_union.s2_leaf.l1_u8;
|
||||||
|
// ^^^^^^^
|
||||||
|
//~^^ ERROR cannot borrow `r.r2_union.f3_union` (via `r.r2_union.f3_union.s2_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f3_union.s1_leaf.l1_u8`) [E0502]
|
||||||
|
println!("{} {}", mref, nref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Borrow a different field of the first union.
|
||||||
|
fn first_union() {
|
||||||
|
unsafe {
|
||||||
|
let mut r = Root {
|
||||||
|
r1_u8: 3,
|
||||||
|
r2_union: First { f3_union: Second { s2_leaf: Leaf { l1_u8: 8, l2_u8: 4 } } }
|
||||||
|
};
|
||||||
|
|
||||||
|
let mref = &mut r.r2_union.f2_leaf.l1_u8;
|
||||||
|
// ^^^^^^^
|
||||||
|
*mref = 22;
|
||||||
|
let nref = &r.r2_union.f1_leaf.l1_u8;
|
||||||
|
// ^^^^^^^
|
||||||
|
//~^^ ERROR cannot borrow `r.r2_union` (via `r.r2_union.f1_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f2_leaf.l1_u8`) [E0502]
|
||||||
|
println!("{} {}", mref, nref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
31
src/test/ui/nll/issue-57100.stderr
Normal file
31
src/test/ui/nll/issue-57100.stderr
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
error[E0502]: cannot borrow `r.r2_union.f3_union` (via `r.r2_union.f3_union.s2_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f3_union.s1_leaf.l1_u8`)
|
||||||
|
--> $DIR/issue-57100.rs:44:20
|
||||||
|
|
|
||||||
|
LL | let mref = &mut r.r2_union.f3_union.s1_leaf.l1_u8;
|
||||||
|
| -------------------------------------- mutable borrow occurs here (via `r.r2_union.f3_union.s1_leaf.l1_u8`)
|
||||||
|
...
|
||||||
|
LL | let nref = &r.r2_union.f3_union.s2_leaf.l1_u8;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ immutable borrow of `r.r2_union.f3_union.s2_leaf.l1_u8` -- which overlaps with `r.r2_union.f3_union.s1_leaf.l1_u8` -- occurs here
|
||||||
|
...
|
||||||
|
LL | println!("{} {}", mref, nref)
|
||||||
|
| ---- mutable borrow later used here
|
||||||
|
|
|
||||||
|
= note: `r.r2_union.f3_union.s2_leaf.l1_u8` is a field of the union `Second`, so it overlaps the field `r.r2_union.f3_union.s1_leaf.l1_u8`
|
||||||
|
|
||||||
|
error[E0502]: cannot borrow `r.r2_union` (via `r.r2_union.f1_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f2_leaf.l1_u8`)
|
||||||
|
--> $DIR/issue-57100.rs:62:20
|
||||||
|
|
|
||||||
|
LL | let mref = &mut r.r2_union.f2_leaf.l1_u8;
|
||||||
|
| ----------------------------- mutable borrow occurs here (via `r.r2_union.f2_leaf.l1_u8`)
|
||||||
|
...
|
||||||
|
LL | let nref = &r.r2_union.f1_leaf.l1_u8;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ immutable borrow of `r.r2_union.f1_leaf.l1_u8` -- which overlaps with `r.r2_union.f2_leaf.l1_u8` -- occurs here
|
||||||
|
...
|
||||||
|
LL | println!("{} {}", mref, nref)
|
||||||
|
| ---- mutable borrow later used here
|
||||||
|
|
|
||||||
|
= note: `r.r2_union.f1_leaf.l1_u8` is a field of the union `First`, so it overlaps the field `r.r2_union.f2_leaf.l1_u8`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0502`.
|
|
@ -1,12 +1,14 @@
|
||||||
error[E0502]: cannot borrow `u.y` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`)
|
||||||
--> $DIR/union-borrow-move-parent-sibling.rs:15:13
|
--> $DIR/union-borrow-move-parent-sibling.rs:15:13
|
||||||
|
|
|
|
||||||
LL | let a = &mut u.x.0;
|
LL | let a = &mut u.x.0;
|
||||||
| ---------- mutable borrow occurs here
|
| ---------- mutable borrow occurs here (via `u.x.0`)
|
||||||
LL | let b = &u.y; //~ ERROR cannot borrow `u.y`
|
LL | let b = &u.y; //~ ERROR cannot borrow `u.y`
|
||||||
| ^^^^ immutable borrow occurs here
|
| ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
|
||||||
LL | use_borrow(a);
|
LL | use_borrow(a);
|
||||||
| - mutable borrow later used here
|
| - mutable borrow later used here
|
||||||
|
|
|
||||||
|
= note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0`
|
||||||
|
|
||||||
error[E0382]: use of moved value: `u`
|
error[E0382]: use of moved value: `u`
|
||||||
--> $DIR/union-borrow-move-parent-sibling.rs:22:13
|
--> $DIR/union-borrow-move-parent-sibling.rs:22:13
|
||||||
|
@ -18,15 +20,17 @@ LL | let b = u.y; //~ ERROR use of moved value: `u.y`
|
||||||
|
|
|
|
||||||
= note: move occurs because `u` has type `U`, which does not implement the `Copy` trait
|
= note: move occurs because `u` has type `U`, which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0502]: cannot borrow `u.y` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`)
|
||||||
--> $DIR/union-borrow-move-parent-sibling.rs:28:13
|
--> $DIR/union-borrow-move-parent-sibling.rs:28:13
|
||||||
|
|
|
|
||||||
LL | let a = &mut (u.x.0).0;
|
LL | let a = &mut (u.x.0).0;
|
||||||
| -------------- mutable borrow occurs here
|
| -------------- mutable borrow occurs here (via `u.x.0.0`)
|
||||||
LL | let b = &u.y; //~ ERROR cannot borrow `u.y`
|
LL | let b = &u.y; //~ ERROR cannot borrow `u.y`
|
||||||
| ^^^^ immutable borrow occurs here
|
| ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
|
||||||
LL | use_borrow(a);
|
LL | use_borrow(a);
|
||||||
| - mutable borrow later used here
|
| - mutable borrow later used here
|
||||||
|
|
|
||||||
|
= note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0`
|
||||||
|
|
||||||
error[E0382]: use of moved value: `u`
|
error[E0382]: use of moved value: `u`
|
||||||
--> $DIR/union-borrow-move-parent-sibling.rs:35:13
|
--> $DIR/union-borrow-move-parent-sibling.rs:35:13
|
||||||
|
@ -38,15 +42,17 @@ LL | let b = u.y; //~ ERROR use of moved value: `u.y`
|
||||||
|
|
|
|
||||||
= note: move occurs because `u` has type `U`, which does not implement the `Copy` trait
|
= note: move occurs because `u` has type `U`, which does not implement the `Copy` trait
|
||||||
|
|
||||||
error[E0502]: cannot borrow `u.x` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `*u.y`)
|
||||||
--> $DIR/union-borrow-move-parent-sibling.rs:41:13
|
--> $DIR/union-borrow-move-parent-sibling.rs:41:13
|
||||||
|
|
|
|
||||||
LL | let a = &mut *u.y;
|
LL | let a = &mut *u.y;
|
||||||
| --------- mutable borrow occurs here
|
| --------- mutable borrow occurs here (via `*u.y`)
|
||||||
LL | let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
|
LL | let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
|
||||||
| ^^^^ immutable borrow occurs here
|
| ^^^^ immutable borrow of `u.x` -- which overlaps with `*u.y` -- occurs here
|
||||||
LL | use_borrow(a);
|
LL | use_borrow(a);
|
||||||
| - mutable borrow later used here
|
| - mutable borrow later used here
|
||||||
|
|
|
||||||
|
= note: `u.x` is a field of the union `U`, so it overlaps the field `*u.y`
|
||||||
|
|
||||||
error[E0382]: use of moved value: `u`
|
error[E0382]: use of moved value: `u`
|
||||||
--> $DIR/union-borrow-move-parent-sibling.rs:48:13
|
--> $DIR/union-borrow-move-parent-sibling.rs:48:13
|
||||||
|
|
|
@ -46,7 +46,7 @@ error[E0502]: cannot borrow `u` (via `u.x`) as immutable because `u` is also bor
|
||||||
LL | let a = &mut *u.y;
|
LL | let a = &mut *u.y;
|
||||||
| ---- mutable borrow occurs here (via `*u.y`)
|
| ---- mutable borrow occurs here (via `*u.y`)
|
||||||
LL | let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
|
LL | let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
|
||||||
| ^^^ immutable borrow occurs here (via `u.x`)
|
| ^^^ immutable borrow of `u.x` -- which overlaps with `*u.y` -- occurs here
|
||||||
LL | use_borrow(a);
|
LL | use_borrow(a);
|
||||||
LL | }
|
LL | }
|
||||||
| - mutable borrow ends here
|
| - mutable borrow ends here
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue