Skip to main content

rune/runtime/
any_obj.rs

1use core::cell::Cell;
2use core::fmt;
3use core::mem::{replace, ManuallyDrop};
4use core::ptr::{self, addr_of, NonNull};
5
6use crate::alloc::clone::TryClone;
7use crate::alloc::{self, Box};
8use crate::{Any, Hash};
9
10use super::{
11    Access, AccessError, AnyObjVtable, AnyTypeInfo, BorrowMut, BorrowRef, FromValue, Handover, Mut,
12    RawAccessGuard, RawAnyGuard, Ref, RefVtable, RuntimeError, Shared, Snapshot, ToValue, TypeInfo,
13    Value,
14};
15
16/// A type-erased wrapper for a reference.
17pub struct AnyObj {
18    shared: NonNull<AnyObjData>,
19}
20
21impl AnyObj {
22    /// Construct a new typed object.
23    ///
24    /// # Safety
25    ///
26    /// Caller must ensure that the type is of the value `T`.
27    #[inline]
28    pub(super) const unsafe fn from_raw(shared: NonNull<AnyObjData>) -> Self {
29        Self { shared }
30    }
31
32    /// Construct an Any that wraps an owned object.
33    ///
34    /// # Examples
35    ///
36    /// ```
37    /// use rune::Value;
38    /// use rune::runtime::AnyObj;
39    /// use rune::alloc::String;
40    ///
41    /// let string = String::try_from("Hello World")?;
42    /// let string = AnyObj::new(string)?;
43    /// let string = Value::from(string);
44    ///
45    /// let string = string.into_shared::<String>()?;
46    /// assert_eq!(string.borrow_ref()?.as_str(), "Hello World");
47    /// # Ok::<_, rune::support::Error>(())
48    /// ```
49    #[inline]
50    pub fn new<T>(data: T) -> alloc::Result<Self>
51    where
52        T: Any,
53    {
54        let shared = AnyObjData {
55            access: Access::new(),
56            count: Cell::new(1),
57            vtable: AnyObjVtable::owned::<T>(),
58            data,
59        };
60
61        let shared = NonNull::from(Box::leak(Box::try_new(shared)?)).cast();
62        Ok(Self { shared })
63    }
64
65    /// Construct an Any that wraps a pointer.
66    ///
67    /// # Safety
68    ///
69    /// Caller must ensure that the returned `AnyObj` doesn't outlive the
70    /// reference it is wrapping.
71    #[inline]
72    pub(crate) unsafe fn from_ref<T>(data: *const T) -> alloc::Result<Self>
73    where
74        T: Any,
75    {
76        let shared = AnyObjData {
77            access: Access::new(),
78            count: Cell::new(1),
79            vtable: AnyObjVtable::from_ref::<T>(),
80            data: NonNull::new_unchecked(data.cast_mut()),
81        };
82
83        let shared = NonNull::from(Box::leak(Box::try_new(shared)?)).cast();
84        Ok(Self { shared })
85    }
86
87    /// Construct an Any that wraps a mutable pointer.
88    ///
89    /// # Safety
90    ///
91    /// Caller must ensure that the returned `AnyObj` doesn't outlive the
92    /// reference it is wrapping.
93    #[inline]
94    pub(crate) unsafe fn from_mut<T>(data: *mut T) -> alloc::Result<Self>
95    where
96        T: Any,
97    {
98        let shared = AnyObjData {
99            access: Access::new(),
100            count: Cell::new(1),
101            vtable: AnyObjVtable::from_mut::<T>(),
102            data: NonNull::new_unchecked(data),
103        };
104
105        let shared = NonNull::from(Box::leak(Box::try_new(shared)?)).cast();
106        Ok(Self { shared })
107    }
108
109    /// Test if this is the last reference to a value which it owns, which means
110    /// that dropping it drops the value it stores.
111    ///
112    /// A value which is only pointed at is never dropped through this, so
113    /// unlike an [`AnySequence`] it is not enough for it to be the last
114    /// reference.
115    ///
116    /// This is what permits the value to be taken apart rather than dropped in
117    /// place, see [`Value`]'s destructor.
118    ///
119    /// [`AnySequence`]: crate::runtime::AnySequence
120    ///
121    /// [`Value`]: crate::runtime::Value
122    #[inline]
123    pub(crate) fn is_last_owner(&self) -> bool {
124        // SAFETY: Since we have a reference to this object, we know that the
125        // shared data is live.
126        unsafe { vtable(self).is_owned() && self.shared.as_ref().count.get() == 1 }
127    }
128
129    /// Hand over the values which the stored value is made of.
130    ///
131    /// This is how a graph of values is taken apart without recursing into it:
132    /// which values are inside is only known to the type which is stored, so it
133    /// is asked through its vtable - see [`Dismantle`].
134    ///
135    /// Nothing is handed over unless dropping this handle is what drops the
136    /// value, since the values are only being taken out because the value they
137    /// are in is going away.
138    ///
139    /// [`Dismantle`]: crate::runtime::Dismantle
140    pub(crate) fn dismantle(&self, out: &mut Handover<'_>) {
141        if !self.is_last_owner() {
142            return;
143        }
144
145        let Some(dismantle) = vtable(self).dismantle else {
146            return;
147        };
148
149        // SAFETY: The vtable is the one for the type which is stored, and the
150        // access guard is what keeps anything else from looking at it while the
151        // values are handed over.
152        unsafe {
153            let Ok(_guard) = self.shared.as_ref().access.exclusive() else {
154                return;
155            };
156
157            dismantle(self.shared, out)
158        }
159    }
160
161    /// Coerce into a typed object.
162    pub(crate) fn into_shared<T>(self) -> Result<Shared<T>, AnyObjError>
163    where
164        T: Any,
165    {
166        let vtable = vtable(&self);
167
168        if !vtable.is::<T>() {
169            return Err(AnyObjError::new(AnyObjErrorKind::Cast(
170                T::ANY_TYPE_INFO,
171                vtable.type_info(),
172            )));
173        }
174
175        // SAFETY: We've typed checked for the appropriate type just above.
176        unsafe { Ok(self.unsafe_into_shared()) }
177    }
178
179    /// Coerce into a typed object.
180    ///
181    /// # Safety
182    ///
183    /// The caller must ensure that the type being convert into is correct.
184    #[inline]
185    pub(crate) unsafe fn unsafe_into_shared<T>(self) -> Shared<T>
186    where
187        T: Any,
188    {
189        let this = ManuallyDrop::new(self);
190        Shared::from_raw(this.shared.cast())
191    }
192
193    /// Downcast into an owned value of type `T`.
194    pub(crate) fn downcast<T>(self) -> Result<T, AnyObjError>
195    where
196        T: Any,
197    {
198        let vtable = vtable(&self);
199
200        if !vtable.is::<T>() {
201            return Err(AnyObjError::new(AnyObjErrorKind::Cast(
202                T::ANY_TYPE_INFO,
203                vtable.type_info(),
204            )));
205        }
206
207        if !vtable.is_owned() {
208            return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
209                vtable.type_info(),
210            )));
211        }
212
213        // SAFETY: We've checked for the appropriate type just above.
214        unsafe {
215            self.shared.as_ref().access.try_take()?;
216            let data = vtable.as_ptr::<T>(self.shared);
217            Ok(data.read())
218        }
219    }
220
221    /// Take the interior value and drop it if necessary.
222    pub(crate) fn drop(self) -> Result<(), AnyObjError> {
223        let vtable = vtable(&self);
224
225        if !vtable.is_owned() {
226            return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
227                vtable.type_info(),
228            )));
229        }
230
231        // SAFETY: We've checked for the appropriate type just above.
232        unsafe {
233            self.shared.as_ref().access.try_take()?;
234
235            if let Some(drop_value) = vtable.drop_value {
236                drop_value(self.shared);
237            }
238
239            Ok(())
240        }
241    }
242
243    /// Take the interior value and return a handle to the taken value.
244    pub fn take(self) -> Result<Self, AnyObjError> {
245        let vtable = vtable(&self);
246
247        // SAFETY: We've checked for the appropriate type just above.
248        unsafe {
249            self.shared.as_ref().access.try_take()?;
250            Ok((vtable.clone)(self.shared)?)
251        }
252    }
253
254    /// Downcast into an owned value of type [`Ref<T>`].
255    ///
256    /// # Errors
257    ///
258    /// This errors in case the underlying value is not owned, non-owned
259    /// references cannot be coerced into [`Ref<T>`].
260    pub(crate) fn into_ref<T>(self) -> Result<Ref<T>, AnyObjError>
261    where
262        T: Any,
263    {
264        let vtable = vtable(&self);
265
266        if !vtable.is::<T>() {
267            return Err(AnyObjError::new(AnyObjErrorKind::Cast(
268                T::ANY_TYPE_INFO,
269                vtable.type_info(),
270            )));
271        }
272
273        if !vtable.is_owned() {
274            return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
275                vtable.type_info(),
276            )));
277        }
278
279        // SAFETY: We've checked for the appropriate type just above.
280        unsafe {
281            self.shared.as_ref().access.try_shared()?;
282            let this = ManuallyDrop::new(self);
283            let data = vtable.as_ptr(this.shared);
284
285            let vtable = &RefVtable {
286                drop: |shared: NonNull<()>| {
287                    let shared = shared.cast::<AnyObjData>();
288                    shared.as_ref().access.release();
289                    AnyObjData::dec(shared)
290                },
291                // The reference keeps the value alive, so it can be handed
292                // back: releasing the access and handing the count over is what
293                // dropping does, minus the count being given up.
294                into_value: Some(|shared: NonNull<()>| {
295                    let shared = shared.cast::<AnyObjData>();
296                    shared.as_ref().access.release();
297                    Value::from(AnyObj::from_raw(shared))
298                }),
299            };
300
301            let guard = RawAnyGuard::new(this.shared.cast(), vtable);
302            Ok(Ref::new(data, guard))
303        }
304    }
305
306    /// Downcast into an owned value of type [`Mut<T>`].
307    ///
308    /// # Errors
309    ///
310    /// This errors in case the underlying value is not owned, non-owned
311    /// references cannot be coerced into [`Mut<T>`].
312    pub(crate) fn into_mut<T>(self) -> Result<Mut<T>, AnyObjError>
313    where
314        T: Any,
315    {
316        let vtable = vtable(&self);
317
318        if !vtable.is::<T>() {
319            return Err(AnyObjError::new(AnyObjErrorKind::Cast(
320                T::ANY_TYPE_INFO,
321                vtable.type_info(),
322            )));
323        }
324
325        if !vtable.is_owned() {
326            return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
327                vtable.type_info(),
328            )));
329        }
330
331        // SAFETY: We've checked for the appropriate type just above.
332        unsafe {
333            self.shared.as_ref().access.try_exclusive()?;
334            let this = ManuallyDrop::new(self);
335            let data = vtable.as_ptr(this.shared);
336
337            let vtable = &RefVtable {
338                drop: |shared: NonNull<()>| {
339                    let shared = shared.cast::<AnyObjData>();
340                    shared.as_ref().access.release();
341                    AnyObjData::dec(shared)
342                },
343                // The reference keeps the value alive, so it can be handed
344                // back: releasing the access and handing the count over is what
345                // dropping does, minus the count being given up.
346                into_value: Some(|shared: NonNull<()>| {
347                    let shared = shared.cast::<AnyObjData>();
348                    shared.as_ref().access.release();
349                    Value::from(AnyObj::from_raw(shared))
350                }),
351            };
352
353            let guard = RawAnyGuard::new(this.shared.cast(), vtable);
354            Ok(Mut::new(data, guard))
355        }
356    }
357
358    /// Get a reference to the interior value while checking for shared access.
359    ///
360    /// This prevents other exclusive accesses from being performed while the
361    /// guard returned from this function is live.
362    pub fn borrow_ref<T>(&self) -> Result<BorrowRef<'_, T>, AnyObjError>
363    where
364        T: Any,
365    {
366        let vtable = vtable(self);
367
368        if !vtable.is::<T>() {
369            return Err(AnyObjError::new(AnyObjErrorKind::Cast(
370                T::ANY_TYPE_INFO,
371                vtable.type_info(),
372            )));
373        }
374
375        // SAFETY: We've checked for the appropriate type just above.
376        unsafe {
377            let guard = self.shared.as_ref().access.shared()?;
378            let data = vtable.as_ptr(self.shared);
379            Ok(BorrowRef::new(data, guard.into_raw()))
380        }
381    }
382
383    /// Try to borrow a reference to the interior value while checking for
384    /// shared access.
385    ///
386    /// Returns `None` if the interior type is not `T`.
387    ///
388    /// This prevents other exclusive accesses from being performed while the
389    /// guard returned from this function is alive.
390    pub fn try_borrow_ref<T>(&self) -> Result<Option<BorrowRef<'_, T>>, AccessError>
391    where
392        T: Any,
393    {
394        let vtable = vtable(self);
395
396        if !vtable.is::<T>() {
397            return Ok(None);
398        }
399
400        // SAFETY: We've checked for the appropriate type just above.
401        unsafe {
402            let guard = self.shared.as_ref().access.shared()?;
403            let data = vtable.as_ptr(self.shared);
404            Ok(Some(BorrowRef::new(data, guard.into_raw())))
405        }
406    }
407
408    /// Try to borrow a reference to the interior value while checking for
409    /// exclusive access.
410    ///
411    /// Returns `None` if the interior type is not `T`.
412    ///
413    /// This prevents other exclusive accesses from being performed while the
414    /// guard returned from this function is alive.
415    pub fn try_borrow_mut<T>(&self) -> Result<Option<BorrowMut<'_, T>>, AccessError>
416    where
417        T: Any,
418    {
419        let vtable = vtable(self);
420
421        if !vtable.is::<T>() {
422            return Ok(None);
423        }
424
425        // SAFETY: We've checked for the appropriate type just above.
426        unsafe {
427            let guard = self.shared.as_ref().access.exclusive()?;
428            let data = vtable.as_ptr(self.shared);
429            Ok(Some(BorrowMut::new(data, guard.into_raw())))
430        }
431    }
432
433    /// Returns some mutable reference to the boxed value if it is of type `T`.
434    pub fn borrow_mut<T>(&self) -> Result<BorrowMut<'_, T>, AnyObjError>
435    where
436        T: Any,
437    {
438        let vtable = vtable(self);
439
440        if !vtable.is::<T>() || !vtable.is_mutable() {
441            return Err(AnyObjError::new(AnyObjErrorKind::Cast(
442                T::ANY_TYPE_INFO,
443                vtable.type_info(),
444            )));
445        }
446
447        // SAFETY: We've checked for the appropriate type just above.
448        unsafe {
449            let guard = self.shared.as_ref().access.exclusive()?;
450            let data = vtable.as_ptr(self.shared);
451            Ok(BorrowMut::new(data, guard.into_raw()))
452        }
453    }
454
455    /// Get a reference to the interior value while checking for shared access.
456    ///
457    /// This prevents other exclusive accesses from being performed while the
458    /// guard returned from this function is live.
459    pub(crate) fn borrow_ref_ptr<T>(self) -> Result<(NonNull<T>, RawAnyObjGuard), AnyObjError>
460    where
461        T: Any,
462    {
463        let vtable = vtable(&self);
464
465        if !vtable.is::<T>() {
466            return Err(AnyObjError::new(AnyObjErrorKind::Cast(
467                T::ANY_TYPE_INFO,
468                vtable.type_info(),
469            )));
470        }
471
472        // SAFETY: We've checked for the appropriate type just above.
473        unsafe {
474            let guard = self.shared.as_ref().access.shared()?.into_raw();
475            let this = ManuallyDrop::new(self);
476
477            let data = vtable.as_ptr(this.shared);
478
479            let guard = RawAnyObjGuard {
480                guard,
481                dec_shared: AnyObjDecShared {
482                    shared: this.shared,
483                },
484            };
485
486            Ok((data, guard))
487        }
488    }
489
490    /// Returns some mutable reference to the boxed value if it is of type `T`.
491    pub(crate) fn borrow_mut_ptr<T>(self) -> Result<(NonNull<T>, RawAnyObjGuard), AnyObjError>
492    where
493        T: Any,
494    {
495        let vtable = vtable(&self);
496
497        if !vtable.is::<T>() || !vtable.is_mutable() {
498            return Err(AnyObjError::new(AnyObjErrorKind::Cast(
499                T::ANY_TYPE_INFO,
500                vtable.type_info(),
501            )));
502        }
503
504        // SAFETY: We've checked for the appropriate type just above.
505        unsafe {
506            let guard = self.shared.as_ref().access.exclusive()?.into_raw();
507            let this = ManuallyDrop::new(self);
508
509            let data = vtable.as_ptr(this.shared);
510
511            let guard = RawAnyObjGuard {
512                guard,
513                dec_shared: AnyObjDecShared {
514                    shared: this.shared,
515                },
516            };
517
518            Ok((data, guard))
519        }
520    }
521
522    /// Deconstruct the shared value into a guard and shared box.
523    ///
524    /// # Safety
525    ///
526    /// The content of the shared value will be forcibly destructed once the
527    /// returned guard is dropped, unchecked use of the shared value after this
528    /// point will lead to undefined behavior.
529    pub(crate) unsafe fn into_drop_guard(self) -> (Self, AnyObjDrop) {
530        // Increment the reference count by one to account for the guard holding
531        // onto it.
532        AnyObjData::inc(self.shared);
533
534        let guard = AnyObjDrop {
535            shared: self.shared,
536        };
537
538        (self, guard)
539    }
540
541    /// Test if the value is sharable.
542    pub(crate) fn is_readable(&self) -> bool {
543        // Safety: Since we have a reference to this shared, we know that the
544        // inner is available.
545        unsafe { self.shared.as_ref().access.is_shared() }
546    }
547
548    /// Test if the value is exclusively accessible.
549    pub(crate) fn is_writable(&self) -> bool {
550        unsafe {
551            let shared = self.shared.as_ref();
552            shared.vtable.is_mutable() && shared.access.is_exclusive()
553        }
554    }
555
556    /// Get access snapshot of shared value.
557    pub(crate) fn snapshot(&self) -> Snapshot {
558        unsafe { self.shared.as_ref().access.snapshot() }
559    }
560
561    /// Debug format the current any type.
562    pub(crate) fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
563        vtable(self).debug(f)
564    }
565
566    /// Access the underlying type hash for the data.
567    pub fn type_hash(&self) -> Hash {
568        vtable(self).type_hash()
569    }
570
571    /// Access full type info for the underlying type.
572    pub fn type_info(&self) -> TypeInfo {
573        vtable(self).type_info()
574    }
575}
576
577impl Clone for AnyObj {
578    #[inline]
579    fn clone(&self) -> Self {
580        // SAFETY: We know that the inner value is live in this instance.
581        unsafe {
582            AnyObjData::inc(self.shared);
583        }
584
585        Self {
586            shared: self.shared,
587        }
588    }
589
590    #[inline]
591    fn clone_from(&mut self, source: &Self) {
592        if ptr::eq(self.shared.as_ptr(), source.shared.as_ptr()) {
593            return;
594        }
595
596        let old = replace(&mut self.shared, source.shared);
597
598        // SAFETY: We know that the inner value is live in both instances.
599        unsafe {
600            AnyObjData::dec(old);
601            AnyObjData::inc(self.shared);
602        }
603    }
604}
605
606impl TryClone for AnyObj {
607    #[inline]
608    fn try_clone(&self) -> alloc::Result<Self> {
609        Ok(self.clone())
610    }
611
612    #[inline]
613    fn try_clone_from(&mut self, source: &Self) -> alloc::Result<()> {
614        self.clone_from(source);
615        Ok(())
616    }
617}
618
619impl fmt::Debug for AnyObj {
620    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
621        self.debug(f)
622    }
623}
624
625impl Drop for AnyObj {
626    fn drop(&mut self) {
627        // Safety: We know that the inner value is live in this instance.
628        unsafe {
629            AnyObjData::dec(self.shared);
630        }
631    }
632}
633
634impl FromValue for AnyObj {
635    #[inline]
636    fn from_value(value: Value) -> Result<Self, RuntimeError> {
637        value.into_any_obj()
638    }
639}
640
641impl ToValue for AnyObj {
642    #[inline]
643    fn to_value(self) -> Result<Value, RuntimeError> {
644        Ok(Value::from(self))
645    }
646}
647
648#[repr(C)]
649pub(super) struct AnyObjData<T = ()> {
650    /// The currently handed out access to the shared data.
651    pub(super) access: Access,
652    /// The number of strong references to the shared data.
653    pub(super) count: Cell<usize>,
654    /// Vtable of the shared value.
655    pub(super) vtable: &'static AnyObjVtable,
656    /// Data of the shared reference.
657    pub(super) data: T,
658}
659
660impl AnyObjData {
661    /// Increment the reference count of the inner value.
662    #[inline]
663    pub(super) unsafe fn inc(this: NonNull<Self>) {
664        let count_ref = &*addr_of!((*this.as_ptr()).count);
665        let count = count_ref.get();
666
667        debug_assert_ne!(
668            count, 0,
669            "Reference count of zero should only happen if Shared is incorrectly implemented"
670        );
671
672        if count == usize::MAX {
673            crate::alloc::abort();
674        }
675
676        count_ref.set(count + 1);
677    }
678
679    /// Decrement the reference count in inner, and free the underlying data if
680    /// it has reached zero.
681    ///
682    /// # Safety
683    ///
684    /// ProtocolCaller needs to ensure that `this` is a valid pointer.
685    #[inline]
686    pub(super) unsafe fn dec(this: NonNull<Self>) {
687        let count_ref = &*addr_of!((*this.as_ptr()).count);
688        let count = count_ref.get();
689
690        debug_assert_ne!(
691            count, 0,
692            "Reference count of zero should only happen if Shared is incorrectly implemented"
693        );
694
695        let count = count - 1;
696        count_ref.set(count);
697
698        if count == 0 {
699            let vtable = *addr_of!((*this.as_ptr()).vtable);
700
701            if let Some(drop_value) = vtable.drop_value {
702                let access = &*addr_of!((*this.as_ptr()).access);
703
704                if !access.is_taken() {
705                    drop_value(this);
706                }
707            }
708
709            (vtable.drop)(this);
710        }
711    }
712}
713
714#[derive(Debug)]
715#[cfg_attr(test, derive(PartialEq))]
716pub(super) enum AnyObjErrorKind {
717    Alloc(alloc::Error),
718    Cast(AnyTypeInfo, TypeInfo),
719    AccessError(AccessError),
720    NotOwned(TypeInfo),
721}
722
723/// Errors caused when accessing or coercing an [`AnyObj`].
724#[cfg_attr(test, derive(PartialEq))]
725pub struct AnyObjError {
726    kind: AnyObjErrorKind,
727}
728
729impl AnyObjError {
730    #[inline]
731    pub(super) fn new(kind: AnyObjErrorKind) -> Self {
732        Self { kind }
733    }
734
735    #[inline]
736    pub(super) fn into_kind(self) -> AnyObjErrorKind {
737        self.kind
738    }
739}
740
741impl core::error::Error for AnyObjError {}
742
743impl fmt::Display for AnyObjError {
744    #[inline]
745    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
746        match &self.kind {
747            AnyObjErrorKind::Alloc(error) => error.fmt(f),
748            AnyObjErrorKind::Cast(expected, actual) => {
749                write!(f, "Failed to cast `{actual}` to `{expected}`")
750            }
751            AnyObjErrorKind::AccessError(error) => error.fmt(f),
752            AnyObjErrorKind::NotOwned(type_info) => {
753                write!(f, "Cannot use owned operations for {type_info}")
754            }
755        }
756    }
757}
758
759impl fmt::Debug for AnyObjError {
760    #[inline]
761    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
762        self.kind.fmt(f)
763    }
764}
765
766impl From<alloc::Error> for AnyObjError {
767    #[inline]
768    fn from(error: alloc::Error) -> Self {
769        Self::new(AnyObjErrorKind::Alloc(error))
770    }
771}
772
773impl From<AccessError> for AnyObjError {
774    #[inline]
775    fn from(error: AccessError) -> Self {
776        Self::new(AnyObjErrorKind::AccessError(error))
777    }
778}
779
780/// Guard which decrements and releases shared storage for the guarded reference.
781pub(super) struct AnyObjDecShared {
782    pub(super) shared: NonNull<AnyObjData>,
783}
784
785impl Drop for AnyObjDecShared {
786    fn drop(&mut self) {
787        // Safety: We know that the inner value is live in this instance.
788        unsafe {
789            AnyObjData::dec(self.shared);
790        }
791    }
792}
793
794/// Guard which decrements and releases shared storage for the guarded reference.
795pub(crate) struct AnyObjDrop {
796    #[allow(unused)]
797    pub(super) shared: NonNull<AnyObjData>,
798}
799
800impl Drop for AnyObjDrop {
801    #[inline]
802    fn drop(&mut self) {
803        // Safety: We know that the inner value is live in this instance.
804        unsafe {
805            self.shared.as_ref().access.take();
806            AnyObjData::dec(self.shared);
807        }
808    }
809}
810
811/// The guard returned when dealing with raw pointers.
812pub(crate) struct RawAnyObjGuard {
813    #[allow(unused)]
814    pub(super) guard: RawAccessGuard,
815    #[allow(unused)]
816    pub(super) dec_shared: AnyObjDecShared,
817}
818
819#[inline]
820fn vtable(any: &AnyObj) -> &'static AnyObjVtable {
821    unsafe { addr_of!((*any.shared.as_ptr()).vtable).read() }
822}