about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorLaurențiu Nicola <lnicola@users.noreply.github.com>2024-12-04 03:44:01 +0000
committerGitHub <noreply@github.com>2024-12-04 03:44:01 +0000
commit01870ba9d7da99e7e4e6bedc7a67e5dc7d811bd5 (patch)
tree0ee8ece6b63b6d48790416186d9ee19d0c479f76 /src
parentfef7ca07bfd5a75da9716a861707fa8abe95fa5f (diff)
parent0d328a81ec0543ffbe63906f0e0b88bb2179ecc2 (diff)
downloadrust-01870ba9d7da99e7e4e6bedc7a67e5dc7d811bd5.tar.gz
rust-01870ba9d7da99e7e4e6bedc7a67e5dc7d811bd5.zip
Merge pull request #18606 from ChayimFriedman2/improve-soundness-just-a-bit
minor: Improve soundness a bit by making `TaggedArcPtr::try_as_arc_owned()` unsafe
Diffstat (limited to 'src')
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol.rs30
1 files changed, 17 insertions, 13 deletions
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs
index ef76192ba83..200b14027f8 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs
@@ -77,8 +77,12 @@ impl TaggedArcPtr {
     }
 
     /// Retrieves the tag.
+    ///
+    /// # Safety
+    ///
+    /// You can only drop the `Arc` if the instance is dropped.
     #[inline]
-    pub(crate) fn try_as_arc_owned(self) -> Option<ManuallyDrop<Arc<Box<str>>>> {
+    pub(crate) unsafe fn try_as_arc_owned(self) -> Option<ManuallyDrop<Arc<Box<str>>>> {
         // Unpack the tag from the alignment niche
         let tag = Strict::addr(self.packed.as_ptr()) & Self::BOOL_BITS;
         if tag != 0 {
@@ -245,16 +249,14 @@ impl Symbol {
             }
         }
 
-        ManuallyDrop::into_inner(
-            match shard.raw_entry_mut().from_key_hashed_nocheck::<str>(hash, arc.as_ref()) {
-                RawEntryMut::Occupied(occ) => occ.remove_entry(),
-                RawEntryMut::Vacant(_) => unreachable!(),
-            }
-            .0
-             .0
-            .try_as_arc_owned()
-            .unwrap(),
-        );
+        let ptr = match shard.raw_entry_mut().from_key_hashed_nocheck::<str>(hash, arc.as_ref()) {
+            RawEntryMut::Occupied(occ) => occ.remove_entry(),
+            RawEntryMut::Vacant(_) => unreachable!(),
+        }
+        .0
+         .0;
+        // SAFETY: We're dropping, we have ownership.
+        ManuallyDrop::into_inner(unsafe { ptr.try_as_arc_owned().unwrap() });
         debug_assert_eq!(Arc::count(arc), 1);
 
         // Shrink the backing storage if the shard is less than 50% occupied.
@@ -267,7 +269,8 @@ impl Symbol {
 impl Drop for Symbol {
     #[inline]
     fn drop(&mut self) {
-        let Some(arc) = self.repr.try_as_arc_owned() else {
+        // SAFETY: We're dropping, we have ownership.
+        let Some(arc) = (unsafe { self.repr.try_as_arc_owned() }) else {
             return;
         };
         // When the last `Ref` is dropped, remove the object from the global map.
@@ -288,7 +291,8 @@ impl Clone for Symbol {
 }
 
 fn increase_arc_refcount(repr: TaggedArcPtr) -> TaggedArcPtr {
-    let Some(arc) = repr.try_as_arc_owned() else {
+    // SAFETY: We're not dropping the `Arc`.
+    let Some(arc) = (unsafe { repr.try_as_arc_owned() }) else {
         return repr;
     };
     // increase the ref count