abi_stable/sabi_trait/
robject.rs

1use super::*;
2
3use std::fmt;
4
5#[allow(unused_imports)]
6use core_extensions::SelfOps;
7
8use crate::{
9    abi_stability::PrefixStableAbi,
10    erased_types::{c_functions::adapt_std_fmt, InterfaceType, MakeRequiredTraits},
11    pointer_trait::{
12        AsMutPtr, AsPtr, CanTransmuteElement, GetPointerKind, PK_Reference, PK_SmartPointer,
13        PointerKind, TransmuteElement,
14    },
15    sabi_trait::vtable::{BaseVtable_Prefix, BaseVtable_Ref},
16    sabi_types::{MaybeCmp, RMut, RRef},
17    std_types::UTypeId,
18    type_level::{
19        impl_enum::{Implemented, Unimplemented},
20        trait_marker,
21    },
22    StableAbi,
23};
24
25/// `RObject` implements ffi-safe trait objects, for a minimal selection of traits.
26///
27/// The main use of `RObject<_>` is as the default backend for `#[sabi_trait]`
28/// generated trait objects.
29///
30/// # Construction
31///
32/// `RObject<_>` is how `#[sabi_trait]`-based ffi-safe trait objects are implemented,
33/// and there's no way to construct it separate from those.
34///
35/// # Trait object
36///
37/// `RObject<'borrow, Pointer<()>, Interface, VTable>`
38/// can be used as a trait object for any combination of
39/// the traits listed below:
40///
41/// - [`Send`]
42///
43/// - [`Sync`]
44///
45/// - [`Unpin`](std::marker::Unpin)
46///
47/// - [`Debug`]
48///
49/// - [`Display`]
50///
51/// - [`Error`](std::error::Error)
52///
53/// - [`Clone`]
54///
55/// # Deconstruction
56///
57/// `RObject<_>` can be unwrapped into a concrete type,
58/// within the same dynamic library/executable that constructed it,
59/// using these (fallible) conversion methods:
60///
61/// - [`downcast_into`](#method.downcast_into):
62/// Unwraps into a pointer to `T`.Requires `T: 'static`.
63///
64/// - [`downcast_as`](#method.downcast_as):
65/// Unwraps into a `&T`.Requires `T: 'static`.
66///
67/// - [`downcast_as_mut`](#method.downcast_as_mut):
68/// Unwraps into a `&mut T`.Requires `T: 'static`.
69///
70/// `RObject` can only be converted back if the trait object was constructed to allow it.
71///
72///
73///
74///
75///
76#[repr(C)]
77#[derive(StableAbi)]
78#[sabi(
79    not_stableabi(V),
80    bound(V: PrefixStableAbi),
81    bound(I: InterfaceType),
82    extra_checks = <I as MakeRequiredTraits>::MAKE,
83)]
84pub struct RObject<'lt, P, I, V>
85where
86    P: GetPointerKind,
87{
88    vtable: PrefixRef<V>,
89    ptr: ManuallyDrop<P>,
90    _marker: PhantomData<(&'lt (), extern "C" fn() -> I)>,
91}
92
93mod clone_impl {
94    pub trait CloneImpl<PtrKind> {
95        fn clone_impl(&self) -> Self;
96    }
97}
98use self::clone_impl::CloneImpl;
99
100/// This impl is for smart pointers.
101impl<'lt, P, I, V> CloneImpl<PK_SmartPointer> for RObject<'lt, P, I, V>
102where
103    P: AsPtr,
104    I: InterfaceType<Clone = Implemented<trait_marker::Clone>>,
105{
106    fn clone_impl(&self) -> Self {
107        let ptr =
108            unsafe { self.sabi_robject_vtable()._sabi_clone().unwrap()(RRef::new(&self.ptr)) };
109        Self {
110            vtable: self.vtable,
111            ptr: ManuallyDrop::new(ptr),
112            _marker: PhantomData,
113        }
114    }
115}
116
117/// This impl is for references.
118impl<'lt, P, I, V> CloneImpl<PK_Reference> for RObject<'lt, P, I, V>
119where
120    P: AsPtr + Copy,
121    I: InterfaceType,
122{
123    fn clone_impl(&self) -> Self {
124        Self {
125            vtable: self.vtable,
126            ptr: ManuallyDrop::new(*self.ptr),
127            _marker: PhantomData,
128        }
129    }
130}
131
132/// Clone is implemented for references and smart pointers,
133/// using `GetPointerKind` to decide whether `P` is a smart pointer or a reference.
134///
135/// RObject does not implement Clone if `P` == `&mut ()` :
136///
137///
138/// ```compile_fail
139/// use abi_stable::{
140///     sabi_trait::{doc_examples::ConstExample_TO, TD_Opaque},
141///     std_types::*,
142/// };
143///
144/// let mut object = ConstExample_TO::from_value(10usize, TD_Opaque);
145/// let borrow = object.sabi_reborrow_mut();
146/// let _ = borrow.clone();
147/// ```
148///
149/// Here is the same example with `sabi_reborrow`
150///
151/// ```
152/// use abi_stable::{
153///     sabi_trait::{doc_examples::ConstExample_TO, TD_Opaque},
154///     std_types::*,
155/// };
156///
157/// let mut object = ConstExample_TO::from_value(10usize, TD_Opaque);
158/// let borrow = object.sabi_reborrow();
159/// let _ = borrow.clone();
160/// ```
161///
162///
163impl<'lt, P, I, V> Clone for RObject<'lt, P, I, V>
164where
165    P: AsPtr,
166    I: InterfaceType,
167    Self: CloneImpl<<P as GetPointerKind>::Kind>,
168{
169    fn clone(&self) -> Self {
170        self.clone_impl()
171    }
172}
173
174impl<'lt, P, I, V> Debug for RObject<'lt, P, I, V>
175where
176    P: AsPtr<PtrTarget = ()> + AsPtr,
177    I: InterfaceType<Debug = Implemented<trait_marker::Debug>>,
178{
179    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180        unsafe {
181            adapt_std_fmt::<ErasedObject>(
182                self.sabi_erased_ref(),
183                self.sabi_robject_vtable()._sabi_debug().unwrap(),
184                f,
185            )
186        }
187    }
188}
189
190impl<'lt, P, I, V> Display for RObject<'lt, P, I, V>
191where
192    P: AsPtr<PtrTarget = ()>,
193    I: InterfaceType<Display = Implemented<trait_marker::Display>>,
194{
195    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196        unsafe {
197            adapt_std_fmt::<ErasedObject>(
198                self.sabi_erased_ref(),
199                self.sabi_robject_vtable()._sabi_display().unwrap(),
200                f,
201            )
202        }
203    }
204}
205
206impl<'lt, P, I, V> std::error::Error for RObject<'lt, P, I, V>
207where
208    P: AsPtr<PtrTarget = ()>,
209    I: InterfaceType<
210        Display = Implemented<trait_marker::Display>,
211        Debug = Implemented<trait_marker::Debug>,
212        Error = Implemented<trait_marker::Error>,
213    >,
214{
215}
216
217unsafe impl<'lt, P, I, V> Send for RObject<'lt, P, I, V>
218where
219    P: GetPointerKind,
220    I: InterfaceType<Send = Implemented<trait_marker::Send>>,
221{
222}
223
224unsafe impl<'lt, P, I, V> Sync for RObject<'lt, P, I, V>
225where
226    P: GetPointerKind,
227    I: InterfaceType<Sync = Implemented<trait_marker::Sync>>,
228{
229}
230
231impl<'lt, P, I, V> Unpin for RObject<'lt, P, I, V>
232where
233    // `Unpin` is a property of the referent
234    P: GetPointerKind,
235    I: InterfaceType<Unpin = Implemented<trait_marker::Unpin>>,
236{
237}
238
239impl<'lt, P, I, V> RObject<'lt, P, I, V>
240where
241    P: AsPtr<PtrTarget = ()>,
242{
243    /// Constructs an RObject from a pointer and an extra vtable.
244    ///
245    /// This is mostly intended to be called by `#[sabi_trait]` generated trait objects.
246    ///
247    /// # Safety
248    ///
249    /// These are the requirements for the caller:
250    ///
251    /// - `P` must be a pointer to the type that the vtable functions
252    ///     take as the first parameter.
253    ///
254    /// - The vtable must not come from a reborrowed `RObject`
255    ///     (created using `RObject::reborrow` or `RObject::reborrow_mut`).
256    ///
257    /// - The vtable must be the `SomeVTableName` of a struct declared with
258    ///     `#[derive(StableAbi)] #[sabi(kind(Prefix(prefix_ref= SomeVTableName)))]`.
259    ///
260    /// - The vtable must have `RObjectVtable_Ref` as its first declared field
261    ///
262    pub unsafe fn with_vtable<OrigPtr>(ptr: OrigPtr, vtable: PrefixRef<V>) -> RObject<'lt, P, I, V>
263    where
264        OrigPtr: CanTransmuteElement<(), TransmutedPtr = P>,
265        OrigPtr::PtrTarget: Sized + 'lt,
266        P: AsPtr<PtrTarget = ()>,
267    {
268        RObject {
269            vtable,
270            ptr: ManuallyDrop::new(unsafe { ptr.transmute_element::<()>() }),
271            _marker: PhantomData,
272        }
273    }
274}
275
276impl<'borr, 'a, I, V> RObject<'borr, RRef<'a, ()>, I, V> {
277    /// This function allows constructing an RObject in a constant/static.
278    ///
279    /// This is mostly intended for `#[sabi_trait]`-generated trait objects
280    ///
281    /// # Safety
282    ///
283    /// This has the same safety requirements as `RObject::with_vtable`
284    ///
285    /// # Example
286    ///
287    /// Because this is intended for `#[sabi_trait]` generated trait objects,
288    /// this demonstrates how to construct one in a constant.
289    ///
290    /// ```
291    /// use abi_stable::sabi_trait::{
292    ///     doc_examples::ConstExample_CTO,
293    ///     prelude::TD_Opaque,
294    /// };
295    ///
296    /// const EXAMPLE0: ConstExample_CTO<'static, 'static> =
297    ///     ConstExample_CTO::from_const(&0usize, TD_Opaque);
298    ///
299    /// ```
300    pub const unsafe fn with_vtable_const<T, Downcasting>(ptr: &'a T, vtable: PrefixRef<V>) -> Self
301    where
302        T: 'borr,
303    {
304        RObject {
305            vtable,
306            ptr: {
307                let x = unsafe { RRef::new(ptr).transmute::<()>() };
308                ManuallyDrop::new(x)
309            },
310            _marker: PhantomData,
311        }
312    }
313}
314
315impl<'lt, P, I, V> RObject<'lt, P, I, V>
316where
317    P: GetPointerKind,
318{
319    /// The uid in the vtable has to be the same as the one for T,
320    /// otherwise it was not created from that T in the library that
321    /// declared the trait object.
322    fn sabi_check_same_utypeid<T>(&self) -> Result<(), UneraseError<()>>
323    where
324        T: 'static,
325    {
326        let expected_typeid = self.sabi_robject_vtable()._sabi_type_id()();
327        let actual_typeid = UTypeId::new::<T>();
328        if expected_typeid == MaybeCmp::Just(actual_typeid) {
329            Ok(())
330        } else {
331            Err(UneraseError {
332                robject: (),
333                expected_typeid,
334                actual_typeid,
335            })
336        }
337    }
338
339    /// Attempts to unerase this trait object into the pointer it was constructed with.
340    ///
341    /// # Errors
342    ///
343    /// This will return an error in any of these conditions:
344    ///
345    /// - It is called in a dynamic library/binary outside
346    /// the one from which this RObject was constructed.
347    ///
348    /// - The trait object wrapping this `RObject` was constructed with a
349    /// `TD_CanDowncast` argument.
350    ///
351    /// - `T` is not the concrete type this `RObject<_>` was constructed with.
352    ///
353    /// # Example
354    ///
355    /// ```rust
356    /// use abi_stable::{
357    ///     sabi_trait::doc_examples::Doer_TO, std_types::RBox,
358    ///     type_level::downcasting::TD_CanDowncast,
359    /// };
360    ///
361    /// let to = || Doer_TO::from_value(5usize, TD_CanDowncast);
362    ///
363    /// // `to.obj` is an RObject
364    /// assert_eq!(
365    ///     to().obj.downcast_into::<usize>().ok(),
366    ///     Some(RBox::new(5usize))
367    /// );
368    /// assert_eq!(to().obj.downcast_into::<u8>().ok(), None);
369    ///
370    /// ```
371    pub fn downcast_into<T>(self) -> Result<P::TransmutedPtr, UneraseError<Self>>
372    where
373        T: 'static,
374        P: AsPtr<PtrTarget = ()> + CanTransmuteElement<T>,
375    {
376        check_unerased!(self, self.sabi_check_same_utypeid::<T>());
377        unsafe {
378            let this = ManuallyDrop::new(self);
379            Ok(ptr::read(&*this.ptr).transmute_element::<T>())
380        }
381    }
382
383    /// Attempts to unerase this trait object into a reference of
384    /// the value was constructed with.
385    ///
386    /// # Errors
387    ///
388    /// This will return an error in any of these conditions:
389    ///
390    /// - It is called in a dynamic library/binary outside
391    /// the one from which this RObject was constructed.
392    ///
393    /// - The trait object wrapping this `RObject` was constructed with a
394    /// `TD_CanDowncast` argument.
395    ///
396    /// - `T` is not the concrete type this `RObject<_>` was constructed with.
397    ///
398    /// # Example
399    ///
400    /// ```rust
401    /// use abi_stable::{
402    ///     sabi_trait::doc_examples::Doer_TO, std_types::RArc,
403    ///     type_level::downcasting::TD_CanDowncast, RMut, RRef,
404    /// };
405    ///
406    /// {
407    ///     let to: Doer_TO<'_, RArc<()>> =
408    ///         Doer_TO::from_ptr(RArc::new(8usize), TD_CanDowncast);
409    ///
410    ///     // `to.obj` is an RObject
411    ///     assert_eq!(to.obj.downcast_as::<usize>().ok(), Some(&8usize));
412    ///     assert_eq!(to.obj.downcast_as::<u8>().ok(), None);
413    /// }
414    /// {
415    ///     // `#[sabi_trait]` trait objects constructed from `&`
416    ///     // use `RRef<'_, ()>` instead of `&'_ ()`
417    ///     // since `&T` can't soundly be transmuted back and forth into `&()`
418    ///     let to: Doer_TO<'_, RRef<'_, ()>> = Doer_TO::from_ptr(&13usize, TD_CanDowncast);
419    ///
420    ///     assert_eq!(to.obj.downcast_as::<usize>().ok(), Some(&13usize));
421    ///     assert_eq!(to.obj.downcast_as::<u8>().ok(), None);
422    /// }
423    /// {
424    ///     let mmut = &mut 21usize;
425    ///     // `#[sabi_trait]` trait objects constructed from `&mut`
426    ///     // use `RMut<'_, ()>` instead of `&'_ mut ()`
427    ///     // since `&mut T` can't soundly be transmuted back and forth into `&mut ()`
428    ///     let to: Doer_TO<'_, RMut<'_, ()>> = Doer_TO::from_ptr(mmut, TD_CanDowncast);
429    ///
430    ///     assert_eq!(to.obj.downcast_as::<usize>().ok(), Some(&21usize));
431    ///     assert_eq!(to.obj.downcast_as::<u8>().ok(), None);
432    /// }
433    ///
434    /// ```
435    pub fn downcast_as<T>(&self) -> Result<&T, UneraseError<&Self>>
436    where
437        T: 'static,
438        P: AsPtr<PtrTarget = ()> + CanTransmuteElement<T>,
439    {
440        check_unerased!(self, self.sabi_check_same_utypeid::<T>());
441        unsafe { Ok(&*(self.ptr.as_ptr() as *const T)) }
442    }
443
444    /// Attempts to unerase this trait object into a mutable reference of
445    /// the value was constructed with.
446    ///
447    /// # Errors
448    ///
449    /// This will return an error in any of these conditions:
450    ///
451    /// - It is called in a dynamic library/binary outside
452    /// the one from which this RObject was constructed.
453    ///
454    /// - The trait object wrapping this `RObject` was constructed with a
455    /// `TD_CanDowncast` argument.
456    ///
457    /// - `T` is not the concrete type this `RObject<_>` was constructed with.
458    ///
459    ///
460    /// # Example
461    ///
462    /// ```rust
463    /// use abi_stable::{
464    ///     sabi_trait::doc_examples::Doer_TO, std_types::RBox,
465    ///     type_level::downcasting::TD_CanDowncast, RMut, RRef,
466    /// };
467    ///
468    /// {
469    ///     let mut to: Doer_TO<'_, RBox<()>> =
470    ///         Doer_TO::from_value(34usize, TD_CanDowncast);
471    ///
472    ///     // `to.obj` is an RObject
473    ///     assert_eq!(to.obj.downcast_as_mut::<usize>().ok(), Some(&mut 34usize));
474    ///     assert_eq!(to.obj.downcast_as_mut::<u8>().ok(), None);
475    /// }
476    /// {
477    ///     let mmut = &mut 55usize;
478    ///     // `#[sabi_trait]` trait objects constructed from `&mut`
479    ///     // use `RMut<'_, ()>` instead of `&'_ mut ()`
480    ///     // since `&mut T` can't soundly be transmuted back and forth into `&mut ()`
481    ///     let mut to: Doer_TO<'_, RMut<'_, ()>> = Doer_TO::from_ptr(mmut, TD_CanDowncast);
482    ///
483    ///     assert_eq!(to.obj.downcast_as_mut::<usize>().ok(), Some(&mut 55usize));
484    ///     assert_eq!(to.obj.downcast_as_mut::<u8>().ok(), None);
485    /// }
486    ///
487    /// ```
488    pub fn downcast_as_mut<T>(&mut self) -> Result<&mut T, UneraseError<&mut Self>>
489    where
490        T: 'static,
491        P: AsMutPtr<PtrTarget = ()> + CanTransmuteElement<T>,
492    {
493        check_unerased!(self, self.sabi_check_same_utypeid::<T>());
494        unsafe { Ok(&mut *(self.ptr.as_mut_ptr() as *mut T)) }
495    }
496
497    /// Unwraps the `RObject<_>` into a pointer to T,
498    /// without checking whether `T` is the type that the RObject was constructed with.
499    ///
500    /// # Safety
501    ///
502    /// You must check that `T` is the type that RObject was constructed
503    /// with through other means.
504    ///
505    /// # Example
506    ///
507    /// ```rust
508    /// use abi_stable::{
509    ///     sabi_trait::doc_examples::Doer_TO, std_types::RBox,
510    ///     type_level::downcasting::TD_Opaque,
511    /// };
512    ///
513    /// let to = || Doer_TO::from_value(5usize, TD_Opaque);
514    ///
515    /// unsafe {
516    ///     // `to.obj` is an RObject
517    ///     assert_eq!(
518    ///         to().obj.unchecked_downcast_into::<usize>(),
519    ///         RBox::new(5usize)
520    ///     );
521    /// }
522    /// ```
523    #[inline]
524    pub unsafe fn unchecked_downcast_into<T>(self) -> P::TransmutedPtr
525    where
526        P: AsPtr<PtrTarget = ()> + CanTransmuteElement<T>,
527    {
528        let this = ManuallyDrop::new(self);
529        unsafe { ptr::read(&*this.ptr).transmute_element::<T>() }
530    }
531
532    /// Unwraps the `RObject<_>` into a reference to T,
533    /// without checking whether `T` is the type that the RObject was constructed with.
534    ///
535    /// # Safety
536    ///
537    /// You must check that `T` is the type that RObject was constructed
538    /// with through other means.
539    ///
540    /// # Example
541    ///
542    /// ```rust
543    /// use abi_stable::{
544    ///     sabi_trait::doc_examples::Doer_TO, std_types::RArc,
545    ///     type_level::downcasting::TD_Opaque, RMut, RRef,
546    /// };
547    ///
548    /// {
549    ///     let to: Doer_TO<'_, RArc<()>> = Doer_TO::from_ptr(RArc::new(8usize), TD_Opaque);
550    ///
551    ///     unsafe {
552    ///         // `to.obj` is an RObject
553    ///         assert_eq!(to.obj.unchecked_downcast_as::<usize>(), &8usize);
554    ///     }
555    /// }
556    /// {
557    ///     // `#[sabi_trait]` trait objects constructed from `&`
558    ///     // use `RRef<'_, ()>` instead of `&'_ ()`
559    ///     // since `&T` can't soundly be transmuted back and forth into `&()`
560    ///     let to: Doer_TO<'_, RRef<'_, ()>> = Doer_TO::from_ptr(&13usize, TD_Opaque);
561    ///
562    ///     unsafe {
563    ///         assert_eq!(to.obj.unchecked_downcast_as::<usize>(), &13usize);
564    ///     }
565    /// }
566    /// {
567    ///     let mmut = &mut 21usize;
568    ///     // `#[sabi_trait]` trait objects constructed from `&mut`
569    ///     // use `RMut<'_, ()>` instead of `&'_ mut ()`
570    ///     // since `&mut T` can't soundly be transmuted back and forth into `&mut ()`
571    ///     let to: Doer_TO<'_, RMut<'_, ()>> = Doer_TO::from_ptr(mmut, TD_Opaque);
572    ///
573    ///     unsafe {
574    ///         assert_eq!(to.obj.unchecked_downcast_as::<usize>(), &21usize);
575    ///     }
576    /// }
577    ///
578    /// ```
579    #[inline]
580    pub unsafe fn unchecked_downcast_as<T>(&self) -> &T
581    where
582        P: AsPtr<PtrTarget = ()>,
583    {
584        unsafe { &*(self.ptr.as_ptr() as *const T) }
585    }
586
587    /// Unwraps the `RObject<_>` into a mutable reference to T,
588    /// without checking whether `T` is the type that the RObject was constructed with.
589    ///
590    /// # Safety
591    ///
592    /// You must check that `T` is the type that RObject was constructed
593    /// with through other means.
594    ///
595    /// # Example
596    ///
597    /// ```rust
598    /// use abi_stable::{
599    ///     sabi_trait::doc_examples::Doer_TO, std_types::RBox,
600    ///     type_level::downcasting::TD_Opaque, RMut, RRef,
601    /// };
602    ///
603    /// {
604    ///     let mut to: Doer_TO<'_, RBox<()>> = Doer_TO::from_value(34usize, TD_Opaque);
605    ///
606    ///     unsafe {
607    ///         // `to.obj` is an RObject
608    ///         assert_eq!(to.obj.unchecked_downcast_as_mut::<usize>(), &mut 34usize);
609    ///     }
610    /// }
611    /// {
612    ///     let mmut = &mut 55usize;
613    ///     // `#[sabi_trait]` trait objects constructed from `&mut`
614    ///     // use `RMut<'_, ()>` instead of `&'_ mut ()`
615    ///     // since `&mut T` can't soundly be transmuted back and forth into `&mut ()`
616    ///     let mut to: Doer_TO<'_, RMut<'_, ()>> = Doer_TO::from_ptr(mmut, TD_Opaque);
617    ///
618    ///     unsafe {
619    ///         assert_eq!(to.obj.unchecked_downcast_as_mut::<usize>(), &mut 55usize);
620    ///     }
621    /// }
622    ///
623    /// ```
624    #[inline]
625    pub unsafe fn unchecked_downcast_as_mut<T>(&mut self) -> &mut T
626    where
627        P: AsMutPtr<PtrTarget = ()>,
628    {
629        unsafe { &mut *(self.ptr.as_mut_ptr() as *mut T) }
630    }
631}
632
633mod private_struct {
634    pub struct PrivStruct;
635}
636use self::private_struct::PrivStruct;
637
638/// This is used to make sure that reborrowing does not change
639/// the Send-ness or Sync-ness of the pointer.
640pub trait ReborrowBounds<SendNess, SyncNess> {}
641
642// If it's reborrowing, it must have either both Sync+Send or neither.
643impl ReborrowBounds<Unimplemented<trait_marker::Send>, Unimplemented<trait_marker::Sync>>
644    for PrivStruct
645{
646}
647
648impl ReborrowBounds<Implemented<trait_marker::Send>, Implemented<trait_marker::Sync>>
649    for PrivStruct
650{
651}
652
653impl<'lt, P, I, V> RObject<'lt, P, I, V>
654where
655    P: GetPointerKind,
656    I: InterfaceType,
657{
658    /// Creates a shared reborrow of this RObject.
659    ///
660    /// This is only callable if `RObject` is either `Send + Sync` or `!Send + !Sync`.
661    ///
662    /// # Example
663    ///
664    /// ```rust
665    /// use abi_stable::{
666    ///     sabi_trait::doc_examples::Doer_TO, std_types::RBox,
667    ///     type_level::downcasting::TD_Opaque, RMut, RRef,
668    /// };
669    ///
670    /// let mut to: Doer_TO<'_, RBox<()>> = Doer_TO::from_value(13usize, TD_Opaque);
671    ///
672    /// // `to.obj` is an RObject
673    /// assert_eq!(debug_string(to.obj.reborrow()), "13");
674    /// assert_eq!(debug_string(to.obj.reborrow()), "13");
675    ///
676    /// // `#[sabi_trait]` trait objects have an equivalent `sabi_reborrow` method.
677    /// assert_eq!(debug_string(to.sabi_reborrow()), "13");
678    /// assert_eq!(debug_string(to.sabi_reborrow()), "13");
679    ///
680    /// fn debug_string<T>(to: T) -> String
681    /// where
682    ///     T: std::fmt::Debug,
683    /// {
684    ///     format!("{:?}", to)
685    /// }
686    ///
687    /// ```
688    pub fn reborrow<'re>(&'re self) -> RObject<'lt, RRef<'re, ()>, I, V>
689    where
690        P: AsPtr<PtrTarget = ()>,
691        PrivStruct: ReborrowBounds<I::Send, I::Sync>,
692    {
693        // Reborrowing will break if I add extra functions that operate on `P`.
694        RObject {
695            vtable: self.vtable,
696            ptr: ManuallyDrop::new(self.ptr.as_rref()),
697            _marker: PhantomData,
698        }
699    }
700
701    /// Creates a mutable reborrow of this RObject.
702    ///
703    /// The reborrowed RObject cannot use these methods:
704    ///
705    /// - RObject::clone
706    ///
707    /// This is only callable if `RObject` is either `Send + Sync` or `!Send + !Sync`.
708    ///
709    /// # Example
710    ///
711    /// ```rust
712    /// use abi_stable::{
713    ///     sabi_trait::doc_examples::{Doer, Doer_TO},
714    ///     std_types::RBox,
715    ///     type_level::downcasting::TD_Opaque,
716    ///     RMut, RRef,
717    /// };
718    ///
719    /// let mut to: Doer_TO<'_, RBox<()>> = Doer_TO::from_value(2usize, TD_Opaque);
720    ///
721    /// // `#[sabi_trait]` trait objects have an equivalent `sabi_reborrow_mut` method,
722    /// // which delegate to this method.
723    /// assert_eq!(increment(to.sabi_reborrow_mut()).value(), 3);
724    /// assert_eq!(increment(to.sabi_reborrow_mut()).value(), 4);
725    ///
726    /// fn increment<T>(mut to: T) -> T
727    /// where
728    ///     T: Doer,
729    /// {
730    ///     to.add_into(1);
731    ///     to
732    /// }
733    ///
734    /// ```
735    pub fn reborrow_mut<'re>(&'re mut self) -> RObject<'lt, RMut<'re, ()>, I, V>
736    where
737        P: AsMutPtr<PtrTarget = ()>,
738        PrivStruct: ReborrowBounds<I::Send, I::Sync>,
739    {
740        // Reborrowing will break if I add extra functions that operate on `P`.
741        RObject {
742            vtable: self.vtable,
743            ptr: ManuallyDrop::new(self.ptr.as_rmut()),
744            _marker: PhantomData,
745        }
746    }
747}
748
749impl<'lt, P, I, V> RObject<'lt, P, I, V>
750where
751    P: GetPointerKind,
752{
753    /// Gets the vtable.
754    #[inline]
755    pub const fn sabi_et_vtable(&self) -> PrefixRef<V> {
756        self.vtable
757    }
758
759    /// The vtable common to all `#[sabi_trait]` generated trait objects.
760    #[inline]
761    pub fn sabi_robject_vtable(&self) -> RObjectVtable_Ref<(), P, I> {
762        unsafe { BaseVtable_Ref(self.vtable.cast::<BaseVtable_Prefix<(), P, I>>())._sabi_vtable() }
763    }
764
765    #[inline]
766    fn sabi_into_erased_ptr(self) -> ManuallyDrop<P> {
767        let __this = ManuallyDrop::new(self);
768        unsafe { ptr::read(&__this.ptr) }
769    }
770
771    /// Gets an `RRef` pointing to the erased object.
772    pub fn sabi_erased_ref(&self) -> RRef<'_, ErasedObject<()>>
773    where
774        P: AsPtr<PtrTarget = ()>,
775    {
776        unsafe { RRef::from_raw(self.ptr.as_ptr() as *const _) }
777    }
778
779    /// Gets an `RMut` pointing to the erased object.
780    pub fn sabi_erased_mut(&mut self) -> RMut<'_, ErasedObject<()>>
781    where
782        P: AsMutPtr<PtrTarget = ()>,
783    {
784        unsafe { RMut::from_raw(self.ptr.as_mut_ptr() as *mut _) }
785    }
786
787    /// Gets an `RRef` pointing to the erased object.
788    pub fn sabi_as_rref(&self) -> RRef<'_, ()>
789    where
790        P: AsPtr<PtrTarget = ()>,
791    {
792        self.ptr.as_rref()
793    }
794
795    /// Gets an `RMut` pointing to the erased object.
796    pub fn sabi_as_rmut(&mut self) -> RMut<'_, ()>
797    where
798        P: AsMutPtr<PtrTarget = ()>,
799    {
800        self.ptr.as_rmut()
801    }
802
803    /// Calls the `f` callback with an `MovePtr` pointing to the erased object.
804    #[inline]
805    pub fn sabi_with_value<F, R>(self, f: F) -> R
806    where
807        P: OwnedPointer<PtrTarget = ()>,
808        F: FnOnce(MovePtr<'_, ()>) -> R,
809    {
810        OwnedPointer::with_move_ptr(self.sabi_into_erased_ptr(), f)
811    }
812}
813
814impl<'lt, I, V> RObject<'lt, crate::std_types::RArc<()>, I, V> {
815    /// Does a shallow clone of the object, just incrementing the reference counter
816    pub fn shallow_clone(&self) -> Self {
817        Self {
818            vtable: self.vtable,
819            ptr: self.ptr.clone(),
820            _marker: PhantomData,
821        }
822    }
823}
824
825impl<P, I, V> Drop for RObject<'_, P, I, V>
826where
827    P: GetPointerKind,
828{
829    fn drop(&mut self) {
830        // This condition is necessary because if the RObject was reborrowed,
831        // the destructor function would take a different pointer type.
832        if <P as GetPointerKind>::KIND == PointerKind::SmartPointer {
833            let destructor = self.sabi_robject_vtable()._sabi_drop();
834            unsafe {
835                destructor(RMut::<P>::new(&mut self.ptr));
836            }
837        }
838    }
839}
840
841//////////////////////////////////////////////////////////////////
842
843/// Error for `RObject<_>` being downcasted into the wrong type
844/// with one of the `*downcast*` methods.
845#[derive(Copy, Clone)]
846pub struct UneraseError<T> {
847    robject: T,
848    expected_typeid: MaybeCmp<UTypeId>,
849    actual_typeid: UTypeId,
850}
851
852#[allow(clippy::missing_const_for_fn)]
853impl<T> UneraseError<T> {
854    fn map<F, U>(self, f: F) -> UneraseError<U>
855    where
856        F: FnOnce(T) -> U,
857    {
858        UneraseError {
859            robject: f(self.robject),
860            expected_typeid: self.expected_typeid,
861            actual_typeid: self.actual_typeid,
862        }
863    }
864
865    /// Extracts the RObject, to handle the failure to unerase it.
866    #[must_use]
867    pub fn into_inner(self) -> T {
868        self.robject
869    }
870}
871
872impl<D> fmt::Debug for UneraseError<D> {
873    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
874        f.debug_struct("UneraseError")
875            .field("dyn_trait", &"<not shown>")
876            .field("expected_typeid", &self.expected_typeid)
877            .field("actual_typeid", &self.actual_typeid)
878            .finish()
879    }
880}
881
882impl<D> fmt::Display for UneraseError<D> {
883    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
884        fmt::Debug::fmt(self, f)
885    }
886}
887
888impl<D> ::std::error::Error for UneraseError<D> {}
889
890//////////////////////////////////////////////////////////////////