]> git.lizzy.rs Git - rust.git/commitdiff
Rearrange and document the new implementation
authorBen Kimock <kimockb@gmail.com>
Tue, 12 Jul 2022 00:54:31 +0000 (20:54 -0400)
committerBen Kimock <kimockb@gmail.com>
Wed, 13 Jul 2022 01:03:54 +0000 (21:03 -0400)
stacked_borrow now has an item module, and its own FrameExtra. These
serve to protect the implementation of Item (which is a bunch of
bit-packing tricks) from the primary logic of Stacked Borrows, and the
FrameExtra we have separates Stacked Borrows more cleanly from the
interpreter itself.

The new strategy for checking protectors also makes some subtle
performance tradeoffs, so they are now documented in Stack::item_popped
because that function primarily benefits from them, and it also touches
every aspect of them.

Also separating the actual CallId that is protecting a Tag from the Tag
makes it inconvienent to reproduce exactly the same protector errors, so
this also takes the opportunity to use some slightly cleaner English in
those errors. We need to make some change, might as well make it good.

18 files changed:
src/lib.rs
src/machine.rs
src/stacked_borrows.rs
src/stacked_borrows/item.rs [new file with mode: 0644]
src/stacked_borrows/stack.rs
tests/compiletest.rs
tests/fail/stacked_borrows/aliasing_mut1.stderr
tests/fail/stacked_borrows/aliasing_mut2.stderr
tests/fail/stacked_borrows/aliasing_mut4.stderr
tests/fail/stacked_borrows/deallocate_against_barrier1.rs
tests/fail/stacked_borrows/deallocate_against_barrier1.stderr
tests/fail/stacked_borrows/deallocate_against_barrier2.rs
tests/fail/stacked_borrows/deallocate_against_barrier2.stderr
tests/fail/stacked_borrows/illegal_write6.stderr
tests/fail/stacked_borrows/invalidate_against_barrier1.stderr
tests/fail/stacked_borrows/invalidate_against_barrier2.stderr
tests/fail/stacked_borrows/newtype_retagging.rs
tests/fail/stacked_borrows/newtype_retagging.stderr

index f3e6e0eef70a3481771acb84f570b700073fed40..b3d408a6dc07244945073a84014a923dd2d350e4 100644 (file)
@@ -90,8 +90,8 @@
 pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
 pub use crate::range_map::RangeMap;
 pub use crate::stacked_borrows::{
-    stack::Stack, CallId, EvalContextExt as StackedBorEvalContextExt, Item, Permission, SbTag,
-    SbTagExtra, Stacks,
+    CallId, EvalContextExt as StackedBorEvalContextExt, Item, Permission, SbTag, SbTagExtra, Stack,
+    Stacks,
 };
 pub use crate::sync::{CondvarId, EvalContextExt as SyncEvalContextExt, MutexId, RwLockId};
 pub use crate::thread::{
index 122bee2970e24e8cfa1920620ce0c69e99a60917..e31d7ba0105d611e5ff38d599a06d8cd8a5dfa86 100644 (file)
@@ -5,7 +5,6 @@
 use std::cell::RefCell;
 use std::collections::HashSet;
 use std::fmt;
-use std::num::NonZeroU64;
 use std::time::Instant;
 
 use rand::rngs::StdRng;
@@ -43,7 +42,7 @@
 /// Extra data stored with each stack frame
 pub struct FrameData<'tcx> {
     /// Extra data for Stacked Borrows.
-    pub call_id: stacked_borrows::CallId,
+    pub stacked_borrows: Option<stacked_borrows::FrameExtra>,
 
     /// If this is Some(), then this is a special "catch unwind" frame (the frame of `try_fn`
     /// called by `try`). When this frame is popped during unwinding a panic,
@@ -54,18 +53,15 @@ pub struct FrameData<'tcx> {
     /// for the start of this frame. When we finish executing this frame,
     /// we use this to register a completed event with `measureme`.
     pub timing: Option<measureme::DetachedTiming>,
-
-    pub protected_tags: Vec<SbTag>,
 }
 
 impl<'tcx> std::fmt::Debug for FrameData<'tcx> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         // Omitting `timing`, it does not support `Debug`.
-        let FrameData { call_id, catch_unwind, timing: _, protected_tags } = self;
+        let FrameData { stacked_borrows, catch_unwind, timing: _ } = self;
         f.debug_struct("FrameData")
-            .field("call_id", call_id)
+            .field("stacked_borrows", stacked_borrows)
             .field("catch_unwind", catch_unwind)
-            .field("protected_tags", protected_tags)
             .finish()
     }
 }
@@ -894,11 +890,12 @@ fn init_frame_extra(
         };
 
         let stacked_borrows = ecx.machine.stacked_borrows.as_ref();
-        let call_id = stacked_borrows.map_or(NonZeroU64::new(1).unwrap(), |stacked_borrows| {
-            stacked_borrows.borrow_mut().new_call()
-        });
 
-        let extra = FrameData { call_id, catch_unwind: None, timing, protected_tags: Vec::new() };
+        let extra = FrameData {
+            stacked_borrows: stacked_borrows.map(|sb| sb.borrow_mut().new_frame()),
+            catch_unwind: None,
+            timing,
+        };
         Ok(frame.with_extra(extra))
     }
 
index 8996754be367273f30df1ffd765028218ea741dc..4cae27ecd2192a67ba85e9fd8459865c5714f96e 100644 (file)
@@ -16,6 +16,7 @@
 };
 use rustc_span::DUMMY_SP;
 use rustc_target::abi::Size;
+use smallvec::SmallVec;
 use std::collections::HashSet;
 
 use crate::*;
 pub mod diagnostics;
 use diagnostics::{AllocHistory, TagHistory};
 
-pub mod stack;
-use stack::Stack;
+mod item;
+pub use item::{Item, Permission};
+mod stack;
+pub use stack::Stack;
 
 pub type CallId = NonZeroU64;
 
@@ -78,113 +81,21 @@ fn and_then<T>(self, f: impl FnOnce(SbTag) -> Option<T>) -> Option<T> {
     }
 }
 
-/// Indicates which permission is granted (by this item to some pointers)
-#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
-pub enum Permission {
-    /// Grants unique mutable access.
-    Unique,
-    /// Grants shared mutable access.
-    SharedReadWrite,
-    /// Grants shared read-only access.
-    SharedReadOnly,
-    /// Grants no access, but separates two groups of SharedReadWrite so they are not
-    /// all considered mutually compatible.
-    Disabled,
-}
-
-impl Permission {
-    const UNIQUE: u64 = 0;
-    const SHARED_READ_WRITE: u64 = 1;
-    const SHARED_READ_ONLY: u64 = 2;
-    const DISABLED: u64 = 3;
-
-    fn to_bits(self) -> u64 {
-        match self {
-            Permission::Unique => Self::UNIQUE,
-            Permission::SharedReadWrite => Self::SHARED_READ_WRITE,
-            Permission::SharedReadOnly => Self::SHARED_READ_ONLY,
-            Permission::Disabled => Self::DISABLED,
-        }
-    }
-
-    fn from_bits(perm: u64) -> Self {
-        match perm {
-            Self::UNIQUE => Permission::Unique,
-            Self::SHARED_READ_WRITE => Permission::SharedReadWrite,
-            Self::SHARED_READ_ONLY => Permission::SharedReadOnly,
-            Self::DISABLED => Permission::Disabled,
-            _ => unreachable!(),
-        }
-    }
-}
-
-mod item {
-    use super::{Permission, SbTag};
-    use std::fmt;
-    use std::num::NonZeroU64;
-
-    /// An item in the per-location borrow stack.
-    #[derive(Copy, Clone, Hash, PartialEq, Eq)]
-    pub struct Item(u64);
-
-    // An Item contains 3 bitfields:
-    // * Bits 0-61 store an SbTag
-    // * Bits 61-63 store a Permission
-    // * Bit 64 stores a flag which indicates if we have a protector
-    const TAG_MASK: u64 = u64::MAX >> 3;
-    const PERM_MASK: u64 = 0x3 << 61;
-    const PROTECTED_MASK: u64 = 0x1 << 63;
-
-    const PERM_SHIFT: u64 = 61;
-    const PROTECTED_SHIFT: u64 = 63;
-
-    impl Item {
-        pub fn new(tag: SbTag, perm: Permission, protected: bool) -> Self {
-            assert!(tag.0.get() <= TAG_MASK);
-            let packed_tag = tag.0.get();
-            let packed_perm = perm.to_bits() << PERM_SHIFT;
-            let packed_protected = (protected as u64) << PROTECTED_SHIFT;
-
-            let new = Self(packed_tag | packed_perm | packed_protected);
-
-            debug_assert!(new.tag() == tag);
-            debug_assert!(new.perm() == perm);
-            debug_assert!(new.protected() == protected);
-
-            new
-        }
-
-        /// The pointers the permission is granted to.
-        pub fn tag(self) -> SbTag {
-            SbTag(NonZeroU64::new(self.0 & TAG_MASK).unwrap())
-        }
-
-        /// The permission this item grants.
-        pub fn perm(self) -> Permission {
-            Permission::from_bits((self.0 & PERM_MASK) >> PERM_SHIFT)
-        }
-
-        /// Whether or not there is a protector for this tag
-        pub fn protected(self) -> bool {
-            self.0 & PROTECTED_MASK > 0
-        }
-
-        /// Set the Permission stored in this Item to Permission::Disabled
-        pub fn set_disabled(&mut self) {
-            // Clear the current set permission
-            self.0 &= !PERM_MASK;
-            // Write Permission::Disabled to the Permission bits
-            self.0 |= Permission::Disabled.to_bits() << PERM_SHIFT;
-        }
-    }
-
-    impl fmt::Debug for Item {
-        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-            write!(f, "[{:?} for {:?}]", self.perm(), self.tag())
-        }
-    }
+#[derive(Debug)]
+pub struct FrameExtra {
+    /// The ID of the call this frame corresponds to.
+    call_id: CallId,
+
+    /// If this frame is protecting any tags, they are listed here. We use this list to do
+    /// incremental updates of the global list of protected tags stored in the
+    /// `stacked_borrows::GlobalState` upon function return, and if we attempt to pop a protected
+    /// tag, to identify which call is responsible for protecting the tag.
+    /// See `Stack::item_popped` for more explanation.
+    ///
+    /// This will contain one tag per reference passed to the function, so
+    /// a size of 2 is enough for the vast majority of functions.
+    protected_tags: SmallVec<[SbTag; 2]>,
 }
-pub use item::Item;
 
 /// Extra per-allocation state.
 #[derive(Clone, Debug)]
@@ -208,7 +119,11 @@ pub struct GlobalStateInner {
     base_ptr_tags: FxHashMap<AllocId, SbTag>,
     /// Next unused call ID (for protectors).
     next_call_id: CallId,
-    /// All tags currently protected
+    /// All currently protected tags.
+    /// An item is protected if its tag is in this set, *and* it has the "protected" bit set.
+    /// We add tags to this when they are created with a protector in `reborrow`, and
+    /// we remove tags from this when the call which is protecting them returns, in
+    /// `GlobalStateInner::end_call`. See `Stack::item_popped` for more details.
     protected_tags: FxHashSet<SbTag>,
     /// The pointer ids to trace
     tracked_pointer_tags: HashSet<SbTag>,
@@ -287,18 +202,23 @@ fn new_ptr(&mut self) -> SbTag {
         id
     }
 
-    pub fn new_call(&mut self) -> CallId {
-        let id = self.next_call_id;
-        trace!("new_call: Assigning ID {}", id);
-        if self.tracked_call_ids.contains(&id) {
-            register_diagnostic(NonHaltingDiagnostic::CreatedCallId(id));
+    pub fn new_frame(&mut self) -> FrameExtra {
+        let call_id = self.next_call_id;
+        trace!("new_frame: Assigning call ID {}", call_id);
+        if self.tracked_call_ids.contains(&call_id) {
+            register_diagnostic(NonHaltingDiagnostic::CreatedCallId(call_id));
         }
-        self.next_call_id = NonZeroU64::new(id.get() + 1).unwrap();
-        id
+        self.next_call_id = NonZeroU64::new(call_id.get() + 1).unwrap();
+        FrameExtra { call_id, protected_tags: SmallVec::new() }
     }
 
     pub fn end_call(&mut self, frame: &machine::FrameData<'_>) {
-        for tag in &frame.protected_tags {
+        for tag in &frame
+            .stacked_borrows
+            .as_ref()
+            .expect("we should have Stacked Borrows data")
+            .protected_tags
+        {
             self.protected_tags.remove(tag);
         }
     }
@@ -407,17 +327,40 @@ fn item_popped(
             return Ok(());
         }
 
+        // We store tags twice, once in global.protected_tags and once in each call frame.
+        // We do this because consulting a single global set in this function is faster
+        // than attempting to search all call frames in the program for the `FrameExtra`
+        // (if any) which is protecting the popped tag.
+        //
+        // This duplication trades off making `end_call` slower to make this function faster. This
+        // trade-off is profitable in practice for a combination of two reasons.
+        // 1. A single protected tag can (and does in some programs) protect thousands of `Item`s.
+        //    Therefore, adding overhead to in function call/return is profitable even if it only
+        //    saves a little work in this function.
+        // 2. Most frames protect only one or two tags. So this duplicative global turns a search
+        //    which ends up about linear in the number of protected tags in the program into a
+        //    constant time check (and a slow linear, because the tags in the frames aren't contiguous).
         if global.protected_tags.contains(&item.tag()) {
+            // This path is cold because it is fatal to the program. So here it is fine to do the
+            // more expensive search to figure out which call is responsible for protecting this
+            // tag.
             let call_id = threads
                 .all_stacks()
                 .flatten()
-                .find(|t| t.extra.protected_tags.contains(&item.tag()))
-                .map(|frame| frame.extra.call_id)
+                .map(|frame| {
+                    frame
+                        .extra
+                        .stacked_borrows
+                        .as_ref()
+                        .expect("we should have Stacked Borrows data")
+                })
+                .find(|frame| frame.protected_tags.contains(&item.tag()))
+                .map(|frame| frame.call_id)
                 .unwrap(); // FIXME: Surely we should find something, but a panic seems wrong here?
             if let Some((tag, _alloc_range, _offset, _access)) = provoking_access {
                 Err(err_sb_ub(
                     format!(
-                        "not granting access to tag {:?} because incompatible item is protected: {:?} (call {:?})",
+                        "not granting access to tag {:?} because incompatible item {:?} is protected by call {:?}",
                         tag, item, call_id
                     ),
                     None,
@@ -426,7 +369,7 @@ fn item_popped(
             } else {
                 Err(err_sb_ub(
                     format!(
-                        "deallocating while item is protected: {:?} (call {:?})",
+                        "deallocating while item {:?} is protected by call {:?}",
                         item, call_id
                     ),
                     None,
@@ -904,7 +847,7 @@ fn reborrow(
         );
 
         if protect {
-            this.frame_mut().extra.protected_tags.push(new_tag);
+            this.frame_mut().extra.stacked_borrows.as_mut().unwrap().protected_tags.push(new_tag);
             this.machine.stacked_borrows.as_mut().unwrap().get_mut().protected_tags.insert(new_tag);
         }
         // FIXME: can't hold the current span handle across the borrows of self above
diff --git a/src/stacked_borrows/item.rs b/src/stacked_borrows/item.rs
new file mode 100644 (file)
index 0000000..ad1b9b0
--- /dev/null
@@ -0,0 +1,104 @@
+use crate::stacked_borrows::SbTag;
+use std::fmt;
+use std::num::NonZeroU64;
+
+/// An item in the per-location borrow stack.
+#[derive(Copy, Clone, Hash, PartialEq, Eq)]
+pub struct Item(u64);
+
+// An Item contains 3 bitfields:
+// * Bits 0-61 store an SbTag
+// * Bits 61-63 store a Permission
+// * Bit 64 stores a flag which indicates if we have a protector
+const TAG_MASK: u64 = u64::MAX >> 3;
+const PERM_MASK: u64 = 0x3 << 61;
+const PROTECTED_MASK: u64 = 0x1 << 63;
+
+const PERM_SHIFT: u64 = 61;
+const PROTECTED_SHIFT: u64 = 63;
+
+impl Item {
+    pub fn new(tag: SbTag, perm: Permission, protected: bool) -> Self {
+        assert!(tag.0.get() <= TAG_MASK);
+        let packed_tag = tag.0.get();
+        let packed_perm = perm.to_bits() << PERM_SHIFT;
+        let packed_protected = (protected as u64) << PROTECTED_SHIFT;
+
+        let new = Self(packed_tag | packed_perm | packed_protected);
+
+        debug_assert!(new.tag() == tag);
+        debug_assert!(new.perm() == perm);
+        debug_assert!(new.protected() == protected);
+
+        new
+    }
+
+    /// The pointers the permission is granted to.
+    pub fn tag(self) -> SbTag {
+        SbTag(NonZeroU64::new(self.0 & TAG_MASK).unwrap())
+    }
+
+    /// The permission this item grants.
+    pub fn perm(self) -> Permission {
+        Permission::from_bits((self.0 & PERM_MASK) >> PERM_SHIFT)
+    }
+
+    /// Whether or not there is a protector for this tag
+    pub fn protected(self) -> bool {
+        self.0 & PROTECTED_MASK > 0
+    }
+
+    /// Set the Permission stored in this Item
+    pub fn set_permission(&mut self, perm: Permission) {
+        // Clear the current set permission
+        self.0 &= !PERM_MASK;
+        // Write Permission::Disabled to the Permission bits
+        self.0 |= perm.to_bits() << PERM_SHIFT;
+    }
+}
+
+impl fmt::Debug for Item {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[{:?} for {:?}]", self.perm(), self.tag())
+    }
+}
+
+/// Indicates which permission is granted (by this item to some pointers)
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub enum Permission {
+    /// Grants unique mutable access.
+    Unique,
+    /// Grants shared mutable access.
+    SharedReadWrite,
+    /// Grants shared read-only access.
+    SharedReadOnly,
+    /// Grants no access, but separates two groups of SharedReadWrite so they are not
+    /// all considered mutually compatible.
+    Disabled,
+}
+
+impl Permission {
+    const UNIQUE: u64 = 0;
+    const SHARED_READ_WRITE: u64 = 1;
+    const SHARED_READ_ONLY: u64 = 2;
+    const DISABLED: u64 = 3;
+
+    fn to_bits(self) -> u64 {
+        match self {
+            Permission::Unique => Self::UNIQUE,
+            Permission::SharedReadWrite => Self::SHARED_READ_WRITE,
+            Permission::SharedReadOnly => Self::SHARED_READ_ONLY,
+            Permission::Disabled => Self::DISABLED,
+        }
+    }
+
+    fn from_bits(perm: u64) -> Self {
+        match perm {
+            Self::UNIQUE => Permission::Unique,
+            Self::SHARED_READ_WRITE => Permission::SharedReadWrite,
+            Self::SHARED_READ_ONLY => Permission::SharedReadOnly,
+            Self::DISABLED => Permission::Disabled,
+            _ => unreachable!(),
+        }
+    }
+}
index 0863f8023277580357406da3f378f8c6c5e0d93a..1b05471618a52bc4f2507ee9c0f40e88b513a696 100644 (file)
@@ -303,10 +303,11 @@ pub fn disable_uniques_starting_at<V: FnMut(Item) -> crate::InterpResult<'tcx>>(
                 if item.perm() == Permission::Unique {
                     log::trace!("access: disabling item {:?}", item);
                     visitor(*item)?;
-                    item.set_disabled();
-                    for t in &mut self.cache.items {
-                        if t.tag() == item.tag() {
-                            t.set_disabled();
+                    item.set_permission(Permission::Disabled);
+                    // Also update all copies of this item in the cache.
+                    for it in &mut self.cache.items {
+                        if it.tag() == item.tag() {
+                            it.set_permission(Permission::Disabled);
                         }
                     }
                 }
index 008fc7806457fd45d36bfc38b1d0b08bd27572a9..c568d1c50434c30fdb97c01ac4db1e35ca006aa4 100644 (file)
@@ -97,7 +97,7 @@ macro_rules! regexes {
     // erase specific alignments
     "alignment [0-9]+"               => "alignment ALIGN",
     // erase thread caller ids
-    r"\(call [0-9]+\)"              => "(call ID)",
+    r"call [0-9]+"                  => "call ID",
     // erase platform module paths
     "sys::[a-z]+::"                  => "sys::PLATFORM::",
     // Windows file paths
index 82c504cd836f9034b9161ac1d32624916a2e2c6b..b821d1e6edb42ef5177a3167c28919dd5b680c1c 100644 (file)
@@ -1,8 +1,8 @@
-error: Undefined Behavior: not granting access to tag <TAG> because incompatible item is protected: [Unique for <TAG>] (call ID)
+error: Undefined Behavior: not granting access to tag <TAG> because incompatible item [Unique for <TAG>] is protected by call ID
   --> $DIR/aliasing_mut1.rs:LL:CC
    |
 LL | pub fn safe(_x: &mut i32, _y: &mut i32) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag <TAG> because incompatible item is protected: [Unique for <TAG>] (call ID)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag <TAG> because incompatible item [Unique for <TAG>] is protected by call ID
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
index 2973e22b2b793babf8e27dc7c48d0c8eb3f10686..594b578fc09a7235c737be067bee54f51711bc0e 100644 (file)
@@ -1,8 +1,8 @@
-error: Undefined Behavior: not granting access to tag <TAG> because incompatible item is protected: [SharedReadOnly for <TAG>] (call ID)
+error: Undefined Behavior: not granting access to tag <TAG> because incompatible item [SharedReadOnly for <TAG>] is protected by call ID
   --> $DIR/aliasing_mut2.rs:LL:CC
    |
 LL | pub fn safe(_x: &i32, _y: &mut i32) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag <TAG> because incompatible item is protected: [SharedReadOnly for <TAG>] (call ID)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag <TAG> because incompatible item [SharedReadOnly for <TAG>] is protected by call ID
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
index b9a7b810dbd8504ee9072780a79afc95b4217c42..0c7d85ae5756c1c63fde4b042fec3db640080404 100644 (file)
@@ -1,8 +1,8 @@
-error: Undefined Behavior: not granting access to tag <TAG> because incompatible item is protected: [SharedReadOnly for <TAG>] (call ID)
+error: Undefined Behavior: not granting access to tag <TAG> because incompatible item [SharedReadOnly for <TAG>] is protected by call ID
   --> $DIR/aliasing_mut4.rs:LL:CC
    |
 LL | pub fn safe(_x: &i32, _y: &mut Cell<i32>) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag <TAG> because incompatible item is protected: [SharedReadOnly for <TAG>] (call ID)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag <TAG> because incompatible item [SharedReadOnly for <TAG>] is protected by call ID
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
index 0798f863ce110e6b8234e9c6dfd58947e76bc3ab..20e026df7b9b226146698319ebf4c79b944b0ff7 100644 (file)
@@ -1,4 +1,4 @@
-//@error-pattern: deallocating while item is protected
+//@error-pattern: deallocating while item
 
 fn inner(x: &mut i32, f: fn(&mut i32)) {
     // `f` may mutate, but it may not deallocate!
index 124731e85bd59ccf017e845b0ebed7a9db222982..689c0a5deae68c9755fc0d5204e80d5ee37f977e 100644 (file)
@@ -1,8 +1,8 @@
-error: Undefined Behavior: deallocating while item is protected: [Unique for <TAG>] (call ID)
+error: Undefined Behavior: deallocating while item [Unique for <TAG>] is protected by call ID
   --> RUSTLIB/alloc/src/alloc.rs:LL:CC
    |
 LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating while item is protected: [Unique for <TAG>] (call ID)
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating while item [Unique for <TAG>] is protected by call ID
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
index 23c54c8d898837ea2470e96bae15a25f9c9e1274..9cb2d52bf2e9af989f526599a1043b3c311fd8c6 100644 (file)
@@ -1,4 +1,4 @@
-//@error-pattern: deallocating while item is protected
+//@error-pattern: deallocating while item
 use std::marker::PhantomPinned;
 
 pub struct NotUnpin(i32, PhantomPinned);
index e09158dfb40836aac3890669ce130b6b56aa742e..a1a7ce0c6bb681a662c3de52f73ea76c1a53899c 100644 (file)
@@ -1,8 +1,8 @@
-error: Undefined Behavior: deallocating while item is protected: [SharedReadWrite for <TAG>] (call ID)
+error: Undefined Behavior: deallocating while item [SharedReadWrite for <TAG>] is protected by call ID
   --> RUSTLIB/alloc/src/alloc.rs:LL:CC
    |
 LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating while item is protected: [SharedReadWrite for <TAG>] (call ID)
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating while item [SharedReadWrite for <TAG>] is protected by call ID
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
index cab6f392d1b116684a28217dbdfa5d2c449da38f..42f7b3f8b54bfbb9b192695eb66e9e87d144b1f5 100644 (file)
@@ -1,8 +1,8 @@
-error: Undefined Behavior: not granting access to tag <TAG> because incompatible item is protected: [Unique for <TAG>] (call ID)
+error: Undefined Behavior: not granting access to tag <TAG> because incompatible item [Unique for <TAG>] is protected by call ID
   --> $DIR/illegal_write6.rs:LL:CC
    |
 LL |     unsafe { *y = 2 };
-   |              ^^^^^^ not granting access to tag <TAG> because incompatible item is protected: [Unique for <TAG>] (call ID)
+   |              ^^^^^^ not granting access to tag <TAG> because incompatible item [Unique for <TAG>] is protected by call ID
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
index 40d5147cadff53a3802a7559a037401e80705c51..4a1b14e460941dccd2414dc8aaf6efd5519a3d7a 100644 (file)
@@ -1,8 +1,8 @@
-error: Undefined Behavior: not granting access to tag <TAG> because incompatible item is protected: [Unique for <TAG>] (call ID)
+error: Undefined Behavior: not granting access to tag <TAG> because incompatible item [Unique for <TAG>] is protected by call ID
   --> $DIR/invalidate_against_barrier1.rs:LL:CC
    |
 LL |     let _val = unsafe { *x };
-   |                         ^^ not granting access to tag <TAG> because incompatible item is protected: [Unique for <TAG>] (call ID)
+   |                         ^^ not granting access to tag <TAG> because incompatible item [Unique for <TAG>] is protected by call ID
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
index 30148396cc5d15b8ce981ecce646e80d143903b3..c6f158316f51294cee00729f48ff85a0f938b198 100644 (file)
@@ -1,8 +1,8 @@
-error: Undefined Behavior: not granting access to tag <TAG> because incompatible item is protected: [SharedReadOnly for <TAG>] (call ID)
+error: Undefined Behavior: not granting access to tag <TAG> because incompatible item [SharedReadOnly for <TAG>] is protected by call ID
   --> $DIR/invalidate_against_barrier2.rs:LL:CC
    |
 LL |     unsafe { *x = 0 };
-   |              ^^^^^^ not granting access to tag <TAG> because incompatible item is protected: [SharedReadOnly for <TAG>] (call ID)
+   |              ^^^^^^ not granting access to tag <TAG> because incompatible item [SharedReadOnly for <TAG>] is protected by call ID
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
index 4786cd02d954f31e32d1239f9f874d9cc80c40c6..f9cceb761af3e6f2fcee46b164b028f32222bf3b 100644 (file)
@@ -1,5 +1,5 @@
 //@compile-flags: -Zmiri-retag-fields
-//@error-pattern: incompatible item is protected
+//@error-pattern: is protected by call
 struct Newtype<'a>(&'a mut i32);
 
 fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {
index 337a22967c7dd16a8e782a591da364fa768fe07a..d9aebecfda731bbaf883e0be56f47bb58ac7debf 100644 (file)
@@ -1,8 +1,8 @@
-error: Undefined Behavior: not granting access to tag <TAG> because incompatible item is protected: [Unique for <TAG>] (call ID)
+error: Undefined Behavior: not granting access to tag <TAG> because incompatible item [Unique for <TAG>] is protected by call ID
   --> RUSTLIB/alloc/src/boxed.rs:LL:CC
    |
 LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag <TAG> because incompatible item is protected: [Unique for <TAG>] (call ID)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag <TAG> because incompatible item [Unique for <TAG>] is protected by call ID
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information