]> git.lizzy.rs Git - rust.git/commitdiff
Fallout from allowing some mutation in guards.
authorFelix S. Klock II <pnkfelix@pnkfx.org>
Mon, 7 May 2018 13:58:09 +0000 (15:58 +0200)
committerFelix S. Klock II <pnkfelix@pnkfx.org>
Tue, 29 May 2018 21:02:40 +0000 (23:02 +0200)
For some reason, allowing restricted mutation in match arms exposed an
obvious case where a unique borrow can indeed fail, namely something
like:

```rust
match b {
    ...
    ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); false } => { &mut *r }
    //                             ~~~~~~~
    //                                |
    // This ends up holding a `&unique` borrow of `r`, but there ends up being an
    // implicit shared borrow in the guard thanks to rust-lang/rust#49870
    ...
}
```

src/librustc_mir/borrow_check/mod.rs

index 233974435f3f835ba8c4316979703cb5573349c8..ec267104518e46f0a22f80dec94814e3ea1b4283 100644 (file)
@@ -1697,14 +1697,16 @@ fn check_access_permissions(
         );
         let mut error_reported = false;
         match kind {
-            Reservation(WriteKind::MutableBorrow(BorrowKind::Unique))
-            | Write(WriteKind::MutableBorrow(BorrowKind::Unique)) => {
-                if let Err(_place_err) = self.is_mutable(place, LocalMutationIsAllowed::Yes) {
-                    span_bug!(span, "&unique borrow for {:?} should not fail", place);
-                }
-            }
-            Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { .. }))
-            | Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => {
+            Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Unique))
+                | Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. }))
+                | Write(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Unique))
+                | Write(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. })) =>
+            {
+                let is_local_mutation_allowed = match borrow_kind {
+                    BorrowKind::Unique => LocalMutationIsAllowed::Yes,
+                    BorrowKind::Mut { .. } => is_local_mutation_allowed,
+                    BorrowKind::Shared => unreachable!(),
+                };
                 match self.is_mutable(place, is_local_mutation_allowed) {
                     Ok(root_place) => self.add_used_mut(root_place, flow_state),
                     Err(place_err) => {