1
Fork 0

Auto merge of #53438 - matthewjasper:permissive-match-access, r=pnkfelix

[NLL] Be more permissive when checking access due to Match

Partially addresses #53114. notably, we should now have parity with AST borrowck. Matching on uninitialized values is still forbidden.

* ~~Give fake borrows for match their own `BorrowKind`~~
* ~~Allow borrows with this kind to happen on values that are already mutably borrowed.~~
* ~~Track borrows with this type even behind shared reference dereferences and consider all accesses to be deep when checking for conflicts with this borrow type. See [src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.rs](cb5c989598 (diff-a2126cd3263a1f5342e2ecd5e699fbc6)) for an example soundness issue this fixes (a case of #27282 that wasn't handled correctly).~~
* Create a new `BorrowKind`: `Shallow` (name can be bike-shed)
* `Shallow` borrows differ from shared borrows in that
  * When we check for access we treat them as a `Shallow(Some(_))` read
  * When we check for conflicts with them, if the borrow place is a strict prefix of the access place then we don't consider that a conflict.
    * For example, a `Shallow` borrow of `x` does not conflict with any access or borrow of `x.0` or `*x`
* Remove the current fake borrow in matches.
* When building matches, we take a `Shallow` borrow of any `Place` that we switch on or bind in a match, and any prefix of those places. (There are some optimizations where we do fewer borrows, but this shouldn't change semantics)
  * `match x { &Some(1) => (),  _ => (), }` would `Shallow` borrow `x`, `*x` and `(*x as Some).0` (the `*x` borrow is unnecessary, but I'm not sure how easy it would be to remove.)
* Replace the fake discriminant read with a `ReadForMatch`.
* Change ReadForMatch to only check for initializedness (to prevent `let x: !; match x {}`), but not conflicting borrows. It is still considered a use for liveness and `unsafe` checking.
* Give special cased error messages for this kind of borrow.

Table from the above issue after this PR

| Thing | AST | MIR | Want | Example |
| --- | --- | --- | --- |---|
| `let _ = <unsafe-field>` | 💚  | 💚  |  |  [playground](https://play.rust-lang.org/?gist=bb7843e42fa5318c1043d04bd72abfe4&version=nightly&mode=debug&edition=2015) |
| `match <unsafe_field> { _ => () }` |   |  |  | [playground](https://play.rust-lang.org/?gist=3e3af05fbf1fae28fab2aaf9412fb2ea&version=nightly&mode=debug&edition=2015) |
| `let _ = <moved>` | 💚  | 💚 | 💚 | [playground](https://play.rust-lang.org/?gist=91a6efde8288558e584aaeee0a50558b&version=nightly&mode=debug&edition=2015) |
| `match <moved> { _ => () }` |  |   | 💚 | [playground](https://play.rust-lang.org/?gist=804f8185040b2fe131f2c4a64b3048ca&version=nightly&mode=debug&edition=2015) |
| `let _ = <borrowed>` | 💚  | 💚 | 💚 | [playground](https://play.rust-lang.org/?gist=0e487c2893b89cb772ec2f2b7c5da876&version=nightly&mode=debug&edition=2015) |
| `match <borrowed> { _ => () }` | 💚  | 💚 | 💚 | [playground](https://play.rust-lang.org/?gist=0e487c2893b89cb772ec2f2b7c5da876&version=nightly&mode=debug&edition=2015) |

r? @nikomatsakis
This commit is contained in:
bors 2018-09-25 01:04:12 +00:00
commit 3a2190a9cd
53 changed files with 1197 additions and 906 deletions

View file

@ -46,6 +46,7 @@ for mir::BorrowKind {
match *self {
mir::BorrowKind::Shared |
mir::BorrowKind::Shallow |
mir::BorrowKind::Unique => {}
mir::BorrowKind::Mut { allow_two_phase_borrow } => {
allow_two_phase_borrow.hash_stable(hcx, hasher);
@ -272,7 +273,7 @@ for mir::StatementKind<'gcx> {
}
}
impl_stable_hash_for!(enum mir::FakeReadCause { ForMatch, ForLet });
impl_stable_hash_for!(enum mir::FakeReadCause { ForMatchGuard, ForMatchedPlace, ForLet });
impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>>
for mir::ValidationOperand<'gcx, T>

View file

@ -451,11 +451,32 @@ impl From<Mutability> for hir::Mutability {
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
pub enum BorrowKind {
/// Data must be immutable and is aliasable.
Shared,
/// The immediately borrowed place must be immutable, but projections from
/// it don't need to be. For example, a shallow borrow of `a.b` doesn't
/// conflict with a mutable borrow of `a.b.c`.
///
/// This is used when lowering matches: when matching on a place we want to
/// ensure that place have the same value from the start of the match until
/// an arm is selected. This prevents this code from compiling:
///
/// let mut x = &Some(0);
/// match *x {
/// None => (),
/// Some(_) if { x = &None; false } => (),
/// Some(_) => (),
/// }
///
/// This can't be a shared borrow because mutably borrowing (*x as Some).0
/// should not prevent `if let None = x { ... }`, for example, becase the
/// mutating `(*x as Some).0` can't affect the discriminant of `x`.
/// We can also report errors with this kind of borrow differently.
Shallow,
/// Data must be immutable but not aliasable. This kind of borrow
/// cannot currently be expressed by the user and is used only in
/// implicit closure bindings. It is needed when the closure is
@ -504,7 +525,7 @@ pub enum BorrowKind {
impl BorrowKind {
pub fn allows_two_phase_borrow(&self) -> bool {
match *self {
BorrowKind::Shared | BorrowKind::Unique => false,
BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false,
BorrowKind::Mut {
allow_two_phase_borrow,
} => allow_two_phase_borrow,
@ -1672,7 +1693,11 @@ pub enum FakeReadCause {
///
/// This should ensure that you cannot change the variant for an enum
/// while you are in the midst of matching on it.
ForMatch,
ForMatchGuard,
/// `let x: !; match x {}` doesn't generate any read of x so we need to
/// generate a read of x to check that it is initialized and safe.
ForMatchedPlace,
/// Officially, the semantics of
///
@ -1773,7 +1798,7 @@ impl<'tcx> Debug for Statement<'tcx> {
/// A path to a value; something that can be evaluated without
/// changing or disturbing program state.
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub enum Place<'tcx> {
/// local variable
Local(Local),
@ -1790,7 +1815,7 @@ pub enum Place<'tcx> {
/// The def-id of a static, along with its normalized type (which is
/// stored to avoid requiring normalization when reading MIR).
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub struct Static<'tcx> {
pub def_id: DefId,
pub ty: Ty<'tcx>,
@ -1805,13 +1830,13 @@ impl_stable_hash_for!(struct Static<'tcx> {
/// or `*B` or `B[index]`. Note that it is parameterized because it is
/// shared between `Constant` and `Place`. See the aliases
/// `PlaceProjection` etc below.
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub struct Projection<'tcx, B, V, T> {
pub base: B,
pub elem: ProjectionElem<'tcx, V, T>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub enum ProjectionElem<'tcx, V, T> {
Deref,
Field(Field, T),
@ -2198,6 +2223,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
Ref(region, borrow_kind, ref place) => {
let kind_str = match borrow_kind {
BorrowKind::Shared => "",
BorrowKind::Shallow => "shallow ",
BorrowKind::Mut { .. } | BorrowKind::Unique => "mut ",
};

View file

@ -287,6 +287,10 @@ impl BorrowKind {
// use `&mut`. It gives all the capabilities of an `&uniq`
// and hence is a safe "over approximation".
BorrowKind::Unique => hir::MutMutable,
// We have no type corresponding to a shallow borrow, so use
// `&` as an approximation.
BorrowKind::Shallow => hir::MutImmutable,
}
}
}

View file

@ -963,6 +963,7 @@ impl<'tcx> PlaceContext<'tcx> {
PlaceContext::Inspect |
PlaceContext::Borrow { kind: BorrowKind::Shared, .. } |
PlaceContext::Borrow { kind: BorrowKind::Shallow, .. } |
PlaceContext::Borrow { kind: BorrowKind::Unique, .. } |
PlaceContext::Projection(Mutability::Not) |
PlaceContext::Copy | PlaceContext::Move |
@ -974,7 +975,9 @@ impl<'tcx> PlaceContext<'tcx> {
/// Returns true if this place context represents a use that does not change the value.
pub fn is_nonmutating_use(&self) -> bool {
match *self {
PlaceContext::Inspect | PlaceContext::Borrow { kind: BorrowKind::Shared, .. } |
PlaceContext::Inspect |
PlaceContext::Borrow { kind: BorrowKind::Shared, .. } |
PlaceContext::Borrow { kind: BorrowKind::Shallow, .. } |
PlaceContext::Borrow { kind: BorrowKind::Unique, .. } |
PlaceContext::Projection(Mutability::Not) |
PlaceContext::Copy | PlaceContext::Move => true,

View file

@ -87,6 +87,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
let kind = match self.kind {
mir::BorrowKind::Shared => "",
mir::BorrowKind::Shallow => "shallow ",
mir::BorrowKind::Unique => "uniq ",
mir::BorrowKind::Mut { .. } => "mut ",
};
@ -287,7 +288,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
borrow_data.activation_location = match context {
// The use of TMP in a shared borrow does not
// count as an actual activation.
PlaceContext::Borrow { kind: mir::BorrowKind::Shared, .. } => {
PlaceContext::Borrow { kind: mir::BorrowKind::Shared, .. }
| PlaceContext::Borrow { kind: mir::BorrowKind::Shallow, .. } => {
TwoPhaseActivation::NotActivated
}
_ => {

View file

@ -333,6 +333,27 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Origin::Mir,
),
(BorrowKind::Mut { .. }, _, _, BorrowKind::Shallow, _, _)
| (BorrowKind::Unique, _, _, BorrowKind::Shallow, _, _) => {
let mut err = tcx.cannot_mutate_in_match_guard(
span,
issued_span,
&desc_place,
"mutably borrow",
Origin::Mir,
);
borrow_spans.var_span_label(
&mut err,
format!(
"borrow occurs due to use of `{}` in closure",
desc_place
),
);
err.buffer(&mut self.errors_buffer);
return;
}
(BorrowKind::Unique, _, _, _, _, _) => tcx.cannot_uniquely_borrow_by_one_closure(
span,
&desc_place,
@ -368,7 +389,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Origin::Mir,
),
(BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) => unreachable!(),
(BorrowKind::Shallow, _, _, BorrowKind::Unique, _, _)
| (BorrowKind::Shallow, _, _, BorrowKind::Mut { .. }, _, _) => {
// Shallow borrows are uses from the user's point of view.
self.report_use_while_mutably_borrowed(context, (place, span), issued_borrow);
return
}
(BorrowKind::Shared, _, _, BorrowKind::Shared, _, _)
| (BorrowKind::Shared, _, _, BorrowKind::Shallow, _, _)
| (BorrowKind::Shallow, _, _, BorrowKind::Shared, _, _)
| (BorrowKind::Shallow, _, _, BorrowKind::Shallow, _, _) => unreachable!(),
};
if issued_spans == borrow_spans {
@ -780,12 +810,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
let loan_span = loan_spans.args_or_use();
let tcx = self.infcx.tcx;
let mut err = tcx.cannot_assign_to_borrowed(
span,
loan_span,
&self.describe_place(place).unwrap_or("_".to_owned()),
Origin::Mir,
);
let mut err = if loan.kind == BorrowKind::Shallow {
tcx.cannot_mutate_in_match_guard(
span,
loan_span,
&self.describe_place(place).unwrap_or("_".to_owned()),
"assign",
Origin::Mir,
)
} else {
tcx.cannot_assign_to_borrowed(
span,
loan_span,
&self.describe_place(place).unwrap_or("_".to_owned()),
Origin::Mir,
)
};
loan_spans.var_span_label(&mut err, "borrow occurs due to use in closure");

View file

@ -499,11 +499,20 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
);
}
StatementKind::FakeRead(_, ref place) => {
self.access_place(
// Read for match doesn't access any memory and is used to
// assert that a place is safe and live. So we don't have to
// do any checks here.
//
// FIXME: Remove check that the place is initialized. This is
// needed for now because matches don't have never patterns yet.
// So this is the only place we prevent
// let x: !;
// match x {};
// from compiling.
self.check_if_path_or_subpath_is_moved(
ContextKind::FakeRead.new(location),
InitializationRequiringAction::Use,
(place, span),
(Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
LocalMutationIsAllowed::No,
flow_state,
);
}
@ -755,6 +764,7 @@ use self::AccessDepth::{Deep, Shallow};
enum ArtificialField {
Discriminant,
ArrayLength,
ShallowBorrow,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@ -835,6 +845,7 @@ enum LocalMutationIsAllowed {
enum InitializationRequiringAction {
Update,
Borrow,
MatchOn,
Use,
Assignment,
}
@ -849,6 +860,7 @@ impl InitializationRequiringAction {
match self {
InitializationRequiringAction::Update => "update",
InitializationRequiringAction::Borrow => "borrow",
InitializationRequiringAction::MatchOn => "use", // no good noun
InitializationRequiringAction::Use => "use",
InitializationRequiringAction::Assignment => "assign",
}
@ -858,6 +870,7 @@ impl InitializationRequiringAction {
match self {
InitializationRequiringAction::Update => "updated",
InitializationRequiringAction::Borrow => "borrowed",
InitializationRequiringAction::MatchOn => "matched on",
InitializationRequiringAction::Use => "used",
InitializationRequiringAction::Assignment => "assigned",
}
@ -972,7 +985,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Control::Continue
}
(Read(_), BorrowKind::Shared) | (Reservation(..), BorrowKind::Shared) => {
(Read(_), BorrowKind::Shared) | (Reservation(..), BorrowKind::Shared)
| (Read(_), BorrowKind::Shallow) | (Reservation(..), BorrowKind::Shallow) => {
Control::Continue
}
(Write(WriteKind::Move), BorrowKind::Shallow) => {
// Handled by initialization checks.
Control::Continue
}
@ -984,7 +1003,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
}
match kind {
ReadKind::Copy => {
ReadKind::Copy => {
error_reported = true;
this.report_use_while_mutably_borrowed(context, place_span, borrow)
}
@ -1108,6 +1127,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
match *rvalue {
Rvalue::Ref(_ /*rgn*/, bk, ref place) => {
let access_kind = match bk {
BorrowKind::Shallow => {
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
},
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
BorrowKind::Unique | BorrowKind::Mut { .. } => {
let wk = WriteKind::MutableBorrow(bk);
@ -1127,9 +1149,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
flow_state,
);
let action = if bk == BorrowKind::Shallow {
InitializationRequiringAction::MatchOn
} else {
InitializationRequiringAction::Borrow
};
self.check_if_path_or_subpath_is_moved(
context,
InitializationRequiringAction::Borrow,
action,
(place, span),
flow_state,
);
@ -1315,11 +1343,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
return;
}
// FIXME: replace this with a proper borrow_conflicts_with_place when
// that is merged.
let sd = if might_be_alive { Deep } else { Shallow(None) };
if places_conflict::places_conflict(self.infcx.tcx, self.mir, place, root_place, sd) {
if places_conflict::borrow_conflicts_with_place(
self.infcx.tcx,
self.mir,
place,
borrow.kind,
root_place,
sd
) {
debug!("check_for_invalidation_at_exit({:?}): INVALID", place);
// FIXME: should be talking about the region lifetime instead
// of just a span here.
@ -1369,7 +1402,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// only mutable borrows should be 2-phase
assert!(match borrow.kind {
BorrowKind::Shared => false,
BorrowKind::Shared | BorrowKind::Shallow => false,
BorrowKind::Unique | BorrowKind::Mut { .. } => true,
});
@ -1669,7 +1702,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
let is_local_mutation_allowed = match borrow_kind {
BorrowKind::Unique => LocalMutationIsAllowed::Yes,
BorrowKind::Mut { .. } => is_local_mutation_allowed,
BorrowKind::Shared => unreachable!(),
BorrowKind::Shared | BorrowKind::Shallow => unreachable!(),
};
match self.is_mutable(place, is_local_mutation_allowed) {
Ok(root_place) => {
@ -1699,8 +1732,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
| Write(wk @ WriteKind::Move)
| Reservation(wk @ WriteKind::StorageDeadOrDrop)
| Reservation(wk @ WriteKind::MutableBorrow(BorrowKind::Shared))
| Reservation(wk @ WriteKind::MutableBorrow(BorrowKind::Shallow))
| Write(wk @ WriteKind::StorageDeadOrDrop)
| Write(wk @ WriteKind::MutableBorrow(BorrowKind::Shared)) => {
| Write(wk @ WriteKind::MutableBorrow(BorrowKind::Shared))
| Write(wk @ WriteKind::MutableBorrow(BorrowKind::Shallow)) => {
if let Err(_place_err) = self.is_mutable(place, is_local_mutation_allowed) {
if self.infcx.tcx.migrate_borrowck() {
// rust-lang/rust#46908: In pure NLL mode this
@ -1743,6 +1778,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Read(ReadKind::Borrow(BorrowKind::Unique))
| Read(ReadKind::Borrow(BorrowKind::Mut { .. }))
| Read(ReadKind::Borrow(BorrowKind::Shared))
| Read(ReadKind::Borrow(BorrowKind::Shallow))
| Read(ReadKind::Copy) => {
// Access authorized
return false;

View file

@ -329,6 +329,9 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
match *rvalue {
Rvalue::Ref(_ /*rgn*/, bk, ref place) => {
let access_kind = match bk {
BorrowKind::Shallow => {
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
},
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
BorrowKind::Unique | BorrowKind::Mut { .. } => {
let wk = WriteKind::MutableBorrow(bk);
@ -439,8 +442,9 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
// have already taken the reservation
}
(Read(_), BorrowKind::Shared) | (Reservation(..), BorrowKind::Shared) => {
// Reads/reservations don't invalidate shared borrows
(Read(_), BorrowKind::Shallow) | (Reservation(..), BorrowKind::Shallow)
| (Read(_), BorrowKind::Shared) | (Reservation(..), BorrowKind::Shared) => {
// Reads/reservations don't invalidate shared or shallow borrows
}
(Read(_), BorrowKind::Unique) | (Read(_), BorrowKind::Mut { .. }) => {

View file

@ -61,7 +61,14 @@ pub(super) fn each_borrow_involving_path<'a, 'tcx, 'gcx: 'tcx, F, I, S> (
for i in candidates {
let borrowed = &borrow_set[i];
if places_conflict::places_conflict(tcx, mir, &borrowed.borrowed_place, place, access) {
if places_conflict::borrow_conflicts_with_place(
tcx,
mir,
&borrowed.borrowed_place,
borrowed.kind,
place,
access,
) {
debug!(
"each_borrow_involving_path: {:?} @ {:?} vs. {:?}/{:?}",
i, borrowed, place, access

View file

@ -12,20 +12,21 @@ use borrow_check::ArtificialField;
use borrow_check::Overlap;
use borrow_check::{Deep, Shallow, AccessDepth};
use rustc::hir;
use rustc::mir::{Mir, Place};
use rustc::mir::{BorrowKind, Mir, Place};
use rustc::mir::{Projection, ProjectionElem};
use rustc::ty::{self, TyCtxt};
use std::cmp::max;
pub(super) fn places_conflict<'gcx, 'tcx>(
pub(super) fn borrow_conflicts_with_place<'gcx, 'tcx>(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
borrow_place: &Place<'tcx>,
borrow_kind: BorrowKind,
access_place: &Place<'tcx>,
access: AccessDepth,
) -> bool {
debug!(
"places_conflict({:?},{:?},{:?})",
"borrow_conflicts_with_place({:?},{:?},{:?})",
borrow_place, access_place, access
);
@ -39,7 +40,14 @@ pub(super) fn places_conflict<'gcx, 'tcx>(
unroll_place(borrow_place, None, |borrow_components| {
unroll_place(access_place, None, |access_components| {
place_components_conflict(tcx, mir, borrow_components, access_components, access)
place_components_conflict(
tcx,
mir,
borrow_components,
borrow_kind,
access_components,
access
)
})
})
}
@ -48,6 +56,7 @@ fn place_components_conflict<'gcx, 'tcx>(
tcx: TyCtxt<'_, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
mut borrow_components: PlaceComponentsIter<'_, 'tcx>,
borrow_kind: BorrowKind,
mut access_components: PlaceComponentsIter<'_, 'tcx>,
access: AccessDepth,
) -> bool {
@ -95,10 +104,10 @@ fn place_components_conflict<'gcx, 'tcx>(
loop {
// loop invariant: borrow_c is always either equal to access_c or disjoint from it.
if let Some(borrow_c) = borrow_components.next() {
debug!("places_conflict: borrow_c = {:?}", borrow_c);
debug!("borrow_conflicts_with_place: borrow_c = {:?}", borrow_c);
if let Some(access_c) = access_components.next() {
debug!("places_conflict: access_c = {:?}", access_c);
debug!("borrow_conflicts_with_place: access_c = {:?}", access_c);
// Borrow and access path both have more components.
//
@ -127,7 +136,7 @@ fn place_components_conflict<'gcx, 'tcx>(
// idea, at least for now, so just give up and
// report a conflict. This is unsafe code anyway so
// the user could always use raw pointers.
debug!("places_conflict: arbitrary -> conflict");
debug!("borrow_conflicts_with_place: arbitrary -> conflict");
return true;
}
Overlap::EqualOrDisjoint => {
@ -136,7 +145,7 @@ fn place_components_conflict<'gcx, 'tcx>(
Overlap::Disjoint => {
// We have proven the borrow disjoint - further
// projections will remain disjoint.
debug!("places_conflict: disjoint");
debug!("borrow_conflicts_with_place: disjoint");
return false;
}
}
@ -157,7 +166,8 @@ fn place_components_conflict<'gcx, 'tcx>(
match (elem, &base_ty.sty, access) {
(_, _, Shallow(Some(ArtificialField::Discriminant)))
| (_, _, Shallow(Some(ArtificialField::ArrayLength))) => {
| (_, _, Shallow(Some(ArtificialField::ArrayLength)))
| (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => {
// The discriminant and array length are like
// additional fields on the type; they do not
// overlap any existing data there. Furthermore,
@ -167,7 +177,7 @@ fn place_components_conflict<'gcx, 'tcx>(
//
// e.g. a (mutable) borrow of `a[5]` while we read the
// array length of `a`.
debug!("places_conflict: implicit field");
debug!("borrow_conflicts_with_place: implicit field");
return false;
}
@ -175,7 +185,7 @@ fn place_components_conflict<'gcx, 'tcx>(
// e.g. a borrow of `*x.y` while we shallowly access `x.y` or some
// prefix thereof - the shallow access can't touch anything behind
// the pointer.
debug!("places_conflict: shallow access behind ptr");
debug!("borrow_conflicts_with_place: shallow access behind ptr");
return false;
}
(ProjectionElem::Deref, ty::Ref(_, _, hir::MutImmutable), _) => {
@ -185,7 +195,7 @@ fn place_components_conflict<'gcx, 'tcx>(
(ProjectionElem::Deref, ty::Ref(_, _, hir::MutMutable), AccessDepth::Drop) => {
// Values behind a mutatble reference are not access either by Dropping a
// value, or by StorageDead
debug!("places_conflict: drop access behind ptr");
debug!("borrow_conflicts_with_place: drop access behind ptr");
return false;
}
@ -225,11 +235,13 @@ fn place_components_conflict<'gcx, 'tcx>(
// If the second example, where we did, then we still know
// that the borrow can access a *part* of our place that
// our access cares about, so we still have a conflict.
//
// FIXME: Differs from AST-borrowck; includes drive-by fix
// to #38899. Will probably need back-compat mode flag.
debug!("places_conflict: full borrow, CONFLICT");
return true;
if borrow_kind == BorrowKind::Shallow && access_components.next().is_some() {
debug!("borrow_conflicts_with_place: shallow borrow");
return false;
} else {
debug!("borrow_conflicts_with_place: full borrow, CONFLICT");
return true;
}
}
}
}
@ -241,7 +253,7 @@ fn place_components_conflict<'gcx, 'tcx>(
///
/// NB: This particular impl strategy is not the most obvious. It was
/// chosen because it makes a measurable difference to NLL
/// performance, as this code (`places_conflict`) is somewhat hot.
/// performance, as this code (`borrow_conflicts_with_place`) is somewhat hot.
struct PlaceComponents<'p, 'tcx: 'p> {
component: &'p Place<'tcx>,
next: Option<&'p PlaceComponents<'p, 'tcx>>,

View file

@ -57,39 +57,22 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
// See issue #47412 for this hole being discovered in the wild.
//
// HACK(eddyb) Work around the above issue by adding a dummy inspection
// of `discriminant_place`, specifically by applying `Rvalue::Discriminant`
// (which will work regardless of type) and storing the result in a temp.
// of `discriminant_place`, specifically by applying `ReadForMatch`.
//
// NOTE: Under NLL, the above issue should no longer occur because it
// injects a borrow of the matched input, which should have the same effect
// as eddyb's hack. Once NLL is the default, we can remove the hack.
let dummy_source_info = self.source_info(discriminant_span);
let dummy_access = Rvalue::Discriminant(discriminant_place.clone());
let dummy_ty = dummy_access.ty(&self.local_decls, tcx);
let dummy_temp = self.temp(dummy_ty, dummy_source_info.span);
self.cfg
.push_assign(block, dummy_source_info, &dummy_temp, dummy_access);
// NOTE: ReadForMatch also checks that the discriminant is initialized.
// This is currently needed to not allow matching on an uninitialized,
// uninhabited value. If we get never patterns, those will check that
// the place is initialized, and so this read would only be used to
// check safety.
let source_info = self.source_info(discriminant_span);
let borrowed_input_temp = if tcx.generate_borrow_of_any_match_input() {
// The region is unknown at this point; we rely on NLL
// inference to find an appropriate one. Therefore you can
// only use this when NLL is turned on.
assert!(tcx.use_mir_borrowck());
let borrowed_input = Rvalue::Ref(
tcx.types.re_empty,
BorrowKind::Shared,
self.cfg.push(block, Statement {
source_info,
kind: StatementKind::FakeRead(
FakeReadCause::ForMatchedPlace,
discriminant_place.clone(),
);
let borrowed_input_ty = borrowed_input.ty(&self.local_decls, tcx);
let borrowed_input_temp = self.temp(borrowed_input_ty, span);
self.cfg
.push_assign(block, source_info, &borrowed_input_temp, borrowed_input);
Some(borrowed_input_temp)
} else {
None
};
),
});
let mut arm_blocks = ArmBlocks {
blocks: arms.iter().map(|_| self.cfg.start_new_block()).collect(),
@ -118,6 +101,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
.map(|_| self.cfg.start_new_block())
.collect();
let mut has_guard = false;
// assemble a list of candidates: there is one candidate per
// pattern, which means there may be more than one candidate
// *per arm*. These candidates are kept sorted such that the
@ -140,24 +125,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
.map(
|(
(arm_index, pat_index, pattern, guard),
(pre_binding_block, next_candidate_pre_binding_block),
(pre_binding_block, next_candidate_pre_binding_block)
)| {
if let (true, Some(borrow_temp)) =
(tcx.emit_read_for_match(), borrowed_input_temp.clone())
{
// Inject a fake read, see comments on `FakeReadCause::ForMatch`.
let pattern_source_info = self.source_info(pattern.span);
self.cfg.push(
*pre_binding_block,
Statement {
source_info: pattern_source_info,
kind: StatementKind::FakeRead(
FakeReadCause::ForMatch,
borrow_temp.clone(),
),
},
);
}
has_guard |= guard.is_some();
// One might ask: why not build up the match pair such that it
// matches via `borrowed_input_temp.deref()` instead of
@ -202,9 +172,31 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
TerminatorKind::Unreachable,
);
// Maps a place to the kind of Fake borrow that we want to perform on
// it: either Shallow or Shared, depending on whether the place is
// bound in the match, or just switched on.
// If there are no match guards then we don't need any fake borrows,
// so don't track them.
let mut fake_borrows = if has_guard && tcx.generate_borrow_of_any_match_input() {
Some(FxHashMap())
} else {
None
};
let pre_binding_blocks: Vec<_> = candidates
.iter()
.map(|cand| (cand.pre_binding_block, cand.span))
.collect();
// this will generate code to test discriminant_place and
// branch to the appropriate arm block
let otherwise = self.match_candidates(span, &mut arm_blocks, candidates, block);
let otherwise = self.match_candidates(
discriminant_span,
&mut arm_blocks,
candidates,
block,
&mut fake_borrows,
);
if !otherwise.is_empty() {
// All matches are exhaustive. However, because some matches
@ -224,6 +216,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
}
}
if let Some(fake_borrows) = fake_borrows {
self.add_fake_borrows(&pre_binding_blocks, fake_borrows, source_info, block);
}
// all the arm blocks will rejoin here
let end_block = self.cfg.start_new_block();
@ -714,12 +710,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
/// up the list of candidates and recurse with a non-exhaustive
/// list. This is important to keep the size of the generated code
/// under control. See `test_candidates` for more details.
///
/// If `add_fake_borrows` is true, then places which need fake borrows
/// will be added to it.
fn match_candidates<'pat>(
&mut self,
span: Span,
arm_blocks: &mut ArmBlocks,
mut candidates: Vec<Candidate<'pat, 'tcx>>,
mut block: BasicBlock,
fake_borrows: &mut Option<FxHashMap<Place<'tcx>, BorrowKind>>,
) -> Vec<BasicBlock> {
debug!(
"matched_candidate(span={:?}, block={:?}, candidates={:?})",
@ -747,6 +747,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
);
let mut unmatched_candidates = candidates.split_off(fully_matched);
// Insert a *Shared* borrow of any places that are bound.
if let Some(fake_borrows) = fake_borrows {
for Binding { source, .. }
in candidates.iter().flat_map(|candidate| &candidate.bindings)
{
fake_borrows.insert(source.clone(), BorrowKind::Shared);
}
}
let fully_matched_with_guard = candidates.iter().take_while(|c| c.guard.is_some()).count();
let unreachable_candidates = if fully_matched_with_guard + 1 < candidates.len() {
@ -783,7 +792,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
return vec![];
} else {
let target = self.cfg.start_new_block();
return self.match_candidates(span, arm_blocks, unmatched_candidates, target);
return self.match_candidates(
span,
arm_blocks,
unmatched_candidates,
target,
&mut None,
);
}
}
}
@ -796,7 +811,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
// Test candidates where possible.
let (otherwise, tested_candidates) =
self.test_candidates(span, arm_blocks, &unmatched_candidates, block);
self.test_candidates(span, arm_blocks, &unmatched_candidates, block, fake_borrows);
// If the target candidates were exhaustive, then we are done.
// But for borrowck continue build decision tree.
@ -810,7 +825,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
// Otherwise, let's process those remaining candidates.
let join_block = self.join_otherwise_blocks(span, otherwise);
self.match_candidates(span, arm_blocks, untested_candidates, join_block)
self.match_candidates(span, arm_blocks, untested_candidates, join_block, &mut None)
}
fn join_otherwise_blocks(&mut self, span: Span, mut otherwise: Vec<BasicBlock>) -> BasicBlock {
@ -950,6 +965,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
arm_blocks: &mut ArmBlocks,
candidates: &[Candidate<'pat, 'tcx>],
block: BasicBlock,
fake_borrows: &mut Option<FxHashMap<Place<'tcx>, BorrowKind>>,
) -> (Vec<BasicBlock>, usize) {
// extract the match-pair from the highest priority candidate
let match_pair = &candidates.first().unwrap().match_pairs[0];
@ -990,6 +1006,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
_ => {}
}
// Insert a Shallow borrow of any places that is switched on.
fake_borrows.as_mut().map(|fb| {
fb.entry(match_pair.place.clone()).or_insert(BorrowKind::Shallow)
});
// perform the test, branching to one of N blocks. For each of
// those N possible outcomes, create a (initially empty)
// vector of candidates. Those are the candidates that still
@ -1026,7 +1047,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
.into_iter()
.zip(target_candidates)
.flat_map(|(target_block, target_candidates)| {
self.match_candidates(span, arm_blocks, target_candidates, target_block)
self.match_candidates(
span,
arm_blocks,
target_candidates,
target_block,
fake_borrows,
)
})
.collect();
@ -1363,7 +1390,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
// borrow of the whole match input. See additional
// discussion on rust-lang/rust#49870.
let borrow_kind = match borrow_kind {
BorrowKind::Shared | BorrowKind::Unique => borrow_kind,
BorrowKind::Shared
| BorrowKind::Shallow
| BorrowKind::Unique => borrow_kind,
BorrowKind::Mut { .. } => BorrowKind::Mut {
allow_two_phase_borrow: true,
},
@ -1502,4 +1531,86 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
debug!("declare_binding: vars={:?}", locals);
self.var_indices.insert(var_id, locals);
}
// Determine the fake borrows that are needed to ensure that the place
// will evaluate to the same thing until an arm has been chosen.
fn add_fake_borrows<'pat>(
&mut self,
pre_binding_blocks: &[(BasicBlock, Span)],
fake_borrows: FxHashMap<Place<'tcx>, BorrowKind>,
source_info: SourceInfo,
start_block: BasicBlock,
) {
let tcx = self.hir.tcx();
debug!("add_fake_borrows pre_binding_blocks = {:?}, fake_borrows = {:?}",
pre_binding_blocks, fake_borrows);
let mut all_fake_borrows = Vec::with_capacity(fake_borrows.len());
// Insert a Shallow borrow of the prefixes of any fake borrows.
for (place, borrow_kind) in fake_borrows
{
{
let mut prefix_cursor = &place;
while let Place::Projection(box Projection { base, elem }) = prefix_cursor {
if let ProjectionElem::Deref = elem {
// Insert a shallow borrow after a deref. For other
// projections the borrow of prefix_cursor will
// conflict with any mutation of base.
all_fake_borrows.push((base.clone(), BorrowKind::Shallow));
}
prefix_cursor = base;
}
}
all_fake_borrows.push((place, borrow_kind));
}
// Deduplicate and ensure a deterministic order.
all_fake_borrows.sort();
all_fake_borrows.dedup();
debug!("add_fake_borrows all_fake_borrows = {:?}", all_fake_borrows);
// Add fake borrows to the start of the match and reads of them before
// the start of each arm.
let mut borrowed_input_temps = Vec::with_capacity(all_fake_borrows.len());
for (matched_place, borrow_kind) in all_fake_borrows {
let borrowed_input =
Rvalue::Ref(tcx.types.re_empty, borrow_kind, matched_place.clone());
let borrowed_input_ty = borrowed_input.ty(&self.local_decls, tcx);
let borrowed_input_temp = self.temp(borrowed_input_ty, source_info.span);
self.cfg.push_assign(
start_block,
source_info,
&borrowed_input_temp,
borrowed_input
);
borrowed_input_temps.push(borrowed_input_temp);
}
// FIXME: This could be a lot of reads (#fake borrows * #patterns).
// The false edges that we currently generate would allow us to only do
// this on the last Candidate, but it's possible that there might not be
// so many false edges in the future, so we read for all Candidates for
// now.
// Another option would be to make our own block and add our own false
// edges to it.
if tcx.emit_read_for_match() {
for &(pre_binding_block, span) in pre_binding_blocks {
let pattern_source_info = self.source_info(span);
for temp in &borrowed_input_temps {
self.cfg.push(pre_binding_block, Statement {
source_info: pattern_source_info,
kind: StatementKind::FakeRead(
FakeReadCause::ForMatchGuard,
temp.clone(),
),
});
}
}
}
}
}

View file

@ -1991,6 +1991,26 @@ fn main() {
```
"##,
E0510: r##"
Cannot mutate place in this match guard.
When matching on a variable it cannot be mutated in the match guards, as this
could cause the match to be non-exhaustive:
```compile_fail,E0510
#![feature(nll, bind_by_move_pattern_guards)]
let mut x = Some(0);
match x {
None => (),
Some(v) if { x = None; false } => (),
Some(_) => (), // No longer matches
}
```
Here executing `x = None` would modify the value being matched and require us
to go "back in time" to the `None` arm.
"##,
E0579: r##"
When matching against an exclusive range, the compiler verifies that the range
is non-empty. Exclusive range patterns include the start point but not the end

View file

@ -14,7 +14,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
*/
#![cfg_attr(not(stage0), feature(nll))]
#![feature(nll)]
#![feature(in_band_lifetimes)]
#![feature(impl_header_lifetime_elision)]
#![feature(slice_patterns)]

View file

@ -33,7 +33,8 @@
use rustc_data_structures::fx::FxHashSet;
use rustc::middle::region;
use rustc::mir::{BasicBlock, Location, Mir, Rvalue, Statement, StatementKind};
use rustc::mir::{BasicBlock, FakeReadCause, Local, Location, Mir, Place};
use rustc::mir::{Rvalue, Statement, StatementKind};
use rustc::mir::visit::{MutVisitor, Visitor, TyContext};
use rustc::ty::{Ty, RegionKind, TyCtxt};
use transform::{MirPass, MirSource};
@ -135,3 +136,62 @@ impl<'tcx> MutVisitor<'tcx> for DeleteAscribeUserType {
self.super_statement(block, statement, location);
}
}
pub struct CleanFakeReadsAndBorrows;
pub struct DeleteAndRecordFakeReads {
fake_borrow_temporaries: FxHashSet<Local>,
}
pub struct DeleteFakeBorrows {
fake_borrow_temporaries: FxHashSet<Local>,
}
// Removes any FakeReads from the MIR
impl MirPass for CleanFakeReadsAndBorrows {
fn run_pass<'a, 'tcx>(&self,
_tcx: TyCtxt<'a, 'tcx, 'tcx>,
_source: MirSource,
mir: &mut Mir<'tcx>) {
let mut delete_reads = DeleteAndRecordFakeReads {
fake_borrow_temporaries: FxHashSet(),
};
delete_reads.visit_mir(mir);
let mut delete_borrows = DeleteFakeBorrows {
fake_borrow_temporaries: delete_reads.fake_borrow_temporaries,
};
delete_borrows.visit_mir(mir);
}
}
impl<'tcx> MutVisitor<'tcx> for DeleteAndRecordFakeReads {
fn visit_statement(&mut self,
block: BasicBlock,
statement: &mut Statement<'tcx>,
location: Location) {
if let StatementKind::FakeRead(cause, ref place) = statement.kind {
if let FakeReadCause::ForMatchGuard = cause {
match *place {
Place::Local(local) => self.fake_borrow_temporaries.insert(local),
_ => bug!("Fake match guard read of non-local: {:?}", place),
};
}
statement.make_nop();
}
self.super_statement(block, statement, location);
}
}
impl<'tcx> MutVisitor<'tcx> for DeleteFakeBorrows {
fn visit_statement(&mut self,
block: BasicBlock,
statement: &mut Statement<'tcx>,
location: Location) {
if let StatementKind::Assign(Place::Local(local), _) = statement.kind {
if self.fake_borrow_temporaries.contains(&local) {
statement.make_nop();
}
}
self.super_statement(block, statement, location);
}
}

View file

@ -237,9 +237,12 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
no_landing_pads::NoLandingPads,
simplify_branches::SimplifyBranches::new("initial"),
remove_noop_landing_pads::RemoveNoopLandingPads,
simplify::SimplifyCfg::new("early-opt"),
// Remove all `AscribeUserType` statements.
cleanup_post_borrowck::CleanAscribeUserType,
// Remove all `FakeRead` statements and the borrows that are only
// used for checking matches
cleanup_post_borrowck::CleanFakeReadsAndBorrows,
simplify::SimplifyCfg::new("early-opt"),
// These next passes must be executed together
add_call_guards::CriticalCallEdges,

View file

@ -555,6 +555,29 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
self.cannot_borrow_path_as_mutable_because(span, path, "", o)
}
fn cannot_mutate_in_match_guard(
self,
mutate_span: Span,
match_span: Span,
match_place: &str,
action: &str,
o: Origin,
) -> DiagnosticBuilder<'cx> {
let mut err = struct_span_err!(
self,
mutate_span,
E0510,
"cannot {} `{}` in match guard{OGN}",
action,
match_place,
OGN = o
);
err.span_label(mutate_span, format!("cannot {}", action));
err.span_label(match_span, format!("value is immutable in match guard"));
self.cancel_if_wrong_origin(err, o)
}
fn cannot_borrow_across_generator_yield(
self,
span: Span,

View file

@ -63,7 +63,6 @@ impl Drop for S {
//
// bb4: {
// StorageDead(_2);
// FakeRead(ForLet, _1);
// StorageLive(_4);
// _4 = move _1;
// _3 = const std::mem::drop(move _4) -> [return: bb5, unwind: bb7];

View file

@ -34,10 +34,9 @@ fn main() {
// }
// let mut _1: ();
// let mut _3: bool;
// let mut _4: u8;
// let mut _5: !;
// let mut _6: ();
// let mut _7: &i32;
// let mut _4: !;
// let mut _5: ();
// let mut _6: &i32;
// bb0: {
// goto -> bb1;
// }
@ -51,7 +50,7 @@ fn main() {
// StorageLive(_2);
// StorageLive(_3);
// _3 = const true;
// _4 = discriminant(_3);
// FakeRead(ForMatchedPlace, _3);
// switchInt(_3) -> [false: bb11, otherwise: bb10];
// }
// bb4: {
@ -89,9 +88,9 @@ fn main() {
// bb14: {
// FakeRead(ForLet, _2);
// StorageDead(_3);
// StorageLive(_7);
// _7 = &_2;
// _6 = const std::mem::drop(move _7) -> [return: bb28, unwind: bb4];
// StorageLive(_6);
// _6 = &_2;
// _5 = const std::mem::drop(move _6) -> [return: bb28, unwind: bb4];
// }
// bb15: {
// goto -> bb16;
@ -129,15 +128,15 @@ fn main() {
// goto -> bb2;
// }
// bb26: {
// _5 = ();
// _4 = ();
// unreachable;
// }
// bb27: {
// StorageDead(_5);
// StorageDead(_4);
// goto -> bb14;
// }
// bb28: {
// StorageDead(_7);
// StorageDead(_6);
// _1 = ();
// StorageDead(_2);
// goto -> bb1;

View file

@ -53,10 +53,11 @@ fn main() {
// bb0: {
// ...
// _2 = std::option::Option<i32>::Some(const 42i32,);
// _3 = discriminant(_2);
// _4 = &(promoted[1]: std::option::Option<i32>);
// _9 = discriminant(_2);
// switchInt(move _9) -> [0isize: bb5, 1isize: bb3, otherwise: bb7];
// FakeRead(ForMatchedPlace, _2);
// _7 = discriminant(_2);
// _9 = &shallow (promoted[2]: std::option::Option<i32>);
// _10 = &(((promoted[1]: std::option::Option<i32>) as Some).0: i32);
// switchInt(move _7) -> [0isize: bb5, 1isize: bb3, otherwise: bb7];
// }
// bb1: {
// resume;
@ -66,15 +67,18 @@ fn main() {
// goto -> bb13;
// }
// bb3: { // binding3(empty) and arm3
// FakeRead(ForMatch, _4);
// FakeRead(ForMatchGuard, _9);
// FakeRead(ForMatchGuard, _10);
// falseEdges -> [real: bb8, imaginary: bb4]; //pre_binding1
// }
// bb4: {
// FakeRead(ForMatch, _4);
// FakeRead(ForMatchGuard, _9);
// FakeRead(ForMatchGuard, _10);
// falseEdges -> [real: bb12, imaginary: bb5]; //pre_binding2
// }
// bb5: {
// FakeRead(ForMatch, _4);
// FakeRead(ForMatchGuard, _9);
// FakeRead(ForMatchGuard, _10);
// falseEdges -> [real: bb2, imaginary: bb6]; //pre_binding3
// }
// bb6: {
@ -84,31 +88,31 @@ fn main() {
// unreachable;
// }
// bb8: { // binding1 and guard
// StorageLive(_7);
// _7 = &(((promoted[0]: std::option::Option<i32>) as Some).0: i32);
// StorageLive(_10);
// _10 = const guard() -> [return: bb9, unwind: bb1];
// StorageLive(_5);
// _5 = &(((promoted[0]: std::option::Option<i32>) as Some).0: i32);
// StorageLive(_8);
// _8 = const guard() -> [return: bb9, unwind: bb1];
// }
// bb9: {
// switchInt(move _10) -> [false: bb10, otherwise: bb11];
// switchInt(move _8) -> [false: bb10, otherwise: bb11];
// }
// bb10: { // to pre_binding2
// falseEdges -> [real: bb4, imaginary: bb4];
// }
// bb11: { // bindingNoLandingPads.before.mir2 and arm2
// StorageLive(_5);
// _5 = ((_2 as Some).0: i32);
// StorageLive(_3);
// _3 = ((_2 as Some).0: i32);
// StorageLive(_11);
// _11 = _5;
// _11 = _3;
// _1 = (const 1i32, move _11);
// StorageDead(_11);
// goto -> bb13;
// }
// bb12: {
// StorageLive(_8);
// _8 = ((_2 as Some).0: i32);
// StorageLive(_6);
// _6 = ((_2 as Some).0: i32);
// StorageLive(_12);
// _12 = _8;
// _12 = _6;
// _1 = (const 2i32, move_12);
// StorageDead(_12);
// goto -> bb13;
@ -123,10 +127,11 @@ fn main() {
// bb0: {
// ...
// _2 = std::option::Option<i32>::Some(const 42i32,);
// _3 = discriminant(_2);
// _4 = &_2;
// _9 = discriminant(_2);
// switchInt(move _9) -> [0isize: bb4, 1isize: bb3, otherwise: bb7];
// FakeRead(ForMatchedPlace, _2);
// _7 = discriminant(_2);
// _9 = &shallow _2;
// _10 = &((_2 as Some).0: i32);
// switchInt(move _7) -> [0isize: bb4, 1isize: bb3, otherwise: bb7];
// }
// bb1: {
// resume;
@ -136,15 +141,18 @@ fn main() {
// goto -> bb13;
// }
// bb3: {
// FakeRead(ForMatch, _4);
// FakeRead(ForMatchGuard, _9);
// FakeRead(ForMatchGuard, _10);
// falseEdges -> [real: bb8, imaginary: bb4]; //pre_binding1
// }
// bb4: {
// FakeRead(ForMatch, _4);
// FakeRead(ForMatchGuard, _9);
// FakeRead(ForMatchGuard, _10);
// falseEdges -> [real: bb2, imaginary: bb5]; //pre_binding2
// }
// bb5: {
// FakeRead(ForMatch, _4);
// FakeRead(ForMatchGuard, _9);
// FakeRead(ForMatchGuard, _10);
// falseEdges -> [real: bb12, imaginary: bb6]; //pre_binding3
// }
// bb6: {
@ -154,31 +162,31 @@ fn main() {
// unreachable;
// }
// bb8: { // binding1 and guard
// StorageLive(_7);
// _7 = &((_2 as Some).0: i32);
// StorageLive(_10);
// _10 = const guard() -> [return: bb9, unwind: bb1];
// StorageLive(_5);
// _5 = &((_2 as Some).0: i32);
// StorageLive(_8);
// _8 = const guard() -> [return: bb9, unwind: bb1];
// }
// bb9: { // end of guard
// switchInt(move _10) -> [false: bb10, otherwise: bb11];
// switchInt(move _8) -> [false: bb10, otherwise: bb11];
// }
// bb10: { // to pre_binding3 (can skip 2 since this is `Some`)
// falseEdges -> [real: bb5, imaginary: bb4];
// }
// bb11: { // arm1
// StorageLive(_5);
// _5 = ((_2 as Some).0: i32);
// StorageLive(_3);
// _3 = ((_2 as Some).0: i32);
// StorageLive(_11);
// _11 = _5;
// _11 = _3;
// _1 = (const 1i32, move _11);
// StorageDead(_11);
// goto -> bb13;
// }
// bb12: { // binding3 and arm3
// StorageLive(_8);
// _8 = ((_2 as Some).0: i32);
// StorageLive(_6);
// _6 = ((_2 as Some).0: i32);
// StorageLive(_12);
// _12 = _8;
// _12 = _6;
// _1 = (const 2i32, move _12);
// StorageDead(_12);
// goto -> bb13;
@ -193,81 +201,86 @@ fn main() {
// bb0: {
// ...
// _2 = std::option::Option<i32>::Some(const 1i32,);
// _3 = discriminant(_2);
// _4 = &_2;
// _13 = discriminant(_2);
// switchInt(move _13) -> [1isize: bb2, otherwise: bb3];
// FakeRead(ForMatchedPlace, _2);
// _11 = discriminant(_2);
// _16 = &shallow _2;
// _17 = &((_2 as Some).0: i32);
// switchInt(move _11) -> [1isize: bb2, otherwise: bb3];
// }
// bb1: {
// resume;
// }
// bb2: {
// FakeRead(ForMatch, _4);
// FakeRead(ForMatchGuard, _16);
// FakeRead(ForMatchGuard, _17);
// falseEdges -> [real: bb7, imaginary: bb3]; //pre_binding1
// }
// bb3: {
// FakeRead(ForMatch, _4);
// FakeRead(ForMatchGuard, _16);
// FakeRead(ForMatchGuard, _17);
// falseEdges -> [real: bb11, imaginary: bb4]; //pre_binding2
// }
// bb4: {
// FakeRead(ForMatch, _4);
// FakeRead(ForMatchGuard, _16);
// FakeRead(ForMatchGuard, _17);
// falseEdges -> [real: bb12, imaginary: bb5]; //pre_binding3
// }
// bb5: {
// FakeRead(ForMatch, _4);
// FakeRead(ForMatchGuard, _16);
// FakeRead(ForMatchGuard, _17);
// falseEdges -> [real: bb16, imaginary: bb6]; //pre_binding4
// }
// bb6: {
// unreachable;
// }
// bb7: { // binding1: Some(w) if guard()
// StorageLive(_7);
// _7 = &((_2 as Some).0: i32);
// StorageLive(_14);
// _14 = const guard() -> [return: bb8, unwind: bb1];
// StorageLive(_5);
// _5 = &((_2 as Some).0: i32);
// StorageLive(_12);
// _12 = const guard() -> [return: bb8, unwind: bb1];
// }
// bb8: { //end of guard
// switchInt(move _14) -> [false: bb9, otherwise: bb10];
// switchInt(move _12) -> [false: bb9, otherwise: bb10];
// }
// bb9: { // to pre_binding2
// falseEdges -> [real: bb3, imaginary: bb3];
// }
// bb10: { // set up bindings for arm1
// StorageLive(_5);
// _5 = ((_2 as Some).0: i32);
// StorageLive(_3);
// _3 = ((_2 as Some).0: i32);
// _1 = const 1i32;
// goto -> bb17;
// }
// bb11: { // binding2 & arm2
// StorageLive(_8);
// _8 = _2;
// StorageLive(_6);
// _6 = _2;
// _1 = const 2i32;
// goto -> bb17;
// }
// bb12: { // binding3: Some(y) if guard2(y)
// StorageLive(_11);
// _11 = &((_2 as Some).0: i32);
// StorageLive(_16);
// StorageLive(_17);
// _17 = (*_11);
// _16 = const guard2(move _17) -> [return: bb13, unwind: bb1];
// StorageLive(_9);
// _9 = &((_2 as Some).0: i32);
// StorageLive(_14);
// StorageLive(_15);
// _15 = (*_9);
// _14 = const guard2(move _15) -> [return: bb13, unwind: bb1];
// }
// bb13: { // end of guard2
// StorageDead(_17);
// switchInt(move _16) -> [false: bb14, otherwise: bb15];
// StorageDead(_15);
// switchInt(move _14) -> [false: bb14, otherwise: bb15];
// }
// bb14: { // to pre_binding4
// falseEdges -> [real: bb5, imaginary: bb5];
// }
// bb15: { // set up bindings for arm3
// StorageLive(_9);
// _9 = ((_2 as Some).0: i32);
// StorageLive(_7);
// _7 = ((_2 as Some).0: i32);
// _1 = const 3i32;
// goto -> bb17;
// }
// bb16: { // binding4 & arm4
// StorageLive(_12);
// _12 = _2;
// StorageLive(_10);
// _10 = _2;
// _1 = const 4i32;
// goto -> bb17;
// }

View file

@ -0,0 +1,122 @@
// Test that the fake borrows for matches are removed after borrow checking.
// ignore-wasm32-bare
#![feature(nll)]
fn match_guard(x: Option<&&i32>) -> i32 {
match x {
Some(0) if true => 0,
_ => 1,
}
}
fn main() {
match_guard(None);
}
// END RUST SOURCE
// START rustc.match_guard.CleanFakeReadsAndBorrows.before.mir
// bb0: {
// FakeRead(ForMatchedPlace, _1);
// _2 = discriminant(_1);
// _3 = &shallow _1;
// _4 = &shallow ((_1 as Some).0: &'<empty> &'<empty> i32);
// _5 = &shallow (*((_1 as Some).0: &'<empty> &'<empty> i32));
// _6 = &shallow (*(*((_1 as Some).0: &'<empty> &'<empty> i32)));
// switchInt(move _2) -> [1isize: bb6, otherwise: bb4];
// }
// bb1: {
// _0 = const 0i32;
// goto -> bb9;
// }
// bb2: {
// _0 = const 1i32;
// goto -> bb9;
// }
// bb3: {
// FakeRead(ForMatchGuard, _3);
// FakeRead(ForMatchGuard, _4);
// FakeRead(ForMatchGuard, _5);
// FakeRead(ForMatchGuard, _6);
// goto -> bb7;
// }
// bb4: {
// FakeRead(ForMatchGuard, _3);
// FakeRead(ForMatchGuard, _4);
// FakeRead(ForMatchGuard, _5);
// FakeRead(ForMatchGuard, _6);
// goto -> bb2;
// }
// bb5: {
// unreachable;
// }
// bb6: {
// switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb3, otherwise: bb4];
// }
// bb7: {
// goto -> bb1;
// }
// bb8: {
// goto -> bb4;
// }
// bb9: {
// return;
// }
// bb10: {
// resume;
// }
// END rustc.match_guard.CleanFakeReadsAndBorrows.before.mir
// START rustc.match_guard.CleanFakeReadsAndBorrows.after.mir
// bb0: {
// nop;
// _2 = discriminant(_1);
// nop;
// nop;
// nop;
// nop;
// switchInt(move _2) -> [1isize: bb6, otherwise: bb4];
// }
// bb1: {
// _0 = const 0i32;
// goto -> bb9;
// }
// bb2: {
// _0 = const 1i32;
// goto -> bb9;
// }
// bb3: {
// nop;
// nop;
// nop;
// nop;
// goto -> bb7;
// }
// bb4: {
// nop;
// nop;
// nop;
// nop;
// goto -> bb2;
// }
// bb5: {
// unreachable;
// }
// bb6: {
// switchInt((*(*((_1 as Some).0: &'<empty> &'<empty> i32)))) -> [0i32: bb3, otherwise: bb4];
// }
// bb7: {
// goto -> bb1;
// }
// bb8: {
// goto -> bb4;
// }
// bb9: {
// return;
// }
// bb10: {
// resume;
// }
// END rustc.match_guard.CleanFakeReadsAndBorrows.after.mir

View file

@ -67,7 +67,6 @@ fn main() {
// Validate(Suspend(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 })), [(*_2): i32]);
// _3 = &ReErased (*_2);
// Validate(Acquire, [(*_3): i32/ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 }) (imm)]);
// FakeRead(ForLet, _3);
// _0 = (*_3);
// EndRegion(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 }));
// StorageDead(_3);

View file

@ -28,7 +28,6 @@ fn main() {
// Validate(Acquire, [_1: std::boxed::Box<[i32]>]);
// StorageDead(_2);
// StorageDead(_3);
// FakeRead(ForLet, _1);
// _0 = ();
// Validate(Release, [_1: std::boxed::Box<[i32]>]);
// drop(_1) -> [return: bb2, unwind: bb3];

View file

@ -47,12 +47,10 @@ fn main() {
// bb0: {
// StorageLive(_1);
// _1 = Test { x: const 0i32 };
// FakeRead(ForLet, _1);
// StorageLive(_2);
// Validate(Suspend(ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 })), [_1: Test]);
// _2 = &ReErased _1;
// Validate(Acquire, [(*_2): Test/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]);
// FakeRead(ForLet, _2);
// StorageLive(_4);
// StorageLive(_5);
// Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [((*_2).0: i32): i32/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]);

View file

@ -1,27 +1,3 @@
error[E0502]: cannot borrow `y` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-anon-fields-struct.rs:23:19
|
LL | Y(ref mut a, _) => a
| --------- mutable borrow occurs here
...
LL | let b = match y {
| ^ immutable borrow occurs here
...
LL | *a += 1;
| ------- borrow later used here
error[E0502]: cannot borrow `y` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-anon-fields-struct.rs:38:19
|
LL | Y(ref mut a, _) => a
| --------- mutable borrow occurs here
...
LL | let b = match y {
| ^ immutable borrow occurs here
...
LL | *a += 1;
| ------- borrow later used here
error[E0499]: cannot borrow `y.0` as mutable more than once at a time
--> $DIR/borrowck-anon-fields-struct.rs:39:11
|
@ -34,7 +10,6 @@ LL | Y(ref mut b, _) => b //~ ERROR cannot borrow
LL | *a += 1;
| ------- borrow later used here
error: aborting due to 3 previous errors
error: aborting due to previous error
Some errors occurred: E0499, E0502.
For more information about an error, try `rustc --explain E0499`.
For more information about this error, try `rustc --explain E0499`.

View file

@ -1,27 +1,3 @@
error[E0502]: cannot borrow `y` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-anon-fields-tuple.rs:21:19
|
LL | (ref mut a, _) => a
| --------- mutable borrow occurs here
...
LL | let b = match y {
| ^ immutable borrow occurs here
...
LL | *a += 1;
| ------- borrow later used here
error[E0502]: cannot borrow `y` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-anon-fields-tuple.rs:36:19
|
LL | (ref mut a, _) => a
| --------- mutable borrow occurs here
...
LL | let b = match y {
| ^ immutable borrow occurs here
...
LL | *a += 1;
| ------- borrow later used here
error[E0499]: cannot borrow `y.0` as mutable more than once at a time
--> $DIR/borrowck-anon-fields-tuple.rs:37:10
|
@ -34,7 +10,6 @@ LL | (ref mut b, _) => b //~ ERROR cannot borrow
LL | *a += 1;
| ------- borrow later used here
error: aborting due to 3 previous errors
error: aborting due to previous error
Some errors occurred: E0499, E0502.
For more information about an error, try `rustc --explain E0499`.
For more information about this error, try `rustc --explain E0499`.

View file

@ -1,27 +1,3 @@
error[E0502]: cannot borrow `y` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-anon-fields-variant.rs:26:19
|
LL | Foo::Y(ref mut a, _) => a,
| --------- mutable borrow occurs here
...
LL | let b = match y {
| ^ immutable borrow occurs here
...
LL | *a += 1;
| ------- borrow later used here
error[E0502]: cannot borrow `y` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-anon-fields-variant.rs:43:19
|
LL | Foo::Y(ref mut a, _) => a,
| --------- mutable borrow occurs here
...
LL | let b = match y {
| ^ immutable borrow occurs here
...
LL | *a += 1;
| ------- borrow later used here
error[E0499]: cannot borrow `y.0` as mutable more than once at a time
--> $DIR/borrowck-anon-fields-variant.rs:44:14
|
@ -34,7 +10,6 @@ LL | Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
LL | *a += 1;
| ------- borrow later used here
error: aborting due to 3 previous errors
error: aborting due to previous error
Some errors occurred: E0499, E0502.
For more information about an error, try `rustc --explain E0499`.
For more information about this error, try `rustc --explain E0499`.

View file

@ -28,17 +28,6 @@ LL | let _bar2 = &mut foo.bar1; //~ ERROR cannot borrow
LL | *bar1;
| ----- borrow later used here
error[E0502]: cannot borrow `*foo` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-borrow-from-owned-ptr.rs:72:11
|
LL | let bar1 = &mut foo.bar1;
| ------------- mutable borrow occurs here
LL | match *foo {
| ^^^^ immutable borrow occurs here
...
LL | *bar1;
| ----- borrow later used here
error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
--> $DIR/borrowck-borrow-from-owned-ptr.rs:73:21
|
@ -121,7 +110,7 @@ LL | let foo = make_foo();
LL | let bar1 = &mut foo.bar1; //~ ERROR cannot borrow
| ^^^^^^^^^^^^^ cannot borrow as mutable
error: aborting due to 12 previous errors
error: aborting due to 11 previous errors
Some errors occurred: E0499, E0502, E0596.
For more information about an error, try `rustc --explain E0499`.

View file

@ -28,17 +28,6 @@ LL | let _bar2 = &mut foo.bar1; //~ ERROR cannot borrow
LL | *bar1;
| ----- borrow later used here
error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-borrow-from-stack-variable.rs:70:11
|
LL | let bar1 = &mut foo.bar1;
| ------------- mutable borrow occurs here
LL | match foo {
| ^^^ immutable borrow occurs here
...
LL | *bar1;
| ----- borrow later used here
error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
--> $DIR/borrowck-borrow-from-stack-variable.rs:71:21
|
@ -121,7 +110,7 @@ LL | let foo = make_foo();
LL | let bar1 = &mut foo.bar1; //~ ERROR cannot borrow
| ^^^^^^^^^^^^^ cannot borrow as mutable
error: aborting due to 12 previous errors
error: aborting due to 11 previous errors
Some errors occurred: E0499, E0502, E0596.
For more information about an error, try `rustc --explain E0499`.

View file

@ -72,23 +72,12 @@ LL | //[mir]~^ ERROR cannot use `h.0` because it was mutably borrow
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `e` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:77:15
|
LL | let x = e.x();
| - borrow of `e` occurs here
LL | match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
| ^ use of borrowed `e`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `e.0` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:78:20
|
LL | let x = e.x();
| - borrow of `e` occurs here
LL | match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
LL | match e {
LL | Baz::X(value) => value
| ^^^^^ use of borrowed `e`
...
@ -139,23 +128,12 @@ LL | //[mir]~^ ERROR cannot use `h.0` because it was mutably borrow
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `*e` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:120:15
|
LL | let x = e.x();
| - borrow of `*e` occurs here
LL | match *e { //[mir]~ ERROR cannot use `*e` because it was mutably borrowed
| ^^ use of borrowed `*e`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `e.0` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:121:20
|
LL | let x = e.x();
| - borrow of `*e` occurs here
LL | match *e { //[mir]~ ERROR cannot use `*e` because it was mutably borrowed
LL | match *e {
LL | Baz::X(value) => value
| ^^^^^ use of borrowed `*e`
...
@ -173,41 +151,18 @@ LL | //[mir]~^ ERROR cannot use `u.a` because it was mutably borrow
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:139:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:140:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
LL | match v {
LL | &[x, _, .., _, _] => println!("{}", x),
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:145:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
...
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:146:18
|
@ -220,18 +175,6 @@ LL | &[_, x, .., _, _] => println!("{}", x),
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:151:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
...
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:152:25
|
@ -244,18 +187,6 @@ LL | &[_, _, .., x, _] => println!("{}", x),
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:157:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
...
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:158:28
|
@ -268,41 +199,18 @@ LL | &[_, _, .., _, x] => println!("{}", x),
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:169:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:170:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
LL | match v {
LL | &[x..] => println!("{:?}", x),
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:175:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
...
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:176:18
|
@ -315,18 +223,6 @@ LL | &[_, x..] => println!("{:?}", x),
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:181:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
...
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:182:15
|
@ -339,18 +235,6 @@ LL | &[x.., _] => println!("{:?}", x),
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:187:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
...
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:188:18
|
@ -363,23 +247,12 @@ LL | &[_, x.., _] => println!("{:?}", x),
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `e` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:201:15
|
LL | let x = &mut e;
| ------ borrow of `e` occurs here
LL | match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
| ^ use of borrowed `e`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `e` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:202:13
|
LL | let x = &mut e;
| ------ borrow of `e` occurs here
LL | match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
LL | match e {
LL | E::A(ref ax) =>
| ^^^^^^^^^^^^ use of borrowed `e`
...
@ -391,7 +264,7 @@ error[E0502]: cannot borrow `e.0` as immutable because it is also borrowed as mu
|
LL | let x = &mut e;
| ------ mutable borrow occurs here
LL | match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
LL | match e {
LL | E::A(ref ax) =>
| ^^^^^^ immutable borrow occurs here
...
@ -410,41 +283,18 @@ LL | E::B { x: ref bx } =>
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `s` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:220:15
|
LL | let x = &mut s;
| ------ borrow of `s` occurs here
LL | match s { //[mir]~ ERROR cannot use `s` because it was mutably borrowed
| ^ use of borrowed `s`
...
LL | drop(x);
| - borrow later used here
error[E0502]: cannot borrow `s.y.0` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-describe-lvalue.rs:221:22
|
LL | let x = &mut s;
| ------ mutable borrow occurs here
LL | match s { //[mir]~ ERROR cannot use `s` because it was mutably borrowed
LL | match s {
LL | S { y: (ref y0, _), .. } =>
| ^^^^^^ immutable borrow occurs here
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `s` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:227:15
|
LL | let x = &mut s;
| ------ borrow of `s` occurs here
...
LL | match s { //[mir]~ ERROR cannot use `s` because it was mutably borrowed
| ^ use of borrowed `s`
...
LL | drop(x);
| - borrow later used here
error[E0502]: cannot borrow `s.x.y` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-describe-lvalue.rs:228:28
|
@ -479,23 +329,12 @@ LL | v[0].y;
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:282:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0502]: cannot borrow `v[..].x` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-describe-lvalue.rs:283:24
|
LL | let x = &mut v;
| ------ mutable borrow occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
LL | match v {
LL | &[_, F {x: ref xf, ..}] => println!("{}", xf),
| ^^^^^^ immutable borrow occurs here
...
@ -534,7 +373,7 @@ LL | drop(x); //[ast]~ ERROR use of moved value: `x`
|
= note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
error: aborting due to 46 previous errors
error: aborting due to 32 previous errors
Some errors occurred: E0382, E0499, E0502, E0503.
For more information about an error, try `rustc --explain E0382`.

View file

@ -27,7 +27,7 @@ error[E0503]: cannot use `e.0` because it was mutably borrowed
|
LL | let x = e.x();
| - borrow of `e` occurs here
LL | match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
LL | match e {
LL | Baz::X(value) => value
| ^^^^^ use of borrowed `e`
@ -68,7 +68,7 @@ error[E0503]: cannot use `e.0` because it was mutably borrowed
|
LL | let x = e.x();
| - borrow of `*e` occurs here
LL | match *e { //[mir]~ ERROR cannot use `*e` because it was mutably borrowed
LL | match *e {
LL | Baz::X(value) => value
| ^^^^^ use of borrowed `*e`
@ -85,7 +85,7 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
LL | let x = &mut v;
| - borrow of `v` occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
LL | match v {
LL | &[x, _, .., _, _] => println!("{}", x),
| ^ use of borrowed `v`
@ -121,7 +121,7 @@ error[E0503]: cannot use `v[..]` because it was mutably borrowed
|
LL | let x = &mut v;
| - borrow of `v` occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
LL | match v {
LL | &[x..] => println!("{:?}", x),
| ^ use of borrowed `v`
@ -157,7 +157,7 @@ error[E0502]: cannot borrow `e.0` as immutable because `e` is also borrowed as m
|
LL | let x = &mut e;
| - mutable borrow occurs here
LL | match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
LL | match e {
LL | E::A(ref ax) =>
| ^^^^^^ immutable borrow occurs here
...
@ -181,7 +181,7 @@ error[E0502]: cannot borrow `s.y.0` as immutable because `s` is also borrowed as
|
LL | let x = &mut s;
| - mutable borrow occurs here
LL | match s { //[mir]~ ERROR cannot use `s` because it was mutably borrowed
LL | match s {
LL | S { y: (ref y0, _), .. } =>
| ^^^^^^ immutable borrow occurs here
...

View file

@ -72,23 +72,12 @@ LL | //[mir]~^ ERROR cannot use `h.0` because it was mutably borrow
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `e` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:77:15
|
LL | let x = e.x();
| - borrow of `e` occurs here
LL | match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
| ^ use of borrowed `e`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `e.0` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:78:20
|
LL | let x = e.x();
| - borrow of `e` occurs here
LL | match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
LL | match e {
LL | Baz::X(value) => value
| ^^^^^ use of borrowed `e`
...
@ -139,23 +128,12 @@ LL | //[mir]~^ ERROR cannot use `h.0` because it was mutably borrow
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `*e` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:120:15
|
LL | let x = e.x();
| - borrow of `*e` occurs here
LL | match *e { //[mir]~ ERROR cannot use `*e` because it was mutably borrowed
| ^^ use of borrowed `*e`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `e.0` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:121:20
|
LL | let x = e.x();
| - borrow of `*e` occurs here
LL | match *e { //[mir]~ ERROR cannot use `*e` because it was mutably borrowed
LL | match *e {
LL | Baz::X(value) => value
| ^^^^^ use of borrowed `*e`
...
@ -173,41 +151,18 @@ LL | //[mir]~^ ERROR cannot use `u.a` because it was mutably borrow
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:139:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:140:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
LL | match v {
LL | &[x, _, .., _, _] => println!("{}", x),
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:145:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
...
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:146:18
|
@ -220,18 +175,6 @@ LL | &[_, x, .., _, _] => println!("{}", x),
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:151:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
...
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:152:25
|
@ -244,18 +187,6 @@ LL | &[_, _, .., x, _] => println!("{}", x),
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:157:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
...
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:158:28
|
@ -268,41 +199,18 @@ LL | &[_, _, .., _, x] => println!("{}", x),
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:169:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:170:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
LL | match v {
LL | &[x..] => println!("{:?}", x),
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:175:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
...
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:176:18
|
@ -315,18 +223,6 @@ LL | &[_, x..] => println!("{:?}", x),
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:181:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
...
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:182:15
|
@ -339,18 +235,6 @@ LL | &[x.., _] => println!("{:?}", x),
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:187:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
...
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v[..]` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:188:18
|
@ -363,23 +247,12 @@ LL | &[_, x.., _] => println!("{:?}", x),
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `e` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:201:15
|
LL | let x = &mut e;
| ------ borrow of `e` occurs here
LL | match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
| ^ use of borrowed `e`
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `e` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:202:13
|
LL | let x = &mut e;
| ------ borrow of `e` occurs here
LL | match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
LL | match e {
LL | E::A(ref ax) =>
| ^^^^^^^^^^^^ use of borrowed `e`
...
@ -391,7 +264,7 @@ error[E0502]: cannot borrow `e.0` as immutable because it is also borrowed as mu
|
LL | let x = &mut e;
| ------ mutable borrow occurs here
LL | match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
LL | match e {
LL | E::A(ref ax) =>
| ^^^^^^ immutable borrow occurs here
...
@ -410,41 +283,18 @@ LL | E::B { x: ref bx } =>
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `s` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:220:15
|
LL | let x = &mut s;
| ------ borrow of `s` occurs here
LL | match s { //[mir]~ ERROR cannot use `s` because it was mutably borrowed
| ^ use of borrowed `s`
...
LL | drop(x);
| - borrow later used here
error[E0502]: cannot borrow `s.y.0` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-describe-lvalue.rs:221:22
|
LL | let x = &mut s;
| ------ mutable borrow occurs here
LL | match s { //[mir]~ ERROR cannot use `s` because it was mutably borrowed
LL | match s {
LL | S { y: (ref y0, _), .. } =>
| ^^^^^^ immutable borrow occurs here
...
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `s` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:227:15
|
LL | let x = &mut s;
| ------ borrow of `s` occurs here
...
LL | match s { //[mir]~ ERROR cannot use `s` because it was mutably borrowed
| ^ use of borrowed `s`
...
LL | drop(x);
| - borrow later used here
error[E0502]: cannot borrow `s.x.y` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-describe-lvalue.rs:228:28
|
@ -479,23 +329,12 @@ LL | v[0].y;
LL | drop(x);
| - borrow later used here
error[E0503]: cannot use `v` because it was mutably borrowed
--> $DIR/borrowck-describe-lvalue.rs:282:15
|
LL | let x = &mut v;
| ------ borrow of `v` occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
| ^ use of borrowed `v`
...
LL | drop(x);
| - borrow later used here
error[E0502]: cannot borrow `v[..].x` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-describe-lvalue.rs:283:24
|
LL | let x = &mut v;
| ------ mutable borrow occurs here
LL | match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
LL | match v {
LL | &[_, F {x: ref xf, ..}] => println!("{}", xf),
| ^^^^^^ immutable borrow occurs here
...
@ -534,7 +373,7 @@ LL | drop(x); //[ast]~ ERROR use of moved value: `x`
|
= note: move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
error: aborting due to 46 previous errors
error: aborting due to 32 previous errors
Some errors occurred: E0382, E0499, E0502, E0503.
For more information about an error, try `rustc --explain E0382`.

View file

@ -74,7 +74,7 @@ fn main() {
{
let mut e = Baz::X(2);
let x = e.x();
match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
match e {
Baz::X(value) => value
//[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed
//[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed
@ -117,7 +117,7 @@ fn main() {
{
let mut e = Box::new(Baz::X(3));
let x = e.x();
match *e { //[mir]~ ERROR cannot use `*e` because it was mutably borrowed
match *e {
Baz::X(value) => value
//[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed
//[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed
@ -136,25 +136,25 @@ fn main() {
{
let mut v = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let x = &mut v;
match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
match v {
&[x, _, .., _, _] => println!("{}", x),
//[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
//[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
_ => panic!("other case"),
}
match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
match v {
&[_, x, .., _, _] => println!("{}", x),
//[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
//[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
_ => panic!("other case"),
}
match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
match v {
&[_, _, .., x, _] => println!("{}", x),
//[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
//[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
_ => panic!("other case"),
}
match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
match v {
&[_, _, .., _, x] => println!("{}", x),
//[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
//[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
@ -166,25 +166,25 @@ fn main() {
{
let mut v = &[1, 2, 3, 4, 5];
let x = &mut v;
match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
match v {
&[x..] => println!("{:?}", x),
//[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
//[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
_ => panic!("other case"),
}
match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
match v {
&[_, x..] => println!("{:?}", x),
//[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
//[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
_ => panic!("other case"),
}
match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
match v {
&[x.., _] => println!("{:?}", x),
//[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
//[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
_ => panic!("other case"),
}
match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
match v {
&[_, x.., _] => println!("{:?}", x),
//[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
//[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed
@ -198,7 +198,7 @@ fn main() {
let mut e = E::A(3);
let x = &mut e;
match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed
match e {
E::A(ref ax) =>
//[ast]~^ ERROR cannot borrow `e.0` as immutable because `e` is also borrowed as mutable
//[mir]~^^ ERROR cannot borrow `e.0` as immutable because it is also borrowed as mutable
@ -217,14 +217,14 @@ fn main() {
struct S { x: F, y: (u32, u32), };
let mut s = S { x: F { x: 1, y: 2}, y: (999, 998) };
let x = &mut s;
match s { //[mir]~ ERROR cannot use `s` because it was mutably borrowed
match s {
S { y: (ref y0, _), .. } =>
//[ast]~^ ERROR cannot borrow `s.y.0` as immutable because `s` is also borrowed as mutable
//[mir]~^^ ERROR cannot borrow `s.y.0` as immutable because it is also borrowed as mutable
println!("y0: {:?}", y0),
_ => panic!("other case"),
}
match s { //[mir]~ ERROR cannot use `s` because it was mutably borrowed
match s {
S { x: F { y: ref x0, .. }, .. } =>
//[ast]~^ ERROR cannot borrow `s.x.y` as immutable because `s` is also borrowed as mutable
//[mir]~^^ ERROR cannot borrow `s.x.y` as immutable because it is also borrowed as mutable
@ -279,7 +279,7 @@ fn main() {
struct F {x: u32, y: u32};
let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}];
let x = &mut v;
match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed
match v {
&[_, F {x: ref xf, ..}] => println!("{}", xf),
//[mir]~^ ERROR cannot borrow `v[..].x` as immutable because it is also borrowed as mutable
// No errors in AST

View file

@ -1,20 +1,9 @@
error[E0503]: cannot use `foo` because it was mutably borrowed
--> $DIR/borrowck-match-already-borrowed.rs:22:19
|
LL | let p = &mut foo;
| -------- borrow of `foo` occurs here
LL | let _ = match foo { //[mir]~ ERROR [E0503]
| ^^^ use of borrowed `foo`
...
LL | drop(p);
| - borrow later used here
error[E0503]: cannot use `foo` because it was mutably borrowed
--> $DIR/borrowck-match-already-borrowed.rs:23:9
|
LL | let p = &mut foo;
| -------- borrow of `foo` occurs here
LL | let _ = match foo { //[mir]~ ERROR [E0503]
LL | let _ = match foo {
LL | Foo::B => 1, //[mir]~ ERROR [E0503]
| ^^^^^^ use of borrowed `foo`
...
@ -33,23 +22,12 @@ LL | Foo::A(x) => x //[ast]~ ERROR [E0503]
LL | drop(p);
| - borrow later used here
error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/borrowck-match-already-borrowed.rs:35:19
|
LL | let r = &mut x;
| ------ borrow of `x` occurs here
LL | let _ = match x { //[mir]~ ERROR [E0503]
| ^ use of borrowed `x`
...
LL | drop(r);
| - borrow later used here
error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/borrowck-match-already-borrowed.rs:36:9
|
LL | let r = &mut x;
| ------ borrow of `x` occurs here
LL | let _ = match x { //[mir]~ ERROR [E0503]
LL | let _ = match x {
LL | x => x + 1, //[ast]~ ERROR [E0503]
| ^ use of borrowed `x`
...
@ -68,6 +46,6 @@ LL | y => y + 2, //[ast]~ ERROR [E0503]
LL | drop(r);
| - borrow later used here
error: aborting due to 6 previous errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0503`.

View file

@ -12,7 +12,7 @@ error[E0503]: cannot use `x` because it was mutably borrowed
|
LL | let r = &mut x;
| - borrow of `x` occurs here
LL | let _ = match x { //[mir]~ ERROR [E0503]
LL | let _ = match x {
LL | x => x + 1, //[ast]~ ERROR [E0503]
| ^ use of borrowed `x`

View file

@ -1,20 +1,9 @@
error[E0503]: cannot use `foo` because it was mutably borrowed
--> $DIR/borrowck-match-already-borrowed.rs:22:19
|
LL | let p = &mut foo;
| -------- borrow of `foo` occurs here
LL | let _ = match foo { //[mir]~ ERROR [E0503]
| ^^^ use of borrowed `foo`
...
LL | drop(p);
| - borrow later used here
error[E0503]: cannot use `foo` because it was mutably borrowed
--> $DIR/borrowck-match-already-borrowed.rs:23:9
|
LL | let p = &mut foo;
| -------- borrow of `foo` occurs here
LL | let _ = match foo { //[mir]~ ERROR [E0503]
LL | let _ = match foo {
LL | Foo::B => 1, //[mir]~ ERROR [E0503]
| ^^^^^^ use of borrowed `foo`
...
@ -33,23 +22,12 @@ LL | Foo::A(x) => x //[ast]~ ERROR [E0503]
LL | drop(p);
| - borrow later used here
error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/borrowck-match-already-borrowed.rs:35:19
|
LL | let r = &mut x;
| ------ borrow of `x` occurs here
LL | let _ = match x { //[mir]~ ERROR [E0503]
| ^ use of borrowed `x`
...
LL | drop(r);
| - borrow later used here
error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/borrowck-match-already-borrowed.rs:36:9
|
LL | let r = &mut x;
| ------ borrow of `x` occurs here
LL | let _ = match x { //[mir]~ ERROR [E0503]
LL | let _ = match x {
LL | x => x + 1, //[ast]~ ERROR [E0503]
| ^ use of borrowed `x`
...
@ -68,6 +46,6 @@ LL | y => y + 2, //[ast]~ ERROR [E0503]
LL | drop(r);
| - borrow later used here
error: aborting due to 6 previous errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0503`.

View file

@ -19,7 +19,7 @@ enum Foo {
fn match_enum() {
let mut foo = Foo::B;
let p = &mut foo;
let _ = match foo { //[mir]~ ERROR [E0503]
let _ = match foo {
Foo::B => 1, //[mir]~ ERROR [E0503]
_ => 2,
Foo::A(x) => x //[ast]~ ERROR [E0503]
@ -32,7 +32,7 @@ fn match_enum() {
fn main() {
let mut x = 1;
let r = &mut x;
let _ = match x { //[mir]~ ERROR [E0503]
let _ = match x {
x => x + 1, //[ast]~ ERROR [E0503]
//[mir]~^ ERROR [E0503]
y => y + 2, //[ast]~ ERROR [E0503]

View file

@ -1,47 +0,0 @@
warning: this constant cannot be used
--> $DIR/conditional_array_execution.rs:15:1
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| attempt to subtract with overflow
|
note: lint level defined here
--> $DIR/conditional_array_execution.rs:11:9
|
LL | #![warn(const_err)]
| ^^^^^^^^^
error[E0080]: referenced constant has errors
--> $DIR/conditional_array_execution.rs:19:14
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ----- attempt to subtract with overflow
...
LL | println!("{}", FOO);
| ^^^^
error[E0080]: erroneous constant used
--> $DIR/conditional_array_execution.rs:19:14
|
LL | println!("{}", FOO);
| ^^^^ --- referenced constant has errors
error[E0080]: referenced constant has errors
--> $DIR/conditional_array_execution.rs:19:20
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ----- attempt to subtract with overflow
...
LL | println!("{}", FOO);
| ^^^
error[E0080]: erroneous constant used
--> $DIR/conditional_array_execution.rs:19:20
|
LL | println!("{}", FOO);
| ^^^ referenced constant has errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0080`.

View file

@ -1,70 +0,0 @@
warning: this constant cannot be used
--> $DIR/issue-43197.rs:20:5
|
LL | const X: u32 = 0-1;
| ^^^^^^^^^^^^^^^---^
| |
| attempt to subtract with overflow
|
note: lint level defined here
--> $DIR/issue-43197.rs:11:9
|
LL | #![warn(const_err)]
| ^^^^^^^^^
warning: this constant cannot be used
--> $DIR/issue-43197.rs:22:5
|
LL | const Y: u32 = foo(0-1);
| ^^^^^^^^^^^^^^^^^^^---^^
| |
| attempt to subtract with overflow
error[E0080]: referenced constant has errors
--> $DIR/issue-43197.rs:24:14
|
LL | const X: u32 = 0-1;
| --- attempt to subtract with overflow
...
LL | println!("{} {}", X, Y);
| ^^^^^^^
error[E0080]: erroneous constant used
--> $DIR/issue-43197.rs:24:14
|
LL | println!("{} {}", X, Y);
| ^^^^^^^ - referenced constant has errors
error[E0080]: referenced constant has errors
--> $DIR/issue-43197.rs:24:26
|
LL | const Y: u32 = foo(0-1);
| --- attempt to subtract with overflow
LL | //~^ WARN this constant cannot be used
LL | println!("{} {}", X, Y);
| ^
error[E0080]: erroneous constant used
--> $DIR/issue-43197.rs:24:26
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
error[E0080]: referenced constant has errors
--> $DIR/issue-43197.rs:24:23
|
LL | const X: u32 = 0-1;
| --- attempt to subtract with overflow
...
LL | println!("{} {}", X, Y);
| ^
error[E0080]: erroneous constant used
--> $DIR/issue-43197.rs:24:23
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0080`.

View file

@ -1,33 +0,0 @@
error[E0080]: referenced constant has errors
--> $DIR/issue-44578.rs:35:14
|
LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
| ------------------------------------ index out of bounds: the len is 1 but the index is 1
...
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^
error[E0080]: erroneous constant used
--> $DIR/issue-44578.rs:35:14
|
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^ -------------------------- referenced constant has errors
error[E0080]: referenced constant has errors
--> $DIR/issue-44578.rs:35:20
|
LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
| ------------------------------------ index out of bounds: the len is 1 but the index is 1
...
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: erroneous constant used
--> $DIR/issue-44578.rs:35:20
|
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0080`.

View file

@ -24,7 +24,6 @@ fn main() {
match b {
&mut false => {},
_ if { (|| { let bar = b; *bar = false; })();
//~^ ERROR cannot move out of `b` because it is borrowed [E0505]
false } => { },
&mut true => { println!("You might think we should get here"); },
//~^ ERROR use of moved value: `*b` [E0382]

View file

@ -1,29 +1,14 @@
error[E0505]: cannot move out of `b` because it is borrowed
--> $DIR/issue-27282-move-match-input-into-guard.rs:26:17
|
LL | match b {
| - borrow of `b` occurs here
LL | &mut false => {},
LL | _ if { (|| { let bar = b; *bar = false; })();
| ^^ - move occurs due to use in closure
| |
| move out of `b` occurs here
...
LL | &mut true => { println!("You might think we should get here"); },
| --------- borrow later used here
error[E0382]: use of moved value: `*b`
--> $DIR/issue-27282-move-match-input-into-guard.rs:29:14
--> $DIR/issue-27282-move-match-input-into-guard.rs:28:14
|
LL | _ if { (|| { let bar = b; *bar = false; })();
| -- - variable moved due to use in closure
| |
| value moved into closure here
...
LL | false } => { },
LL | &mut true => { println!("You might think we should get here"); },
| ^^^^ value used here after move
error: aborting due to 2 previous errors
error: aborting due to previous error
Some errors occurred: E0382, E0505.
For more information about an error, try `rustc --explain E0382`.
For more information about this error, try `rustc --explain E0382`.

View file

@ -31,7 +31,7 @@ fn main() {
&mut Some(&_) if {
// ForceFnOnce needed to exploit #27282
(|| { *x = None; drop(force_fn_once); })();
//~^ ERROR closure requires unique access to `x` but it is already borrowed [E0500]
//~^ ERROR cannot mutably borrow `x` in match guard [E0510]
false
} => {}
&mut Some(&a) if { // this binds to garbage if we've corrupted discriminant

View file

@ -1,17 +1,14 @@
error[E0500]: closure requires unique access to `x` but it is already borrowed
error[E0510]: cannot mutably borrow `x` in match guard
--> $DIR/issue-27282-mutate-before-diverging-arm-1.rs:33:14
|
LL | match x {
| - borrow occurs here
| - value is immutable in match guard
...
LL | (|| { *x = None; drop(force_fn_once); })();
| ^^ - second borrow occurs due to use of `x` in closure
| ^^ - borrow occurs due to use of `x` in closure
| |
| closure construction occurs here
...
LL | &mut Some(&a) if { // this binds to garbage if we've corrupted discriminant
| ------------- borrow later used here
| cannot mutably borrow
error: aborting due to previous error
For more information about this error, try `rustc --explain E0500`.
For more information about this error, try `rustc --explain E0510`.

View file

@ -36,7 +36,7 @@ fn main() {
if {
// ForceFnOnce needed to exploit #27282
(|| { *x = None; drop(force_fn_once); })();
//~^ ERROR closure requires unique access to `x` but it is already borrowed [E0500]
//~^ ERROR cannot mutably borrow `x` in match guard [E0510]
false
} => {}

View file

@ -1,17 +1,14 @@
error[E0500]: closure requires unique access to `x` but it is already borrowed
error[E0510]: cannot mutably borrow `x` in match guard
--> $DIR/issue-27282-mutate-before-diverging-arm-2.rs:38:18
|
LL | match x {
| - borrow occurs here
| - value is immutable in match guard
...
LL | (|| { *x = None; drop(force_fn_once); })();
| ^^ - second borrow occurs due to use of `x` in closure
| ^^ - borrow occurs due to use of `x` in closure
| |
| closure construction occurs here
...
LL | &mut Some(&2)
| ------------- borrow later used here
| cannot mutably borrow
error: aborting due to previous error
For more information about this error, try `rustc --explain E0500`.
For more information about this error, try `rustc --explain E0510`.

View file

@ -0,0 +1,30 @@
// This is testing an attempt to corrupt the discriminant of the match
// arm in a guard, followed by an attempt to continue matching on that
// corrupted discriminant in the remaining match arms.
//
// Basically this is testing that our new NLL feature of emitting a
// fake read on each match arm is catching cases like this.
//
// This case is interesting because a borrow of **x is untracked, because **x is
// immutable. However, for matches we care that **x refers to the same value
// until we have chosen a match arm.
#![feature(nll)]
struct ForceFnOnce;
fn main() {
let mut x = &mut &Some(&2);
let force_fn_once = ForceFnOnce;
match **x {
None => panic!("unreachable"),
Some(&_) if {
// ForceFnOnce needed to exploit #27282
(|| { *x = &None; drop(force_fn_once); })();
//~^ ERROR cannot mutably borrow `x` in match guard [E0510]
false
} => {}
Some(&a) if { // this binds to garbage if we've corrupted discriminant
println!("{}", a);
panic!()
} => {}
_ => panic!("unreachable"),
}
}

View file

@ -0,0 +1,14 @@
error[E0510]: cannot mutably borrow `x` in match guard
--> $DIR/issue-27282-mutate-before-diverging-arm-3.rs:20:14
|
LL | match **x {
| --- value is immutable in match guard
...
LL | (|| { *x = &None; drop(force_fn_once); })();
| ^^ - borrow occurs due to use of `x` in closure
| |
| cannot mutably borrow
error: aborting due to previous error
For more information about this error, try `rustc --explain E0510`.

View file

@ -21,7 +21,7 @@ fn main() {
let mut e = Xyz::A;
let f = &mut e;
let g = f;
match e { //~ cannot use `e` because it was mutably borrowed [E0503]
match e {
Xyz::A => println!("a"),
//~^ cannot use `e` because it was mutably borrowed [E0503]
Xyz::B => println!("b"),

View file

@ -1,15 +1,3 @@
error[E0503]: cannot use `e` because it was mutably borrowed
--> $DIR/borrowed-match-issue-45045.rs:24:11
|
LL | let f = &mut e;
| ------ borrow of `e` occurs here
LL | let g = f;
LL | match e { //~ cannot use `e` because it was mutably borrowed [E0503]
| ^ use of borrowed `e`
...
LL | *g = Xyz::B;
| ----------- borrow later used here
error[E0503]: cannot use `e` because it was mutably borrowed
--> $DIR/borrowed-match-issue-45045.rs:25:9
|
@ -22,6 +10,6 @@ LL | Xyz::A => println!("a"),
LL | *g = Xyz::B;
| ----------- borrow later used here
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0503`.

View file

@ -0,0 +1,164 @@
// Test that a (partially) mutably borrowed place can be matched on, so long as
// we don't have to read any values that are mutably borrowed to determine
// which arm to take.
//
// Test that we don't allow mutating the value being matched on in a way that
// changes which patterns it matches, until we have chosen an arm.
// compile-flags: -Zdisable-ast-check-for-mutation-in-guard
#![feature(nll)]
fn ok_mutation_in_guard(mut q: i32) {
match q {
// OK, mutation doesn't change which patterns g matches
_ if { q = 1; false } => (),
_ => (),
}
}
fn ok_indirect_mutation_in_guard(mut p: &bool) {
match *p {
// OK, mutation doesn't change which patterns s matches
_ if {
p = &true;
false
} => (),
_ => (),
}
}
fn mutation_invalidates_pattern_in_guard(mut q: bool) {
match q {
// s doesn't match the pattern with the guard by the end of the guard.
false if {
q = true; //~ ERROR
true
} => (),
_ => (),
}
}
fn mutation_invalidates_previous_pattern_in_guard(mut r: bool) {
match r {
// s matches a previous pattern by the end of the guard.
true => (),
_ if {
r = true; //~ ERROR
true
} => (),
_ => (),
}
}
fn match_on_borrowed_early_end(mut s: bool) {
let h = &mut s;
match s { //~ ERROR
// s changes value between the start of the match and when its value is checked.
_ if {
*h = !*h;
false
} => (),
true => (),
false => (),
}
}
fn bad_mutation_in_guard(mut t: bool) {
match t {
true => (),
false if {
t = true; //~ ERROR
false
} => (),
false => (),
}
}
fn bad_mutation_in_guard2(mut u: bool) {
match u {
// Guard changes the value bound in the last pattern.
_ => (),
_ if {
u = true; //~ ERROR
false
} => (),
x => (),
}
}
pub fn bad_mutation_in_guard3(mut x: Option<Option<&i32>>) {
// Check that nested patterns are checked.
match x {
None => (),
Some(None) => (),
_ if {
match x {
Some(ref mut r) => *r = None, //~ ERROR
_ => return,
};
false
} => (),
Some(Some(r)) => println!("{}", r),
}
}
fn bad_mutation_in_guard4(mut w: (&mut bool,)) {
match w {
// Guard changes the value bound in the last pattern.
_ => (),
_ if {
*w.0 = true; //~ ERROR
false
} => (),
x => (),
}
}
fn bad_indirect_mutation_in_guard(mut y: &bool) {
match *y {
true => (),
false if {
y = &true; //~ ERROR
false
} => (),
false => (),
}
}
fn bad_indirect_mutation_in_guard2(mut z: &bool) {
match z {
&true => (),
&false if {
z = &true; //~ ERROR
false
} => (),
&false => (),
}
}
fn bad_indirect_mutation_in_guard3(mut a: &bool) {
// Same as bad_indirect_mutation_in_guard2, but using match ergonomics
match a {
true => (),
false if {
a = &true; //~ ERROR
false
} => (),
false => (),
}
}
fn bad_indirect_mutation_in_guard4(mut b: &bool) {
match b {
&_ => (),
&_ if {
b = &true; //~ ERROR
false
} => (),
&b => (),
}
}
fn main() {}

View file

@ -0,0 +1,132 @@
error[E0510]: cannot assign `q` in match guard
--> $DIR/match-guards-partially-borrow.rs:35:13
|
LL | match q {
| - value is immutable in match guard
...
LL | q = true; //~ ERROR
| ^^^^^^^^ cannot assign
...
LL | _ => (),
| - borrow later used here
error[E0510]: cannot assign `r` in match guard
--> $DIR/match-guards-partially-borrow.rs:47:13
|
LL | match r {
| - value is immutable in match guard
...
LL | r = true; //~ ERROR
| ^^^^^^^^ cannot assign
...
LL | _ => (),
| - borrow later used here
error[E0503]: cannot use `s` because it was mutably borrowed
--> $DIR/match-guards-partially-borrow.rs:56:11
|
LL | let h = &mut s;
| ------ borrow of `s` occurs here
LL | match s { //~ ERROR
| ^ use of borrowed `s`
...
LL | *h = !*h;
| -- borrow later used here
error[E0510]: cannot assign `t` in match guard
--> $DIR/match-guards-partially-borrow.rs:71:13
|
LL | match t {
| - value is immutable in match guard
...
LL | t = true; //~ ERROR
| ^^^^^^^^ cannot assign
...
LL | false => (),
| ----- borrow later used here
error[E0506]: cannot assign to `u` because it is borrowed
--> $DIR/match-guards-partially-borrow.rs:83:13
|
LL | match u {
| - borrow of `u` occurs here
...
LL | u = true; //~ ERROR
| ^^^^^^^^ assignment to borrowed `u` occurs here
...
LL | x => (),
| - borrow later used here
error[E0510]: cannot mutably borrow `x.0` in match guard
--> $DIR/match-guards-partially-borrow.rs:97:22
|
LL | match x {
| - value is immutable in match guard
...
LL | Some(ref mut r) => *r = None, //~ ERROR
| ^^^^^^^^^ cannot mutably borrow
error[E0506]: cannot assign to `*w.0` because it is borrowed
--> $DIR/match-guards-partially-borrow.rs:112:13
|
LL | match w {
| - borrow of `*w.0` occurs here
...
LL | *w.0 = true; //~ ERROR
| ^^^^^^^^^^^ assignment to borrowed `*w.0` occurs here
...
LL | x => (),
| - borrow later used here
error[E0510]: cannot assign `y` in match guard
--> $DIR/match-guards-partially-borrow.rs:123:13
|
LL | match *y {
| -- value is immutable in match guard
...
LL | y = &true; //~ ERROR
| ^^^^^^^^^ cannot assign
...
LL | false => (),
| ----- borrow later used here
error[E0510]: cannot assign `z` in match guard
--> $DIR/match-guards-partially-borrow.rs:134:13
|
LL | match z {
| - value is immutable in match guard
...
LL | z = &true; //~ ERROR
| ^^^^^^^^^ cannot assign
...
LL | &false => (),
| ------ borrow later used here
error[E0510]: cannot assign `a` in match guard
--> $DIR/match-guards-partially-borrow.rs:146:13
|
LL | match a {
| - value is immutable in match guard
...
LL | a = &true; //~ ERROR
| ^^^^^^^^^ cannot assign
...
LL | false => (),
| ----- borrow later used here
error[E0510]: cannot assign `b` in match guard
--> $DIR/match-guards-partially-borrow.rs:157:13
|
LL | match b {
| - value is immutable in match guard
...
LL | b = &true; //~ ERROR
| ^^^^^^^^^ cannot assign
...
LL | &b => (),
| -- borrow later used here
error: aborting due to 11 previous errors
Some errors occurred: E0503, E0506, E0510.
For more information about an error, try `rustc --explain E0503`.

View file

@ -0,0 +1,95 @@
// Test that a (partially) mutably borrowed place can be matched on, so long as
// we don't have to read any values that are mutably borrowed to determine
// which arm to take.
//
// Test that we don't allow mutating the value being matched on in a way that
// changes which patterns it matches, until we have chosen an arm.
#![feature(nll)]
struct A(i32, i32);
fn struct_example(mut a: A) {
let x = &mut a.0;
match a { // OK, no access of borrowed data
_ if false => (),
A(_, r) => (),
}
x;
}
fn indirect_struct_example(mut b: &mut A) {
let x = &mut b.0;
match *b { // OK, no access of borrowed data
_ if false => (),
A(_, r) => (),
}
x;
}
fn underscore_example(mut c: i32) {
let r = &mut c;
match c { // OK, no access of borrowed data (or any data at all)
_ if false => (),
_ => (),
}
r;
}
enum E {
V(i32, i32),
W,
}
fn enum_example(mut e: E) {
let x = match e {
E::V(ref mut x, _) => x,
E::W => panic!(),
};
match e { // OK, no access of borrowed data
_ if false => (),
E::V(_, r) => (),
E::W => (),
}
x;
}
fn indirect_enum_example(mut f: &mut E) {
let x = match *f {
E::V(ref mut x, _) => x,
E::W => panic!(),
};
match f { // OK, no access of borrowed data
_ if false => (),
E::V(_, r) => (),
E::W => (),
}
x;
}
fn match_on_muatbly_borrowed_ref(mut p: &bool) {
let r = &mut p;
match *p { // OK, no access at all
_ if false => (),
_ => (),
}
r;
}
fn match_on_borrowed(mut t: bool) {
let x = &mut t;
match t {
true => (), //~ ERROR
false => (),
}
x;
}
enum Never {}
fn never_init() {
let n: Never;
match n {} //~ ERROR
}
fn main() {}

View file

@ -0,0 +1,22 @@
error[E0503]: cannot use `t` because it was mutably borrowed
--> $DIR/match-on-borrowed.rs:82:9
|
LL | let x = &mut t;
| ------ borrow of `t` occurs here
LL | match t {
LL | true => (), //~ ERROR
| ^^^^ use of borrowed `t`
...
LL | x;
| - borrow later used here
error[E0381]: use of possibly uninitialized variable: `n`
--> $DIR/match-on-borrowed.rs:92:11
|
LL | match n {} //~ ERROR
| ^ use of possibly uninitialized `n`
error: aborting due to 2 previous errors
Some errors occurred: E0381, E0503.
For more information about an error, try `rustc --explain E0381`.