Squashed 'third_party/autocxx/' changes from c35090b75..fdfb26e26

fdfb26e26 Merge pull request #1315 from google/update-for-proc-macro-prob
ed6ab7560 cargo update
bfca1e046 Merge pull request #1310 from google/remove-errant-line
b06647b89 Remove commented Cargo line
dfb63e2fa Merge pull request #1309 from google/syn-newtype-wrapper-3
c3cdbcbe3 Newtype wrapper for more concise syn debug output.
2743df8f7 Merge pull request #1306 from google/more-cpp-version-notes-tests
1b68eb0b9 Further documentation on C++ versions.
907b2eff3 Merge pull request #1305 from google/cpp-version-notes
90a17d9c2 Documentation about C++ versions.
60230d257 Merge pull request #1299 from google/rev-0.26
10346e838 Revise to 0.26.
5492cb25f Merge pull request #1297 from google/dyn-trait-test
ad8fd562f Merge pull request #1298 from google/fix-moveit-unsoundness
3ff66d1c2 Use new trait in tests.
2f8fb49f9 Fix subclass Emplace trait name.
e420eb7b4 Merge commit '93ed457' into fix-moveit-unsoundness
5e863df88 Roll to moveit 0.6.
0386ad9c8 Testing and documenting dynamic dispatch for CppRef.
ad9377beb Merge pull request #1274 from google/test-for-1265
84281f824 Merge pull request #1296 from google/fix-mutable-refs-part-two
21d72ad05 Fix mutable ref returns, part two.
cfbe62b08 Merge pull request #1295 from google/fix-1294
a67fbe6a6 Fix reference wrappers + mutable refs problem.
366d1a32b Merge pull request #1293 from google/roll-bindgen-2
8cacf99c2 Ignore new test so it can be merged in.
b9a56c697 Absorb published autocxx-bindgen 0.65.1.
1bfbf9dcc Merge pull request #1292 from google/reference-wrapper-changes
7000c91e6 Upgrade to bindgen 0.65.1.
d35bdbd59 Fix doc problem.
43d94cf1f Remove unused features.
ebf858266 Improve reference wrapper example.
e0dfbf958 Allow unsized types in C++ references.
004ef5ab9 Add comments to C++ reference
7c8b8c0f6 Add comment on potential lurking bug.
902077adc Switch reference wrappers' Deref
6ee12660a Merge pull request #1286 from maurer/syn-2
2633a9aaf Update to syn-2
6cb6d5879 Merge pull request #1291 from badicsalex/main
718c50d30 Crude workaround for nested anonymous enums bug
b1ee9dae5 Add test for nested anonymous enums
cf123189e Merge pull request #1290 from google/adetaylor-patch-2
0c27dcb18 Update bug_report.md
73cf4798b Update issue templates
cce6f6c5d Merge pull request #1288 from google/clippy-1.70
b43a16e59 Clippy fix.
93ed45714 Simplify generics
7e6fc4982 Remove `moveit::EmplaceUnpinned`
2113daf76 Make `as_mov` take `ptr: impl AsMove<P>` and relax bound to `P: Deref`
2e442110d Patch moveit dependency
ad69a8417 Merge pull request #1284 from google/cargo-update-2
776bc8162 Merge pull request #1283 from google/subclass-diagnostics
70f9f0f7e cargo update to remove vulnerable version of time.
25c0ded71 Further book fixes.
f8749c71c Book fixes.
fee4442cf Fix diagnostics for in-line subclass macro.
ae4a4eeeb Merge pull request #1277 from gen-xu/main
02ba1a54e fix: feature flag for runtime
e397e2e71 Merge branch 'main' into test-for-1265
bec2301b5 Merge pull request #1264 from google/reject-unions
b0275ff0f Merge pull request #1275 from google/typo3
370e81d87 Fix typo.
f050f5ae7 Add test for unsoundness.
a44f39806 Format
deba33de8 Further tweaks
994a0b164 Merge pull request #1273 from google/rvalueparamhandler-comment
7b8b14507 More using nuance.
e9a62b429 Merge pull request #1272 from google/1270
98fcc88a8 Add comment explaining RValueParamHandler.
d93a1fd1c Attempts at fixing 1270.
6594410d4 Use a more sophisticated 'using' statement.
abb59541f Merge pull request #1263 from google/va-list
1f9a1d258 Attempt to fix namespaced anon struct case.
d4ad6fecc Add test for funsigned-char
f27bf7856 Add va_list test.
7f38ae7c9 Shorten excessively long name.
f4e57eaed Fix namespaced destructors.
ada12160e Merge pull request #1259 from google/fix-remove-dir-all
edabf36f1 Merge pull request #1258 from google/rev-0.25
8c7452b68 Roll tempfile.
22515641f Revise to 0.25.0.
9f5c550c5 Merge pull request #1257 from htynkn/patch-1
7c724ba32 Update examples.md
97c103aaa Update examples.md
a9edb13c5 fix 404 in examples document
c3771d02d Merge pull request #1253 from nak3/add-cxx.h
b429077f8 Merge pull request #1249 from google/reduction-tweaks
143b2944f Merge pull request #1254 from google/issue-1238
94f0cd51b Reject fns returning mut refs but no mut ref param
e7640d2dd Add failing test case for issue 1238.
0f1a28a28 Tweaks to reduction
252608fb4 Add an option to autocxx_gen to create cxx.h
79c72939e Merge pull request #1250 from google/tests-forcing-wrappers
2121c1a30 Disable the two tests which fail when wrappers are forced.
52028c9a2 Add to book about this.
4359edcf3 Clippy fix.
c34ae5e6d Add github workflow.
dca93fa74 Add to test suite
e20192af4 Add option to force wrapper generation.
5540b8618 Merge pull request #1206 from russelltg/construct_concrete_class
1783da369 Merge pull request #1248 from nak3/llvm-example
a1468090a Merge pull request #1247 from nak3/fix-log
9154d3187 Merge pull request #1245 from nak3/use-subclass
d24515a90 Enable llvm example for CI
36f7a3570 Print the number of files generated in the error of `--generate-exact`
faf3d8202 Do not use deprecated annotation is_subclass in examples
a303a9a72 fmt
e47ff2eff Merge pull request #1241 from google/reproduce-1237
8db3a4241 Fix problem with nested extern types.
20345ebbb Merge pull request #1242 from google/remove-no-mod-found-error
83cec3c50 Clippy fix.
d0e1b23e3 Merge pull request #1240 from google/fix-1229
88e702523 Support extern_rust_type without include_cpp!
6a429bd62 Add test for autodiscover without include_cpp
3bd7dba80 Fix use of extern_rust_type in Box<T> in wrappers.
68c236afb Rename a test to avoid ambiguity.
93e4c9629 Remove warning from test case.
68d2323c5 Fix for Box being passed without std::move.
ba81127ca Add reproduction test for #1237
ca436170e Experimental fix for #1229
59eaac153 Merge pull request #1224 from kitlith/no_std
05c0071a0 Move duplicate Pin definition into "non_cannonical_name"
14eeb91db Merge pull request #1232 from nak3/fix-comment
047943e22 Merge pull request #1234 from nak3/fix-help
31ccc891e Merge branch 'google:main' into test
cb16073c3 Add test for issue #1229
c7b6af021 Make help message of gen-rs-include accurate
9c359b4cc Fix comment about AUTOCXX_RS_JSON_ARCHIVE
8a5e11574 Merge remote-tracking branch 'origin/main' into construct_concrete_class
0b46f92ce go through APIs one final time to go through methods before classes
dcb4de8ba Merge pull request #1225 from EmbarkStudios/main
74a78bd16 FIXUP! cargo fmt
b579e7cde Merge pull request #1227 from google/linking-docs
29c267f4f Add some generic advice about linking.
6e1200d3a Merge pull request #1226 from google/remove-publish-delay
70b2d2b43 Cargo publish now waits automatically.
21a007020 Merge pull request #1223 from google/test-for-1214
a6ffcc103 Merge branch 'main' of github.com:google/autocxx into test-for-1214
788816f30 Format.
8935e64bd Revise to fixed autocxx-bindgen version.
e0da33972 Furthger enhance test.
88641ff57 Slightly bolstering an existing test.
2e4318803 Automatically create outdir if it doesn't exist
ad89df311 when adding a lifetime to pinned reference, allow from core as well.
6a09a1d1c Replace std with core (where possible) in integration tests.
abed8eabe s/::std/::core/, where possible
a3ab76cd7 Merge pull request #1222 from google/rev-0.24
21995a555 Add test for #1214.
1100f09f4 Format.
6c252fad2 More clippy changes.
6c3d25c09 Revise to 0.24.0
9e69fae2d Merge pull request #1193 from google/test-1192
4400acf2a Merge pull request #1221 from google/document-expectations
4d6f80303 Add comments towards #1192.
bde880b67 Merge pull request #1220 from google/repro-1197
aef43a1b8 Merge pull request #1217 from google/add_doc_cfg
c1102a73b Merge pull request #1218 from google/improve-diagnostic
0e8dd146b Merge pull request #1219 from google/no-rewrite
8cd277b4b Make cxxgen.h names predictable in autocxx-build.
e5898442c Fix doc build issue.
7433ac6a5 Improve diagnostics for wrong filename. Fixes #1200.
ae9181f43 Avoid unnecessary rebuilds.
b3748f736 Merge pull request #1216 from google/clippy-new
6a9d9227b Format.
c90cd896e address some comments
ef6dfd9ac Latest clippy fixes.
e28826e00 Clippy
103ce3f9e Merge pull request #1203 from aaronrsiphone/patch-1
2db6e7341 Merge pull request #1210 from nak3/remove-memory
eb486273a Merge pull request #1208 from nak3/fix-cpp_calling_rust
4d831b6a5 Merge pull request #1209 from nak3/fix-typo
316e63643 Merge pull request #1213 from nak3/bump-llvm
495e90916 Bump autocxx version in examples/llvm
49ba02805 Remove unnecessary memory include
fd728b20f Fix typo
acc14b9b6 Add test in github action
5def9b050 Bump miette to 5.x
8d4d785f4 clippy
e1d172f4a fmt
38f26efcc add missing trait
12bf667d1 listen to clippy
f6829c226 fix up overload resolution
d2aa27715 some more work
910e7b5f6 get started
b7a23c5d0 Merge pull request #1202 from google/reference-tweak
eb4b28d5b Update building.md
a476df3e5 Add a note about unsafety of reference wrappers.
34a143f12 Merge pull request #1199 from google/clippy-fixes
4b6020f7c Fix new cargo doc error.
c132a0180 Clippy fixes.
bd0efed70 Fix issue 1192.
81a3d9686 Log some more details of some APIs.
a7c4d35dd Fix the test
16c8a7059 Add test for issue 1192.
f6427a110 Merge pull request #1188 from google/rev-0.23.1
f5ea8a674 Revise to 0.23.1
1c11f4b78 Merge pull request #1187 from google/recursive-struct-fields
f68e08d21 Denote only dependencies of real field types.
a009d0f86 Add tests for circular dependencies.
034e10432 Merge pull request #1185 from google/rev-0.23
05a5c4243 Revise to 0.23.0.
0885061f4 Merge pull request #1180 from google/fix-815
1ee6da4c2 Merge branch 'main' of github.com:google/autocxx into fix-815
b00c5cd17 Merge pull request #1184 from google/nightly-clippies
74dadfb26 Further clippy fixes.
f81c4db3c Further clippy fixes.
d0c5616a2 Shrink error types to keep clippy happy.
5cae78b3d Merge branch 'main' of github.com:google/autocxx into fix-815
68d280b3c Merge pull request #1183 from google/merge-bindgen-upstream-0.62
8aed5e309 Update to released autocxx-bindgen.
59da591a0 Merge pull request #1179 from google/failing-1170-test
65dd0e218 Format.
775317a85 Cargo lock
f052bbdd7 Test against upstream bindgen 0.62.
a19307aa8 Depend on custom bindgen branch
162ec7df8 Remove bogus bits of test
29296ee9c Consider that enums are always movable/destroyable.
4eab29a29 Properly propagate deps for non-POD structs
04eab3251 Simpler test for #1170.
66ca18c78 Record defaulted attributes - no intentional changes yet
3ad39ce5c Failing test for derived class.
f3a803040 Test for explicitly defaulted constructors.
782d1365f Adding failing test for #1170.
6cca9b29c Merge pull request #1172 from google/reduce-with-rustc
9d021f66f Typo.
ee2bdf87f Merge pull request #1176 from google/rustversion-swap
3b28ff920 Fix nightly check error.
1cdbcc964 Clippy complaint.
bc5f4ff05 Compile generated rust code during reduction.
5ef057dce Merge pull request #1173 from google/up-of-vecs
9577311aa Update integration-tests/tests/cpprefs_test.rs
1cb8338a1 Eliminate further use of rustc_version.
e78b73b1c Remove dependency on rustc_version.
1b949ad9c Fix test.
20c8d6ba7 Merge pull request #1175 from google/1152-upmerge
8f2dbaef0 Fix compatibility with clap 3.2.
dda51d028 Merge branch 'main' of github.com:google/autocxx into 1152-upmerge
3086a9023 Merge pull request #1168 from google/extern_rust_fun_type_checking
14f224fde Merge pull request #1171 from google/reduce-quicker
fbeb0f3d6 Adding a test.
ea57ea7d7 Slight reduction speedup.
26f9cf4a2 extern_rust_function types: diagnostics
1196c39b1 Rename: ConvertError -> ConvertErrorFromCpp
759970ae6 Merge pull request #1164 from google/cppref-changes
cb9c680b2 Adding diagnostics for use on non-nightly.
93657b848 Add failing test for extern_rust_function
075bd8e79 Switch from receiver feature to arbitrary_self_types
8c576081d Fix tests for nightly.
51e4c271c Doc fixes.
1204dc7fa Rewrite reference_wrapper.rs to be structs.
c2846add0 Merge pull request #1163 from google/rev-cxx-1.0.72
4d939f0d5 Merge pull request #1162 from google/fix-1161
3d2767958 Revise cxx to 1.0.78.
cf96537ca Clippy fix.
458384470 Add Box test.
23cff78ca Fix GC problem with extern_rust_type.
b24563627 Merge pull request #1158 from google/issue-1097-partial-fix
1ce2ee335 Merge pull request #1160 from google/clippy-1.64-fix
3d376da55 Rust 1.64 clippy lint.
d01bcece0 Merge pull request #1157 from google/adetaylor-patch-1
bce713bfa Partial fix for issue 1097.
7460bfacb Remove extra logging
2d86cdb4a Merge pull request #1156 from google/fix-1143
e7ca09610 Clippy fix.
4fdb3ca22 Enable test.
40d70634e Fix #1143.
f785a168d Merge pull request #1150 from bsilver8192/extern_cpp_type-different-name
79b6b91df Update deps, format TOML
8d2e1dffb Merge pull request #1154 from google/rev-0.22.4
6555d8212 Revise to 0.22.4.
4b44f7f20 Merge pull request #1153 from google/autocxx-bindgen-0.60.3
05dcbf555 Update autocxx-bindgen and bump version to 0.22.4
2388f2d50 Support `extern_cpp_type!` with a different name
7cfa5ea58 Merge pull request #1149 from google/rev-autocxx-bindgen-0.60.1
dadb77ac5 Use official release version.
25cc290a9 Use specific branch and merge fixes
9d2487fab Revise to autocxx-bindgen 0.60.1.
8a9f5fd6d Merge pull request #1145 from boydjohnson/test-case
9d7d2cbdd Merge pull request #1147 from bsilver8192/multiple-json-archive-paths
948e49c4f Merge pull request #1148 from bsilver8192/1.63.0-warning-fixes
c3c020459 Support multiple AUTOCXX_RS_JSON_ARCHIVE entries
37353fabd Fix new clippy and doc warnings in 1.63.0
1e1d16d73 Add failing test case
d0bc76eb5 Merge pull request #1137 from bsilver8192/impl-abstract-type
ec7a4541a Generate `impl UniquePtr` for abstract types too
b830b9da6 Merge pull request #1139 from bsilver8192/bump-mdbook
da8dbd829 Bump mdbook to fix build on nightly
cdebaee64 Merge pull request #1136 from google/disable-windows-gnu-2
5fcc700c7 Disable windows-gnu tests.
0f8cf6309 Fix a comment.
b60c4d032 Merge pull request #1127 from dtolnay-contrib/prettyplease
8b766bd46 Pretty print using prettyplease instead of rustfmt

Change-Id: I0529fc0c35c16160944f5b3a5326c2d53fbe904b
git-subtree-dir: third_party/autocxx
git-subtree-split: fdfb26e26602e24466dfc506782567deb72c9a29
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/src/lib.rs b/src/lib.rs
index 4b9f26b..fe235a9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,6 @@
 #![doc = include_str!("../README.md")]
+#![cfg_attr(nightly, feature(unsize))]
+#![cfg_attr(nightly, feature(dispatch_from_dyn))]
 
 // Copyright 2020 Google LLC
 //
@@ -19,7 +21,7 @@
 pub mod subclass;
 mod value_param;
 
-pub use reference_wrapper::{CppMutRef, CppPin, CppRef};
+pub use reference_wrapper::{AsCppMutRef, AsCppRef, CppMutRef, CppPin, CppRef, CppUniquePtrPin};
 
 #[cfg_attr(doc, aquamarine::aquamarine)]
 /// Include some C++ headers in your Rust project.
@@ -82,7 +84,7 @@
 ///
 /// * *Recommended*: provide various [`generate`] directives in the
 ///   [`include_cpp`] macro. This can specify functions or types.
-/// * *Not recommended*: in your `build.rs`, call [`Builder::auto_allowlist`].
+/// * *Not recommended*: in your `build.rs`, call `Builder::auto_allowlist`.
 ///   This will attempt to spot _uses_ of FFI bindings anywhere in your Rust code
 ///   and build the allowlist that way. This is experimental and has known limitations.
 /// * *Strongly not recommended*: use [`generate_all`]. This will attempt to
@@ -216,7 +218,7 @@
 
 /// A concrete type to make, for example
 /// `concrete!("Container<Contents>")`.
-/// All types msut already be on the allowlist by having used
+/// All types must already be on the allowlist by having used
 /// `generate!` or similar.
 ///
 /// A directive to be included inside
@@ -265,9 +267,12 @@
 /// policy available here:
 /// `safety!(unsafe_references_wrapped)`
 /// This policy treats C++ references as scary and requires
-/// them to be wrapped in a `CppRef` type. This `CppRef`
-/// type is implemented within the generated bindings but
-/// follows the contract of [`CppRef`].
+/// them to be wrapped in a `CppRef` type: see [`CppRef`].
+/// This only works on nightly Rust because it
+/// depends upon an unstable feature
+/// (`arbitrary_self_types`). However, it should
+/// eliminate all undefined behavior related to Rust's
+/// stricter aliasing rules than C++.
 #[macro_export]
 macro_rules! safety {
     ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
@@ -286,12 +291,43 @@
 
 /// Indicates that a C++ type is not to be generated by autocxx in this case,
 /// but instead should refer to some pre-existing Rust type.
-/// Note that the size and alignment of this type *must* be correct.
-/// If you wish for the type to be POD, you can use a `pod!` directive too.
+///
+/// If you wish for the type to be POD, you can use a `pod!` directive too
+/// (but see the "requirements" section below).
 ///
 /// The syntax is:
 /// `extern_cpp_type!("CppNameGoesHere", path::to::rust::type)`
 ///
+/// Generally speaking, this should be used only to refer to types
+/// generated elsewhere by `autocxx` or `cxx` to ensure that they meet
+/// all the right requirements. It's possible - but fragile - to
+/// define such types yourself.
+///
+/// # Requirements for externally defined Rust types
+///
+/// It's generally expected that you would make such a type
+/// in Rust using a separate `include_cpp!` macro, or
+/// a manual `#[cxx::bridge]` directive somehwere. That is, this
+/// directive is intended mainly for use in cross-linking different
+/// sets of bindings in different mods, rather than truly to point to novel
+/// external types.
+///
+/// But with that in mind, here are the requirements you must stick to.
+///
+/// For non-POD external types:
+/// * The size and alignment of this type *must* be correct.
+///
+/// For POD external types:
+/// * As above
+/// * Your type must correspond to the requirements of
+///   [`cxx::kind::Trivial`]. In general, that means, no move constructor
+///   and no destructor. If you generate this type using `cxx` itself
+///   (or `autocxx`) this will be enforced using `static_assert`s
+///   within the generated C++ code. Without using those tools, you're
+///   on your own for determining this... and it's hard because the presence
+///   of particular fields or base classes may well result in your type
+///   violating those rules.
+///
 /// A directive to be included inside
 /// [include_cpp] - see [include_cpp] for general information.
 #[macro_export]
@@ -495,6 +531,25 @@
     /// for instance. This will contribute to an `extern "Rust"` section of the
     /// generated `cxx` bindings, and this type will appear in the C++ header
     /// generated for use in C++.
+    ///
+    /// # Finding these bindings from C++
+    ///
+    /// You will likely need to forward-declare this type within your C++ headers
+    /// before you can use it in such function signatures. autocxx can't generate
+    /// headers (with this type definition) until it's parsed your header files;
+    /// logically therefore if your header files mention one of these types
+    /// it's impossible for them to see the definition of the type.
+    ///
+    /// If you're using multiple sets of `include_cpp!` directives, or
+    /// a mixture of `include_cpp!` and `#[cxx::bridge]` bindings, then you
+    /// may be able to `#include "cxxgen.h"` to refer to the generated C++
+    /// function prototypes. In this particular circumstance, you'll want to know
+    /// how exactly the `cxxgen.h` header is named, because one will be
+    /// generated for each of the sets of bindings encountered. The pattern
+    /// can be set manually using `autocxxgen`'s command-line options. If you're
+    /// using `autocxx`'s `build.rs` support, those headers will be named
+    /// `cxxgen.h`, `cxxgen1.h`, `cxxgen2.h` according to the order in which
+    /// the `include_cpp` or `cxx::bridge` bindings are encountered.
     pub use autocxx_macro::extern_rust_type;
 
     /// Declare that a given function is a Rust function which is to be exported
@@ -504,6 +559,9 @@
     /// #[extern_rust_function]
     /// pub fn call_me_from_cpp() { }
     /// ```
+    ///
+    /// See [`extern_rust_type`] for details of how to find the generated
+    /// declarations from C++.
     pub use autocxx_macro::extern_rust_function;
 }
 
@@ -519,6 +577,7 @@
 /// and implemented by any (autocxx-related) [`moveit::New`].
 pub trait WithinUniquePtr {
     type Inner: UniquePtrTarget + MakeCppStorage;
+    /// Create this item within a [`cxx::UniquePtr`].
     fn within_unique_ptr(self) -> cxx::UniquePtr<Self::Inner>;
 }
 
@@ -527,13 +586,23 @@
 /// and implemented by any (autocxx-related) [`moveit::New`].
 pub trait WithinBox {
     type Inner;
+    /// Create this item inside a pinned box. This is a good option if you
+    /// want to own this object within Rust, and want to create Rust references
+    /// to it.
     fn within_box(self) -> Pin<Box<Self::Inner>>;
+    /// Create this item inside a [`CppPin`]. This is a good option if you
+    /// want to own this option within Rust, but you want to create [`CppRef`]
+    /// C++ references to it. You'd only want to choose that option if you have
+    /// enabled the C++ reference wrapper support by using the
+    /// `safety!(unsafe_references_wrapped`) directive. If you haven't done
+    /// that, ignore this function.
+    fn within_cpp_pin(self) -> CppPin<Self::Inner>;
 }
 
 use cxx::kind::Trivial;
 use cxx::ExternType;
+use moveit::Emplace;
 use moveit::MakeCppStorage;
-use moveit::{Emplace, EmplaceUnpinned};
 
 impl<N, T> WithinUniquePtr for N
 where
@@ -554,6 +623,9 @@
     fn within_box(self) -> Pin<Box<T>> {
         Box::emplace(self)
     }
+    fn within_cpp_pin(self) -> CppPin<Self::Inner> {
+        CppPin::from_pinned_box(Box::emplace(self))
+    }
 }
 
 /// Emulates the [`WithinUniquePtr`] trait, but for trivial (plain old data) types.
@@ -624,9 +696,12 @@
     pub use crate::c_void;
     pub use crate::cpp_semantics;
     pub use crate::include_cpp;
+    pub use crate::AsCppMutRef;
+    pub use crate::AsCppRef;
     pub use crate::CppMutRef;
     pub use crate::CppPin;
     pub use crate::CppRef;
+    pub use crate::CppUniquePtrPin;
     pub use crate::PinMut;
     pub use crate::RValueParam;
     pub use crate::ValueParam;
@@ -638,7 +713,6 @@
     pub use moveit::moveit;
     pub use moveit::new::New;
     pub use moveit::Emplace;
-    pub use moveit::EmplaceUnpinned;
 }
 
 /// Re-export moveit for ease of consumers.
diff --git a/src/reference_wrapper.rs b/src/reference_wrapper.rs
index ed943d3..041bd72 100644
--- a/src/reference_wrapper.rs
+++ b/src/reference_wrapper.rs
@@ -6,15 +6,124 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use core::{marker::PhantomData, ops::Deref, pin::Pin};
+
+#[cfg(nightly)]
+use std::{marker::Unsize, ops::DispatchFromDyn};
+
+use cxx::{memory::UniquePtrTarget, UniquePtr};
+
 /// A C++ const reference. These are different from Rust's `&T` in that
-/// these may exist even while the object is mutated elsewhere.
+/// these may exist even while the object is mutated elsewhere. See also
+/// [`CppMutRef`] for the mutable equivalent.
 ///
-/// This is a trait not a struct due to the nuances of Rust's orphan rule
-/// - implemntations of this trait are found in each set of generated bindings
-/// but they are essentially the same.
-pub trait CppRef<'a, T> {
+/// The key rule is: we *never* dereference these in Rust. Therefore, any
+/// UB here cannot manifest within Rust, but only across in C++, and therefore
+/// they are equivalently safe to using C++ references in pure-C++ codebases.
+///
+/// *Important*: you might be wondering why you've never encountered this type.
+/// These exist in autocxx-generated bindings only if the `unsafe_references_wrapped`
+/// safety policy is given. This may become the default in future.
+///
+/// # Usage
+///
+/// These types of references are pretty useless in Rust. You can't do
+/// field access. But, you can pass them back into C++! And specifically,
+/// you can call methods on them (i.e. use this type as a `this`). So
+/// the common case here is when C++ gives you a reference to some type,
+/// then you want to call methods on that reference.
+///
+/// # Calling methods
+///
+/// As noted, one of the main reasons for this type is to call methods.
+/// Unfortunately, that depends on unstable Rust features. If you can't
+/// call methods on one of these references, check you're using nightly
+/// and add `#![feature(arbitrary_self_types)]` to your crate.
+///
+/// # Lifetimes and cloneability
+///
+/// Although these references implement C++ aliasing semantics, they
+/// do attempt to give you Rust lifetime tracking. This means if a C++ object
+/// gives you a reference, you won't be able to use that reference after the
+/// C++ object is no longer around.
+///
+/// This is usually what you need, since a C++ object will typically give
+/// you a reference to part of _itself_ or something that it owns. But,
+/// if you know that the returned reference lasts longer than its vendor,
+/// you can use `lifetime_cast` to get a long-lived version.
+///
+/// On the other hand, these references do not give you Rust's exclusivity
+/// guarantees. These references can be freely cloned, and using [`CppRef::const_cast`]
+/// you can even make a mutable reference from an immutable reference.
+///
+/// # Field access
+///
+/// Field access would be achieved by adding C++ `get` and/or `set` methods.
+/// It's possible that a future version of `autocxx` could generate such
+/// getters and setters automatically, but they would need to be `unsafe`
+/// because there is no guarantee that the referent of a `CppRef` is actually
+/// what it's supposed to be, or alive. `CppRef`s may flow from C++ to Rust
+/// via arbitrary means, and with sufficient uses of `get` and `set` it would
+/// even be possible to create a use-after-free in pure Rust code (for instance,
+/// store a [`CppPin`] in a struct field, get a `CppRef` to its referent, then
+/// use a setter to reset that field of the struct.)
+///
+/// # Deref
+///
+/// This type implements [`Deref`] because that's the mechanism that the
+/// unstable Rust `arbitrary_self_types` features uses to determine callable
+/// methods. However, actually calling `Deref::deref` is not permitted and will
+/// result in a compilation failure. If you wish to create a Rust reference
+/// from the C++ reference, see [`CppRef::as_ref`].
+///
+/// # Nullness
+///
+/// Creation of a null C++ reference is undefined behavior (because such
+/// a reference can only be created by dereferencing a null pointer.)
+/// However, in practice, they exist, and we need to be compatible with
+/// pre-existing C++ APIs even if they do naughty things like this.
+/// Therefore this `CppRef` type does allow null values. This is a bit
+/// unfortunate because it means `Option<CppRef<T>>`
+/// occupies more space than `CppRef<T>`.
+///
+/// # Dynamic dispatch
+///
+/// You might wonder if you can do this:
+/// ```ignore
+/// let CppRef<dyn Trait> = ...; // obtain some CppRef<concrete type>
+/// ```
+/// Dynamic dispatch works so long as you're using nightly (we require another
+/// unstable feature, `dispatch_from_dyn`). But we need somewhere to store
+/// the trait object, and `CppRef` isn't it -- a `CppRef` can only store a
+/// simple pointer to something else. So, you need to store the trait object
+/// in a `Box` or similar:
+/// ```ignore
+/// trait SomeTrait {
+///    fn some_method(self: CppRef<Self>)
+/// }
+/// impl SomeTrait for ffi::Concrete {
+///   fn some_method(self: CppRef<Self>) {}
+/// }
+/// let obj: Pin<Box<dyn SomeTrait>> = ffi::Concrete::new().within_box();
+/// let obj = CppPin::from_pinned_box(obj);
+/// farm_area.as_cpp_ref().some_method();
+/// ```
+///
+/// # Implementation notes
+///
+/// Internally, this is represented as a raw pointer in Rust. See the note above
+/// about Nullness for why we don't use [`core::ptr::NonNull`].
+#[repr(transparent)]
+pub struct CppRef<'a, T: ?Sized> {
+    ptr: *const T,
+    phantom: PhantomData<&'a T>,
+}
+
+impl<'a, T: ?Sized> CppRef<'a, T> {
     /// Retrieve the underlying C++ pointer.
-    fn as_ptr(&self) -> *const T;
+    pub fn as_ptr(&self) -> *const T {
+        self.ptr
+    }
 
     /// Get a regular Rust reference out of this C++ reference.
     ///
@@ -24,21 +133,111 @@
     /// C++ or Rust code while the returned reference exists. Callers must
     /// also guarantee that no mutable Rust reference is created to the
     /// referent while the returned reference exists.
-    unsafe fn as_ref(&self) -> &T {
+    ///
+    /// Callers must also be sure that the C++ reference is properly
+    /// aligned, not null, pointing to valid data, etc.
+    pub unsafe fn as_ref(&self) -> &T {
         &*self.as_ptr()
     }
+
+    /// Create a C++ reference from a raw pointer.
+    pub fn from_ptr(ptr: *const T) -> Self {
+        Self {
+            ptr,
+            phantom: PhantomData,
+        }
+    }
+
+    /// Create a mutable version of this reference, roughly equivalent
+    /// to C++ `const_cast`.
+    ///
+    /// The opposite is to use [`AsCppRef::as_cpp_ref`] on a [`CppMutRef`]
+    /// to obtain a [`CppRef`].
+    ///
+    /// # Safety
+    ///
+    /// Because we never dereference a `CppRef` in Rust, this cannot create
+    /// undefined behavior _within Rust_ and is therefore not unsafe. It is
+    /// however generally unwise, just as it is in C++. Use sparingly.
+    pub fn const_cast(&self) -> CppMutRef<'a, T> {
+        CppMutRef {
+            ptr: self.ptr as *mut T,
+            phantom: self.phantom,
+        }
+    }
+
+    /// Extend the lifetime of the returned reference beyond normal Rust
+    /// borrow checker rules.
+    ///
+    /// Normally, a reference can't be used beyond the lifetime of the object
+    /// which gave it to you, but sometimes C++ APIs can return references
+    /// to global or other longer-lived objects. In such a case you should
+    /// use this method to get a longer-lived reference.
+    ///
+    /// # Usage
+    ///
+    /// When you're given a C++ reference and you know its referent is valid
+    /// for a long time, use this method. Store the resulting `PhantomReferent`
+    /// somewhere in Rust with an equivalent lifetime.
+    /// That object can then vend longer-lived `CppRef`s using
+    /// [`AsCppRef::as_cpp_ref`].
+    ///
+    /// # Safety
+    ///
+    /// Because `CppRef`s are never dereferenced in Rust, misuse of this API
+    /// cannot lead to undefined behavior _in Rust_ and is therefore not
+    /// unsafe. Nevertheless this can lead to UB in C++, so use carefully.
+    pub fn lifetime_cast(&self) -> PhantomReferent<T> {
+        PhantomReferent(self.ptr)
+    }
 }
 
+impl<'a, T: ?Sized> Deref for CppRef<'a, T> {
+    type Target = *const T;
+    #[inline]
+    fn deref(&self) -> &Self::Target {
+        // With `inline_const` we can simplify this to:
+        // const { panic!("you shouldn't deref CppRef!") }
+        struct C<T: ?Sized>(T);
+        impl<T: ?Sized> C<T> {
+            const V: core::convert::Infallible = panic!(
+                "You cannot directly obtain a Rust reference from a CppRef. Use CppRef::as_ref."
+            );
+        }
+        match C::<T>::V {}
+    }
+}
+
+impl<'a, T: ?Sized> Clone for CppRef<'a, T> {
+    fn clone(&self) -> Self {
+        Self {
+            ptr: self.ptr,
+            phantom: self.phantom,
+        }
+    }
+}
+
+#[cfg(nightly)]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<CppRef<'_, U>> for CppRef<'_, T> {}
+
 /// A C++ non-const reference. These are different from Rust's `&mut T` in that
 /// several C++ references can exist to the same underlying data ("aliasing")
-/// and that's not permitted in Rust.
+/// and that's not permitted for regular Rust references.
 ///
-/// This is a trait not a struct due to the nuances of Rust's orphan rule
-/// - implemntations of this trait are found in each set of generated bindings
-/// but they are essentially the same.
-pub trait CppMutRef<'a, T>: CppRef<'a, T> {
+/// See [`CppRef`] for details on safety, usage models and implementation.
+///
+/// You can convert this to a [`CppRef`] using the [`std::convert::Into`] trait.
+#[repr(transparent)]
+pub struct CppMutRef<'a, T: ?Sized> {
+    ptr: *mut T,
+    phantom: PhantomData<&'a T>,
+}
+
+impl<'a, T: ?Sized> CppMutRef<'a, T> {
     /// Retrieve the underlying C++ pointer.
-    fn as_mut_ptr(&self) -> *mut T;
+    pub fn as_mut_ptr(&self) -> *mut T {
+        self.ptr
+    }
 
     /// Get a regular Rust mutable reference out of this C++ reference.
     ///
@@ -48,16 +247,98 @@
     /// C++ or Rust code while the returned reference exists. Callers must
     /// also guarantee that no other Rust reference is created to the referent
     /// while the returned reference exists.
-    unsafe fn as_mut(&mut self) -> &mut T {
+    ///
+    /// Callers must also be sure that the C++ reference is properly
+    /// aligned, not null, pointing to valid data, etc.
+    pub unsafe fn as_mut(&mut self) -> &mut T {
         &mut *self.as_mut_ptr()
     }
+
+    /// Create a C++ reference from a raw pointer.
+    pub fn from_ptr(ptr: *mut T) -> Self {
+        Self {
+            ptr,
+            phantom: PhantomData,
+        }
+    }
+
+    /// Extend the lifetime of the returned reference beyond normal Rust
+    /// borrow checker rules. See [`CppRef::lifetime_cast`].
+    pub fn lifetime_cast(&mut self) -> PhantomReferentMut<T> {
+        PhantomReferentMut(self.ptr)
+    }
 }
 
-/// Any newtype wrapper which causes the contained object to obey C++ reference
-/// semantics rather than Rust reference semantics.
-///
-/// The complex generics here are working around the orphan rule - the only
-/// important generic is `T` which is the underlying stored type.
+impl<'a, T: ?Sized> Deref for CppMutRef<'a, T> {
+    type Target = *const T;
+    #[inline]
+    fn deref(&self) -> &Self::Target {
+        // With `inline_const` we can simplify this to:
+        // const { panic!("you shouldn't deref CppRef!") }
+        struct C<T: ?Sized>(T);
+        impl<T: ?Sized> C<T> {
+            const V: core::convert::Infallible = panic!("You cannot directly obtain a Rust reference from a CppMutRef. Use CppMutRef::as_mut.");
+        }
+        match C::<T>::V {}
+    }
+}
+
+impl<'a, T: ?Sized> Clone for CppMutRef<'a, T> {
+    fn clone(&self) -> Self {
+        Self {
+            ptr: self.ptr,
+            phantom: self.phantom,
+        }
+    }
+}
+
+impl<'a, T> From<CppMutRef<'a, T>> for CppRef<'a, T> {
+    fn from(mutable: CppMutRef<'a, T>) -> Self {
+        Self {
+            ptr: mutable.ptr,
+            phantom: mutable.phantom,
+        }
+    }
+}
+
+#[cfg(nightly)]
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<CppMutRef<'_, U>> for CppMutRef<'_, T> {}
+
+/// Any type which can return a C++ reference to its contents.
+pub trait AsCppRef<T: ?Sized> {
+    /// Returns a reference which obeys C++ reference semantics
+    fn as_cpp_ref(&self) -> CppRef<T>;
+}
+
+/// Any type which can return a C++ reference to its contents.
+pub trait AsCppMutRef<T: ?Sized>: AsCppRef<T> {
+    /// Returns a mutable reference which obeys C++ reference semantics
+    fn as_cpp_mut_ref(&mut self) -> CppMutRef<T>;
+}
+
+impl<'a, T: ?Sized> AsCppRef<T> for CppMutRef<'a, T> {
+    fn as_cpp_ref(&self) -> CppRef<T> {
+        CppRef::from_ptr(self.ptr)
+    }
+}
+
+/// Workaround for the inability to use std::ptr::addr_of! on the contents
+/// of a box.
+#[repr(transparent)]
+struct CppPinContents<T: ?Sized>(T);
+
+impl<T: ?Sized> CppPinContents<T> {
+    fn addr_of(&self) -> *const T {
+        std::ptr::addr_of!(self.0)
+    }
+    fn addr_of_mut(&mut self) -> *mut T {
+        std::ptr::addr_of_mut!(self.0)
+    }
+}
+
+/// A newtype wrapper which causes the contained object to obey C++ reference
+/// semantics rather than Rust reference semantics. That is, multiple aliasing
+/// mutable C++ references may exist to the contents.
 ///
 /// C++ references are permitted to alias one another, and commonly do.
 /// Rust references must alias according only to the narrow rules of the
@@ -65,27 +346,98 @@
 ///
 /// If you need C++ to access your Rust object, first imprison it in one of these
 /// objects, then use [`Self::as_cpp_ref`] to obtain C++ references to it.
-pub trait CppPin<'a, T: 'a> {
-    /// The type of C++ reference created to the contained object.
-    type CppRef: CppRef<'a, T>;
+/// If you need the object back for use in the Rust domain, use [`CppPin::extract`],
+/// but be aware of the safety invariants that you - as a human - will need
+/// to guarantee.
+///
+/// # Usage models
+///
+/// From fairly safe to fairly unsafe:
+///
+/// * *Configure a thing in Rust then give it to C++*. Take your Rust object,
+///   set it up freely using Rust references, methods and data, then imprison
+///   it in a `CppPin` and keep it around while you work with it in C++.
+///   There is no possibility of _aliasing_ UB in this usage model, but you
+///   still need to be careful of use-after-free bugs, just as if you were
+///   to create a reference to any data in C++. The Rust borrow checker will
+///   help you a little by ensuring that your `CppRef` objects don't outlive
+///   the `CppPin`, but once those references pass into C++, it can't help.
+/// * *Pass a thing to C++, have it operate on it synchronously, then take
+///   it back*. To do this, you'd imprison your Rust object in a `CppPin`,
+///   then pass mutable C++ references (using [`AsCppMutRef::as_cpp_mut_ref`])
+///   into a C++ function. C++ would duly operate on the object, and thereafter
+///   you could reclaim the object with `extract()`. At this point, you (as
+///   a human) will need to give a guarantee that no references remain in the
+///   C++ domain. If your object was just locally used by a single C++ function,
+///   which has now returned, this type of local analysis may well be practical.
+/// * *Share a thing between Rust and C++*. This object can vend both C++
+///   references and Rust references (via `as_ref` etc.) It may be possible
+///   for you to guarantee that C++ does not mutate the object while any Rust
+///   reference exists. If you choose this model, you'll need to carefully
+///   track exactly what happens to references and pointers on both sides,
+///   and document your evidence for why you are sure this is safe.
+///   Failure here is bad: Rust makes all sorts of optimization decisions based
+///   upon its borrow checker guarantees, so mistakes can lead to undebuggable
+///   action-at-a-distance crashes.
+///
+/// # See also
+///
+/// See also [`CppUniquePtrPin`], which is equivalent for data which is in
+/// a [`cxx::UniquePtr`].
+pub struct CppPin<T: ?Sized>(Box<CppPinContents<T>>);
 
-    /// The type of C++ mutable reference created to the contained object..
-    type CppMutRef: CppMutRef<'a, T>;
+impl<T: ?Sized> CppPin<T> {
+    /// Imprison the Rust data within a `CppPin`. This eliminates any remaining
+    /// Rust references (since we take the item by value) and this object
+    /// subsequently only vends C++ style references, not Rust references,
+    /// until or unless `extract` is called.
+    pub fn new(item: T) -> Self
+    where
+        T: Sized,
+    {
+        Self(Box::new(CppPinContents(item)))
+    }
+
+    /// Imprison the boxed Rust data within a `CppPin`. This eliminates any remaining
+    /// Rust references (since we take the item by value) and this object
+    /// subsequently only vends C++ style references, not Rust references,
+    /// until or unless `extract` is called.
+    ///
+    /// If the item is already in a `Box`, this is slightly more efficient than
+    /// `new` because it will avoid moving/reallocating it.
+    pub fn from_box(item: Box<T>) -> Self {
+        // Safety: CppPinContents<T> is #[repr(transparent)] so
+        // this transmute from
+        //   Box<T>
+        // to
+        //   Box<CppPinContents<T>>
+        // is safe.
+        let contents = unsafe { std::mem::transmute(item) };
+        Self(contents)
+    }
+
+    // Imprison the boxed Rust data within a `CppPin`.  This eliminates any remaining
+    /// Rust references (since we take the item by value) and this object
+    /// subsequently only vends C++ style references, not Rust references,
+    /// until or unless `extract` is called.
+    ///
+    /// If the item is already in a `Box`, this is slightly more efficient than
+    /// `new` because it will avoid moving/reallocating it.
+    pub fn from_pinned_box(item: Pin<Box<T>>) -> Self {
+        // Safety: it's OK to un-pin the Box because we'll be putting it
+        // into a CppPin which upholds the same pinned-ness contract.
+        Self::from_box(unsafe { Pin::into_inner_unchecked(item) })
+    }
 
     /// Get an immutable pointer to the underlying object.
-    fn as_ptr(&self) -> *const T;
+    pub fn as_ptr(&self) -> *const T {
+        self.0.addr_of()
+    }
 
     /// Get a mutable pointer to the underlying object.
-    fn as_mut_ptr(&mut self) -> *mut T;
-
-    /// Returns a reference which obeys C++ reference semantics
-    fn as_cpp_ref(&self) -> Self::CppRef;
-
-    /// Returns a mutable reference which obeys C++ reference semantics.
-    ///
-    /// Note that this requires unique ownership of `self`, but this is
-    /// advisory since the resulting reference can be cloned.
-    fn as_cpp_mut_ref(&mut self) -> Self::CppMutRef;
+    pub fn as_mut_ptr(&mut self) -> *mut T {
+        self.0.addr_of_mut()
+    }
 
     /// Get a normal Rust reference to the underlying object. This is unsafe.
     ///
@@ -93,7 +445,7 @@
     ///
     /// You must guarantee that C++ will not mutate the object while the
     /// reference exists.
-    unsafe fn as_ref(&self) -> &T {
+    pub unsafe fn as_ref(&self) -> &T {
         &*self.as_ptr()
     }
 
@@ -103,7 +455,183 @@
     ///
     /// You must guarantee that C++ will not mutate the object while the
     /// reference exists.
-    unsafe fn as_mut(&mut self) -> &mut T {
+    pub unsafe fn as_mut(&mut self) -> &mut T {
         &mut *self.as_mut_ptr()
     }
+
+    /// Extract the object from within its prison, for re-use again within
+    /// the domain of normal Rust references.
+    ///
+    /// This returns a `Box<T>`: if you want the underlying `T` you can extract
+    /// it using `*`.
+    ///
+    /// # Safety
+    ///
+    /// Callers promise that no remaining C++ references exist either
+    /// in the form of Rust [`CppRef`]/[`CppMutRef`] or any remaining pointers/
+    /// references within C++.
+    pub unsafe fn extract(self) -> Box<T> {
+        // Safety: CppPinContents<T> is #[repr(transparent)] so
+        // this transmute from
+        //   Box<CppPinContents<T>>
+        // to
+        //   Box<T>
+        // is safe.
+        std::mem::transmute(self.0)
+    }
+}
+
+impl<T: ?Sized> AsCppRef<T> for CppPin<T> {
+    fn as_cpp_ref(&self) -> CppRef<T> {
+        CppRef::from_ptr(self.as_ptr())
+    }
+}
+
+impl<T: ?Sized> AsCppMutRef<T> for CppPin<T> {
+    fn as_cpp_mut_ref(&mut self) -> CppMutRef<T> {
+        CppMutRef::from_ptr(self.as_mut_ptr())
+    }
+}
+
+/// Any newtype wrapper which causes the contained [`UniquePtr`] target to obey C++ reference
+/// semantics rather than Rust reference semantics. That is, multiple aliasing
+/// mutable C++ references may exist to the contents.
+///
+/// C++ references are permitted to alias one another, and commonly do.
+/// Rust references must alias according only to the narrow rules of the
+/// borrow checker.
+pub struct CppUniquePtrPin<T: UniquePtrTarget>(UniquePtr<T>);
+
+impl<T: UniquePtrTarget> CppUniquePtrPin<T> {
+    /// Imprison the type within a `CppPin`. This eliminates any remaining
+    /// Rust references (since we take the item by value) and this object
+    /// subsequently only vends C++ style references, not Rust references.
+    pub fn new(item: UniquePtr<T>) -> Self {
+        Self(item)
+    }
+
+    /// Get an immutable pointer to the underlying object.
+    pub fn as_ptr(&self) -> *const T {
+        // TODO - avoid brief reference here
+        self.0
+            .as_ref()
+            .expect("UniquePtr was null; we can't make a C++ reference")
+    }
+}
+
+impl<T: UniquePtrTarget> AsCppRef<T> for CppUniquePtrPin<T> {
+    fn as_cpp_ref(&self) -> CppRef<T> {
+        CppRef::from_ptr(self.as_ptr())
+    }
+}
+
+impl<T: UniquePtrTarget> AsCppMutRef<T> for CppUniquePtrPin<T> {
+    fn as_cpp_mut_ref(&mut self) -> CppMutRef<T> {
+        let pinnned_ref: Pin<&mut T> = self
+            .0
+            .as_mut()
+            .expect("UniquePtr was null; we can't make a C++ reference");
+        let ptr = unsafe { Pin::into_inner_unchecked(pinnned_ref) };
+        CppMutRef::from_ptr(ptr)
+    }
+}
+
+/// A structure used to extend the lifetime of a returned C++ reference,
+/// to indicate to Rust that it's beyond the normal Rust lifetime rules.
+/// See [`CppRef::lifetime_cast`].
+#[repr(transparent)]
+pub struct PhantomReferent<T: ?Sized>(*const T);
+
+impl<T: ?Sized> AsCppRef<T> for PhantomReferent<T> {
+    fn as_cpp_ref(&self) -> CppRef<T> {
+        CppRef::from_ptr(self.0)
+    }
+}
+
+/// A structure used to extend the lifetime of a returned C++ mutable reference,
+/// to indicate to Rust that it's beyond the normal Rust lifetime rules.
+/// See [`CppRef::lifetime_cast`].
+#[repr(transparent)]
+pub struct PhantomReferentMut<T: ?Sized>(*mut T);
+
+impl<T: ?Sized> AsCppRef<T> for PhantomReferentMut<T> {
+    fn as_cpp_ref(&self) -> CppRef<T> {
+        CppRef::from_ptr(self.0)
+    }
+}
+
+impl<T: ?Sized> AsCppMutRef<T> for PhantomReferentMut<T> {
+    fn as_cpp_mut_ref(&mut self) -> CppMutRef<T> {
+        CppMutRef::from_ptr(self.0)
+    }
+}
+
+#[cfg(all(feature = "arbitrary_self_types", test))]
+mod tests {
+    use super::*;
+
+    struct CppOuter {
+        _a: u32,
+        inner: CppInner,
+        global: *const CppInner,
+    }
+
+    impl CppOuter {
+        fn get_inner_ref<'a>(self: &CppRef<'a, CppOuter>) -> CppRef<'a, CppInner> {
+            // Safety: emulating C++ code for test purposes. This is safe
+            // because we know the data isn't modified during the lifetime of
+            // the returned reference.
+            let self_rust_ref = unsafe { self.as_ref() };
+            CppRef::from_ptr(std::ptr::addr_of!(self_rust_ref.inner))
+        }
+        fn get_global_ref<'a>(self: &CppRef<'a, CppOuter>) -> CppRef<'a, CppInner> {
+            // Safety: emulating C++ code for test purposes. This is safe
+            // because we know the data isn't modified during the lifetime of
+            // the returned reference.
+            let self_rust_ref = unsafe { self.as_ref() };
+            CppRef::from_ptr(self_rust_ref.global)
+        }
+    }
+
+    struct CppInner {
+        b: u32,
+    }
+
+    impl CppInner {
+        fn value_is(self: &CppRef<Self>) -> u32 {
+            // Safety: emulating C++ code for test purposes. This is safe
+            // because we know the data isn't modified during the lifetime of
+            // the returned reference.
+            let self_rust_ref = unsafe { self.as_ref() };
+            self_rust_ref.b
+        }
+    }
+
+    #[test]
+    fn cpp_objects() {
+        let mut global = CppInner { b: 7 };
+        let global_ref_lifetime_phantom;
+        {
+            let outer = CppOuter {
+                _a: 12,
+                inner: CppInner { b: 3 },
+                global: &mut global,
+            };
+            let outer = CppPin::new(outer);
+            let inner_ref = outer.as_cpp_ref().get_inner_ref();
+            assert_eq!(inner_ref.value_is(), 3);
+            global_ref_lifetime_phantom = Some(outer.as_cpp_ref().get_global_ref().lifetime_cast());
+        }
+        let global_ref = global_ref_lifetime_phantom.unwrap();
+        let global_ref = global_ref.as_cpp_ref();
+        assert_eq!(global_ref.value_is(), 7);
+    }
+
+    #[test]
+    fn cpp_pin() {
+        let a = RustThing { _a: 4 };
+        let a = CppPin::new(a);
+        let _ = a.as_cpp_ref();
+        let _ = a.as_cpp_ref();
+    }
 }
diff --git a/src/rvalue_param.rs b/src/rvalue_param.rs
index 4acc52e..e380c8a 100644
--- a/src/rvalue_param.rs
+++ b/src/rvalue_param.rs
@@ -78,6 +78,13 @@
 /// need to pass a value parameter into C++, and will take responsibility
 /// for extracting that value parameter from the [`RValueParam`] and doing
 /// any later cleanup.
+///
+/// Because C++ move constructors may modify the original object, we consume
+/// the object and store it, pinned, until the call completes. This avoids any
+/// risk that C++ will mutate objects elsewhere in Rust-land, which could cause
+/// problems in the case of re-entrancy as references might exist to those
+/// other objects and Rust assumes there are no unexpected mutations of objects
+/// where references exist.
 #[doc(hidden)]
 pub struct RValueParamHandler<T, RVP>
 where
diff --git a/src/subclass.rs b/src/subclass.rs
index 6c6ee31..bf905d9 100644
--- a/src/subclass.rs
+++ b/src/subclass.rs
@@ -31,7 +31,7 @@
 ///   #[subclass(superclass("MyCppSuperclass"))]
 ///   struct Bar {};
 ///   ```
-/// * as a directive within the [include_cpp] macro, in which case you
+/// * as a directive within the [crate::include_cpp] macro, in which case you
 ///   must provide two arguments of the superclass and then the
 ///   subclass:
 ///   ```
@@ -102,18 +102,14 @@
 /// A type showing how the Rust side of a Rust/C++ subclass pair refers to
 /// the C++ side.
 #[doc(hidden)]
+#[derive(Default)]
 pub enum CppSubclassCppPeerHolder<CppPeer: CppSubclassCppPeer> {
+    #[default]
     Empty,
     Owned(Box<UniquePtr<CppPeer>>),
     Unowned(*mut CppPeer),
 }
 
-impl<CppPeer: CppSubclassCppPeer> Default for CppSubclassCppPeerHolder<CppPeer> {
-    fn default() -> Self {
-        CppSubclassCppPeerHolder::Empty
-    }
-}
-
 impl<CppPeer: CppSubclassCppPeer> CppSubclassCppPeerHolder<CppPeer> {
     fn pin_mut(&mut self) -> Pin<&mut CppPeer> {
         match self {
diff --git a/src/value_param.rs b/src/value_param.rs
index 8e564a1..7386d19 100644
--- a/src/value_param.rs
+++ b/src/value_param.rs
@@ -7,7 +7,7 @@
 // except according to those terms.
 
 use cxx::{memory::UniquePtrTarget, UniquePtr};
-use moveit::{CopyNew, DerefMove, MoveNew, New};
+use moveit::{AsMove, CopyNew, MoveNew, New};
 use std::{marker::PhantomPinned, mem::MaybeUninit, ops::Deref, pin::Pin};
 
 /// A trait representing a parameter to a C++ function which is received
@@ -192,22 +192,21 @@
 
 /// Explicitly force a value parameter to be taken using any type of [`crate::moveit::new::New`],
 /// i.e. a constructor.
-pub fn as_new<N: New<Output = T>, T>(constructor: N) -> impl ValueParam<T> {
+pub fn as_new<N: New>(constructor: N) -> impl ValueParam<N::Output> {
     ByNew(constructor)
 }
 
 /// Explicitly force a value parameter to be taken by copy.
-pub fn as_copy<P: Deref<Target = T>, T>(ptr: P) -> impl ValueParam<T>
+pub fn as_copy<P: Deref>(ptr: P) -> impl ValueParam<P::Target>
 where
-    T: CopyNew,
+    P::Target: CopyNew,
 {
     ByNew(crate::moveit::new::copy(ptr))
 }
 
-/// Explicitly force a value parameter to be taken usign C++ move semantics.
-pub fn as_mov<P: DerefMove + Deref<Target = T>, T>(ptr: P) -> impl ValueParam<T>
+/// Explicitly force a value parameter to be taken using C++ move semantics.
+pub fn as_mov<P: AsMove>(ptr: P) -> impl ValueParam<P::Target>
 where
-    P: DerefMove,
     P::Target: MoveNew,
 {
     ByNew(crate::moveit::new::mov(ptr))
@@ -216,11 +215,8 @@
 #[doc(hidden)]
 pub struct ByNew<N: New>(N);
 
-unsafe impl<N, T> ValueParam<T> for ByNew<N>
-where
-    N: New<Output = T>,
-{
-    type StackStorage = MaybeUninit<T>;
+unsafe impl<N: New> ValueParam<N::Output> for ByNew<N> {
+    type StackStorage = MaybeUninit<N::Output>;
 
     unsafe fn populate_stack_space(self, mut stack: Pin<&mut Option<Self::StackStorage>>) {
         // Safety: we won't move/swap things within the pin.
@@ -228,11 +224,11 @@
         *slot = Some(MaybeUninit::uninit());
         self.0.new(Pin::new_unchecked(slot.as_mut().unwrap()))
     }
-    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut T {
-        // Safety: it's OK to (briefly) create a reference to the T because we
+    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut N::Output {
+        // Safety: it's OK to (briefly) create a reference to the N::Output because we
         // populated it within `populate_stack_space`. It's OK to unpack the pin
         // because we're not going to move the contents.
-        unsafe { Pin::into_inner_unchecked(stack).assume_init_mut() as *mut T }
+        unsafe { Pin::into_inner_unchecked(stack).assume_init_mut() as *mut N::Output }
     }
 
     fn do_drop(stack: Pin<&mut Self::StackStorage>) {