autocxx/
reference_wrapper.rs

1// Copyright 2022 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use core::{marker::PhantomData, ops::Deref, pin::Pin};
10
11#[cfg(nightly)]
12use std::{marker::Unsize, ops::DispatchFromDyn};
13
14use cxx::{memory::UniquePtrTarget, UniquePtr};
15
16/// A C++ const reference. These are different from Rust's `&T` in that
17/// these may exist even while the object is mutated elsewhere. See also
18/// [`CppMutRef`] for the mutable equivalent.
19///
20/// The key rule is: we *never* dereference these in Rust. Therefore, any
21/// UB here cannot manifest within Rust, but only across in C++, and therefore
22/// they are equivalently safe to using C++ references in pure-C++ codebases.
23///
24/// *Important*: you might be wondering why you've never encountered this type.
25/// These exist in autocxx-generated bindings only if the `unsafe_references_wrapped`
26/// safety policy is given. This may become the default in future.
27///
28/// # Usage
29///
30/// These types of references are pretty useless in Rust. You can't do
31/// field access. But, you can pass them back into C++! And specifically,
32/// you can call methods on them (i.e. use this type as a `this`). So
33/// the common case here is when C++ gives you a reference to some type,
34/// then you want to call methods on that reference.
35///
36/// # Calling methods
37///
38/// As noted, one of the main reasons for this type is to call methods.
39/// Unfortunately, that depends on unstable Rust features. If you can't
40/// call methods on one of these references, check you're using nightly
41/// and add `#![feature(arbitrary_self_types_pointers)]` to your crate.
42///
43/// # Lifetimes and cloneability
44///
45/// Although these references implement C++ aliasing semantics, they
46/// do attempt to give you Rust lifetime tracking. This means if a C++ object
47/// gives you a reference, you won't be able to use that reference after the
48/// C++ object is no longer around.
49///
50/// This is usually what you need, since a C++ object will typically give
51/// you a reference to part of _itself_ or something that it owns. But,
52/// if you know that the returned reference lasts longer than its vendor,
53/// you can use `lifetime_cast` to get a long-lived version.
54///
55/// On the other hand, these references do not give you Rust's exclusivity
56/// guarantees. These references can be freely cloned, and using [`CppRef::const_cast`]
57/// you can even make a mutable reference from an immutable reference.
58///
59/// # Field access
60///
61/// Field access would be achieved by adding C++ `get` and/or `set` methods.
62/// It's possible that a future version of `autocxx` could generate such
63/// getters and setters automatically, but they would need to be `unsafe`
64/// because there is no guarantee that the referent of a `CppRef` is actually
65/// what it's supposed to be, or alive. `CppRef`s may flow from C++ to Rust
66/// via arbitrary means, and with sufficient uses of `get` and `set` it would
67/// even be possible to create a use-after-free in pure Rust code (for instance,
68/// store a [`CppPin`] in a struct field, get a `CppRef` to its referent, then
69/// use a setter to reset that field of the struct.)
70///
71/// # Deref
72///
73/// This type implements [`Deref`] because that's the mechanism that the
74/// unstable Rust `arbitrary_self_types` features uses to determine callable
75/// methods. However, actually calling `Deref::deref` is not permitted and will
76/// result in a compilation failure. If you wish to create a Rust reference
77/// from the C++ reference, see [`CppRef::as_ref`].
78///
79/// # Nullness
80///
81/// Creation of a null C++ reference is undefined behavior (because such
82/// a reference can only be created by dereferencing a null pointer.)
83/// However, in practice, they exist, and we need to be compatible with
84/// pre-existing C++ APIs even if they do naughty things like this.
85/// Therefore this `CppRef` type does allow null values. This is a bit
86/// unfortunate because it means `Option<CppRef<T>>`
87/// occupies more space than `CppRef<T>`.
88///
89/// # Dynamic dispatch
90///
91/// You might wonder if you can do this:
92/// ```ignore
93/// let CppRef<dyn Trait> = ...; // obtain some CppRef<concrete type>
94/// ```
95/// Dynamic dispatch works so long as you're using nightly (we require another
96/// unstable feature, `dispatch_from_dyn`). But we need somewhere to store
97/// the trait object, and `CppRef` isn't it -- a `CppRef` can only store a
98/// simple pointer to something else. So, you need to store the trait object
99/// in a `Box` or similar:
100/// ```ignore
101/// trait SomeTrait {
102///    fn some_method(self: CppRef<Self>)
103/// }
104/// impl SomeTrait for ffi::Concrete {
105///   fn some_method(self: CppRef<Self>) {}
106/// }
107/// let obj: Pin<Box<dyn SomeTrait>> = ffi::Concrete::new().within_box();
108/// let obj = CppPin::from_pinned_box(obj);
109/// farm_area.as_cpp_ref().some_method();
110/// ```
111///
112/// # Implementation notes
113///
114/// Internally, this is represented as a raw pointer in Rust. See the note above
115/// about Nullness for why we don't use [`core::ptr::NonNull`].
116#[repr(transparent)]
117pub struct CppRef<'a, T: ?Sized> {
118    ptr: *const T,
119    phantom: PhantomData<&'a T>,
120}
121
122impl<'a, T: ?Sized> CppRef<'a, T> {
123    /// Retrieve the underlying C++ pointer.
124    pub fn as_ptr(&self) -> *const T {
125        self.ptr
126    }
127
128    /// Get a regular Rust reference out of this C++ reference.
129    ///
130    /// # Safety
131    ///
132    /// Callers must guarantee that the referent is not modified by any other
133    /// C++ or Rust code while the returned reference exists. Callers must
134    /// also guarantee that no mutable Rust reference is created to the
135    /// referent while the returned reference exists.
136    ///
137    /// Callers must also be sure that the C++ reference is properly
138    /// aligned, not null, pointing to valid data, etc.
139    pub unsafe fn as_ref(&self) -> &T {
140        &*self.as_ptr()
141    }
142
143    /// Create a C++ reference from a raw pointer.
144    pub fn from_ptr(ptr: *const T) -> Self {
145        Self {
146            ptr,
147            phantom: PhantomData,
148        }
149    }
150
151    /// Create a mutable version of this reference, roughly equivalent
152    /// to C++ `const_cast`.
153    ///
154    /// The opposite is to use [`AsCppRef::as_cpp_ref`] on a [`CppMutRef`]
155    /// to obtain a [`CppRef`].
156    ///
157    /// # Safety
158    ///
159    /// Because we never dereference a `CppRef` in Rust, this cannot create
160    /// undefined behavior _within Rust_ and is therefore not unsafe. It is
161    /// however generally unwise, just as it is in C++. Use sparingly.
162    pub fn const_cast(&self) -> CppMutRef<'a, T> {
163        CppMutRef {
164            ptr: self.ptr as *mut T,
165            phantom: PhantomData,
166        }
167    }
168
169    /// Extend the lifetime of the returned reference beyond normal Rust
170    /// borrow checker rules.
171    ///
172    /// Normally, a reference can't be used beyond the lifetime of the object
173    /// which gave it to you, but sometimes C++ APIs can return references
174    /// to global or other longer-lived objects. In such a case you should
175    /// use this method to get a longer-lived reference.
176    ///
177    /// # Usage
178    ///
179    /// When you're given a C++ reference and you know its referent is valid
180    /// for a long time, use this method. Store the resulting `PhantomReferent`
181    /// somewhere in Rust with an equivalent lifetime.
182    /// That object can then vend longer-lived `CppRef`s using
183    /// [`AsCppRef::as_cpp_ref`].
184    ///
185    /// # Safety
186    ///
187    /// Because `CppRef`s are never dereferenced in Rust, misuse of this API
188    /// cannot lead to undefined behavior _in Rust_ and is therefore not
189    /// unsafe. Nevertheless this can lead to UB in C++, so use carefully.
190    pub fn lifetime_cast(&self) -> PhantomReferent<T> {
191        PhantomReferent(self.ptr)
192    }
193}
194
195impl<T: ?Sized> Deref for CppRef<'_, T> {
196    type Target = *const T;
197    #[inline]
198    fn deref(&self) -> &Self::Target {
199        // With `inline_const` we can simplify this to:
200        // const { panic!("you shouldn't deref CppRef!") }
201        struct C<T: ?Sized>(T);
202        impl<T: ?Sized> C<T> {
203            const V: core::convert::Infallible = panic!(
204                "You cannot directly obtain a Rust reference from a CppRef. Use CppRef::as_ref."
205            );
206        }
207        match C::<T>::V {}
208    }
209}
210
211impl<T: ?Sized> Clone for CppRef<'_, T> {
212    fn clone(&self) -> Self {
213        Self {
214            ptr: self.ptr,
215            phantom: self.phantom,
216        }
217    }
218}
219
220#[cfg(nightly)]
221impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<CppRef<'_, U>> for CppRef<'_, T> {}
222
223/// A C++ non-const reference. These are different from Rust's `&mut T` in that
224/// several C++ references can exist to the same underlying data ("aliasing")
225/// and that's not permitted for regular Rust references.
226///
227/// See [`CppRef`] for details on safety, usage models and implementation.
228///
229/// You can convert this to a [`CppRef`] using the [`std::convert::Into`] trait.
230#[repr(transparent)]
231pub struct CppMutRef<'a, T: ?Sized> {
232    ptr: *mut T,
233    phantom: PhantomData<&'a mut T>,
234}
235
236impl<T: ?Sized> CppMutRef<'_, T> {
237    /// Retrieve the underlying C++ pointer.
238    pub fn as_mut_ptr(&self) -> *mut T {
239        self.ptr
240    }
241
242    /// Get a regular Rust mutable reference out of this C++ reference.
243    ///
244    /// # Safety
245    ///
246    /// Callers must guarantee that the referent is not modified by any other
247    /// C++ or Rust code while the returned reference exists. Callers must
248    /// also guarantee that no other Rust reference is created to the referent
249    /// while the returned reference exists.
250    ///
251    /// Callers must also be sure that the C++ reference is properly
252    /// aligned, not null, pointing to valid data, etc.
253    pub unsafe fn as_mut(&mut self) -> &mut T {
254        &mut *self.as_mut_ptr()
255    }
256
257    /// Create a C++ reference from a raw pointer.
258    pub fn from_ptr(ptr: *mut T) -> Self {
259        Self {
260            ptr,
261            phantom: PhantomData,
262        }
263    }
264
265    /// Extend the lifetime of the returned reference beyond normal Rust
266    /// borrow checker rules. See [`CppRef::lifetime_cast`].
267    pub fn lifetime_cast(&mut self) -> PhantomReferentMut<T> {
268        PhantomReferentMut(self.ptr)
269    }
270}
271
272impl<T: ?Sized> Deref for CppMutRef<'_, T> {
273    type Target = *const T;
274    #[inline]
275    fn deref(&self) -> &Self::Target {
276        // With `inline_const` we can simplify this to:
277        // const { panic!("you shouldn't deref CppRef!") }
278        struct C<T: ?Sized>(T);
279        impl<T: ?Sized> C<T> {
280            const V: core::convert::Infallible = panic!("You cannot directly obtain a Rust reference from a CppMutRef. Use CppMutRef::as_mut.");
281        }
282        match C::<T>::V {}
283    }
284}
285
286impl<T: ?Sized> Clone for CppMutRef<'_, T> {
287    fn clone(&self) -> Self {
288        Self {
289            ptr: self.ptr,
290            phantom: self.phantom,
291        }
292    }
293}
294
295impl<'a, T> From<CppMutRef<'a, T>> for CppRef<'a, T> {
296    fn from(mutable: CppMutRef<'a, T>) -> Self {
297        Self {
298            ptr: mutable.ptr,
299            phantom: PhantomData,
300        }
301    }
302}
303
304#[cfg(nightly)]
305impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<CppMutRef<'_, U>> for CppMutRef<'_, T> {}
306
307/// Any type which can return a C++ reference to its contents.
308pub trait AsCppRef<T: ?Sized> {
309    /// Returns a reference which obeys C++ reference semantics
310    fn as_cpp_ref(&self) -> CppRef<T>;
311}
312
313/// Any type which can return a C++ reference to its contents.
314pub trait AsCppMutRef<T: ?Sized>: AsCppRef<T> {
315    /// Returns a mutable reference which obeys C++ reference semantics
316    fn as_cpp_mut_ref(&mut self) -> CppMutRef<T>;
317}
318
319impl<T: ?Sized> AsCppRef<T> for CppMutRef<'_, T> {
320    fn as_cpp_ref(&self) -> CppRef<T> {
321        CppRef::from_ptr(self.ptr)
322    }
323}
324
325/// Workaround for the inability to use std::ptr::addr_of! on the contents
326/// of a box.
327#[repr(transparent)]
328struct CppPinContents<T: ?Sized>(T);
329
330impl<T: ?Sized> CppPinContents<T> {
331    fn addr_of(&self) -> *const T {
332        std::ptr::addr_of!(self.0)
333    }
334    fn addr_of_mut(&mut self) -> *mut T {
335        std::ptr::addr_of_mut!(self.0)
336    }
337}
338
339/// A newtype wrapper which causes the contained object to obey C++ reference
340/// semantics rather than Rust reference semantics. That is, multiple aliasing
341/// mutable C++ references may exist to the contents.
342///
343/// C++ references are permitted to alias one another, and commonly do.
344/// Rust references must alias according only to the narrow rules of the
345/// borrow checker.
346///
347/// If you need C++ to access your Rust object, first imprison it in one of these
348/// objects, then use [`Self::as_cpp_ref`] to obtain C++ references to it.
349/// If you need the object back for use in the Rust domain, use [`CppPin::extract`],
350/// but be aware of the safety invariants that you - as a human - will need
351/// to guarantee.
352///
353/// # Usage models
354///
355/// From fairly safe to fairly unsafe:
356///
357/// * *Configure a thing in Rust then give it to C++*. Take your Rust object,
358///   set it up freely using Rust references, methods and data, then imprison
359///   it in a `CppPin` and keep it around while you work with it in C++.
360///   There is no possibility of _aliasing_ UB in this usage model, but you
361///   still need to be careful of use-after-free bugs, just as if you were
362///   to create a reference to any data in C++. The Rust borrow checker will
363///   help you a little by ensuring that your `CppRef` objects don't outlive
364///   the `CppPin`, but once those references pass into C++, it can't help.
365/// * *Pass a thing to C++, have it operate on it synchronously, then take
366///   it back*. To do this, you'd imprison your Rust object in a `CppPin`,
367///   then pass mutable C++ references (using [`AsCppMutRef::as_cpp_mut_ref`])
368///   into a C++ function. C++ would duly operate on the object, and thereafter
369///   you could reclaim the object with `extract()`. At this point, you (as
370///   a human) will need to give a guarantee that no references remain in the
371///   C++ domain. If your object was just locally used by a single C++ function,
372///   which has now returned, this type of local analysis may well be practical.
373/// * *Share a thing between Rust and C++*. This object can vend both C++
374///   references and Rust references (via `as_ref` etc.) It may be possible
375///   for you to guarantee that C++ does not mutate the object while any Rust
376///   reference exists. If you choose this model, you'll need to carefully
377///   track exactly what happens to references and pointers on both sides,
378///   and document your evidence for why you are sure this is safe.
379///   Failure here is bad: Rust makes all sorts of optimization decisions based
380///   upon its borrow checker guarantees, so mistakes can lead to undebuggable
381///   action-at-a-distance crashes.
382///
383/// # See also
384///
385/// See also [`CppUniquePtrPin`], which is equivalent for data which is in
386/// a [`cxx::UniquePtr`].
387pub struct CppPin<T: ?Sized>(Box<CppPinContents<T>>);
388
389impl<T: ?Sized> CppPin<T> {
390    /// Imprison the Rust data within a `CppPin`. This eliminates any remaining
391    /// Rust references (since we take the item by value) and this object
392    /// subsequently only vends C++ style references, not Rust references,
393    /// until or unless `extract` is called.
394    pub fn new(item: T) -> Self
395    where
396        T: Sized,
397    {
398        Self(Box::new(CppPinContents(item)))
399    }
400
401    /// Imprison the boxed Rust data within a `CppPin`. This eliminates any remaining
402    /// Rust references (since we take the item by value) and this object
403    /// subsequently only vends C++ style references, not Rust references,
404    /// until or unless `extract` is called.
405    ///
406    /// If the item is already in a `Box`, this is slightly more efficient than
407    /// `new` because it will avoid moving/reallocating it.
408    pub fn from_box(item: Box<T>) -> Self {
409        // Safety: CppPinContents<T> is #[repr(transparent)] so
410        // this transmute from
411        //   Box<T>
412        // to
413        //   Box<CppPinContents<T>>
414        // is safe.
415        let contents = unsafe { std::mem::transmute::<Box<T>, Box<CppPinContents<T>>>(item) };
416        Self(contents)
417    }
418
419    // Imprison the boxed Rust data within a `CppPin`.  This eliminates any remaining
420    /// Rust references (since we take the item by value) and this object
421    /// subsequently only vends C++ style references, not Rust references,
422    /// until or unless `extract` is called.
423    ///
424    /// If the item is already in a `Box`, this is slightly more efficient than
425    /// `new` because it will avoid moving/reallocating it.
426    pub fn from_pinned_box(item: Pin<Box<T>>) -> Self {
427        // Safety: it's OK to un-pin the Box because we'll be putting it
428        // into a CppPin which upholds the same pinned-ness contract.
429        Self::from_box(unsafe { Pin::into_inner_unchecked(item) })
430    }
431
432    /// Get an immutable pointer to the underlying object.
433    pub fn as_ptr(&self) -> *const T {
434        self.0.addr_of()
435    }
436
437    /// Get a mutable pointer to the underlying object.
438    pub fn as_mut_ptr(&mut self) -> *mut T {
439        self.0.addr_of_mut()
440    }
441
442    /// Get a normal Rust reference to the underlying object. This is unsafe.
443    ///
444    /// # Safety
445    ///
446    /// You must guarantee that C++ will not mutate the object while the
447    /// reference exists.
448    pub unsafe fn as_ref(&self) -> &T {
449        &*self.as_ptr()
450    }
451
452    /// Get a normal Rust mutable reference to the underlying object. This is unsafe.
453    ///
454    /// # Safety
455    ///
456    /// You must guarantee that C++ will not mutate the object while the
457    /// reference exists.
458    pub unsafe fn as_mut(&mut self) -> &mut T {
459        &mut *self.as_mut_ptr()
460    }
461
462    /// Extract the object from within its prison, for re-use again within
463    /// the domain of normal Rust references.
464    ///
465    /// This returns a `Box<T>`: if you want the underlying `T` you can extract
466    /// it using `*`.
467    ///
468    /// # Safety
469    ///
470    /// Callers promise that no remaining C++ references exist either
471    /// in the form of Rust [`CppRef`]/[`CppMutRef`] or any remaining pointers/
472    /// references within C++.
473    pub unsafe fn extract(self) -> Box<T> {
474        // Safety: CppPinContents<T> is #[repr(transparent)] so
475        // this transmute from
476        //   Box<CppPinContents<T>>
477        // to
478        //   Box<T>
479        // is safe.
480        std::mem::transmute(self.0)
481    }
482}
483
484impl<T: ?Sized> AsCppRef<T> for CppPin<T> {
485    fn as_cpp_ref(&self) -> CppRef<T> {
486        CppRef::from_ptr(self.as_ptr())
487    }
488}
489
490impl<T: ?Sized> AsCppMutRef<T> for CppPin<T> {
491    fn as_cpp_mut_ref(&mut self) -> CppMutRef<T> {
492        CppMutRef::from_ptr(self.as_mut_ptr())
493    }
494}
495
496/// Any newtype wrapper which causes the contained [`UniquePtr`] target to obey C++ reference
497/// semantics rather than Rust reference semantics. That is, multiple aliasing
498/// mutable C++ references may exist to the contents.
499///
500/// C++ references are permitted to alias one another, and commonly do.
501/// Rust references must alias according only to the narrow rules of the
502/// borrow checker.
503pub struct CppUniquePtrPin<T: UniquePtrTarget>(UniquePtr<T>);
504
505impl<T: UniquePtrTarget> CppUniquePtrPin<T> {
506    /// Imprison the type within a `CppPin`. This eliminates any remaining
507    /// Rust references (since we take the item by value) and this object
508    /// subsequently only vends C++ style references, not Rust references.
509    pub fn new(item: UniquePtr<T>) -> Self {
510        Self(item)
511    }
512
513    /// Get an immutable pointer to the underlying object.
514    pub fn as_ptr(&self) -> *const T {
515        // TODO - avoid brief reference here
516        self.0
517            .as_ref()
518            .expect("UniquePtr was null; we can't make a C++ reference")
519    }
520}
521
522impl<T: UniquePtrTarget> AsCppRef<T> for CppUniquePtrPin<T> {
523    fn as_cpp_ref(&self) -> CppRef<T> {
524        CppRef::from_ptr(self.as_ptr())
525    }
526}
527
528impl<T: UniquePtrTarget> AsCppMutRef<T> for CppUniquePtrPin<T> {
529    fn as_cpp_mut_ref(&mut self) -> CppMutRef<T> {
530        let pinnned_ref: Pin<&mut T> = self
531            .0
532            .as_mut()
533            .expect("UniquePtr was null; we can't make a C++ reference");
534        let ptr = unsafe { Pin::into_inner_unchecked(pinnned_ref) };
535        CppMutRef::from_ptr(ptr)
536    }
537}
538
539/// A structure used to extend the lifetime of a returned C++ reference,
540/// to indicate to Rust that it's beyond the normal Rust lifetime rules.
541/// See [`CppRef::lifetime_cast`].
542#[repr(transparent)]
543pub struct PhantomReferent<T: ?Sized>(*const T);
544
545impl<T: ?Sized> AsCppRef<T> for PhantomReferent<T> {
546    fn as_cpp_ref(&self) -> CppRef<T> {
547        CppRef::from_ptr(self.0)
548    }
549}
550
551/// A structure used to extend the lifetime of a returned C++ mutable reference,
552/// to indicate to Rust that it's beyond the normal Rust lifetime rules.
553/// See [`CppRef::lifetime_cast`].
554#[repr(transparent)]
555pub struct PhantomReferentMut<T: ?Sized>(*mut T);
556
557impl<T: ?Sized> AsCppRef<T> for PhantomReferentMut<T> {
558    fn as_cpp_ref(&self) -> CppRef<T> {
559        CppRef::from_ptr(self.0)
560    }
561}
562
563impl<T: ?Sized> AsCppMutRef<T> for PhantomReferentMut<T> {
564    fn as_cpp_mut_ref(&mut self) -> CppMutRef<T> {
565        CppMutRef::from_ptr(self.0)
566    }
567}
568
569#[cfg(all(feature = "arbitrary_self_types_pointers", test))]
570mod tests {
571    use super::*;
572
573    struct CppOuter {
574        _a: u32,
575        inner: CppInner,
576        global: *const CppInner,
577    }
578
579    impl CppOuter {
580        fn get_inner_ref<'a>(self: &CppRef<'a, CppOuter>) -> CppRef<'a, CppInner> {
581            // Safety: emulating C++ code for test purposes. This is safe
582            // because we know the data isn't modified during the lifetime of
583            // the returned reference.
584            let self_rust_ref = unsafe { self.as_ref() };
585            CppRef::from_ptr(std::ptr::addr_of!(self_rust_ref.inner))
586        }
587        fn get_global_ref<'a>(self: &CppRef<'a, CppOuter>) -> CppRef<'a, CppInner> {
588            // Safety: emulating C++ code for test purposes. This is safe
589            // because we know the data isn't modified during the lifetime of
590            // the returned reference.
591            let self_rust_ref = unsafe { self.as_ref() };
592            CppRef::from_ptr(self_rust_ref.global)
593        }
594    }
595
596    struct CppInner {
597        b: u32,
598    }
599
600    impl CppInner {
601        fn value_is(self: &CppRef<Self>) -> u32 {
602            // Safety: emulating C++ code for test purposes. This is safe
603            // because we know the data isn't modified during the lifetime of
604            // the returned reference.
605            let self_rust_ref = unsafe { self.as_ref() };
606            self_rust_ref.b
607        }
608    }
609
610    #[test]
611    fn cpp_objects() {
612        let mut global = CppInner { b: 7 };
613        let global_ref_lifetime_phantom;
614        {
615            let outer = CppOuter {
616                _a: 12,
617                inner: CppInner { b: 3 },
618                global: &mut global,
619            };
620            let outer = CppPin::new(outer);
621            let inner_ref = outer.as_cpp_ref().get_inner_ref();
622            assert_eq!(inner_ref.value_is(), 3);
623            global_ref_lifetime_phantom = Some(outer.as_cpp_ref().get_global_ref().lifetime_cast());
624        }
625        let global_ref = global_ref_lifetime_phantom.unwrap();
626        let global_ref = global_ref.as_cpp_ref();
627        assert_eq!(global_ref.value_is(), 7);
628    }
629
630    #[test]
631    fn cpp_pin() {
632        let a = RustThing { _a: 4 };
633        let a = CppPin::new(a);
634        let _ = a.as_cpp_ref();
635        let _ = a.as_cpp_ref();
636    }
637}