Squashed 'third_party/autocxx/' content from commit 629e8fa53

git-subtree-dir: third_party/autocxx
git-subtree-split: 629e8fa531a633164c0b52e2a3cab536d4cd0849
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
Change-Id: I62a03b0049f49adf029e0204639cdb5468dde1a1
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..6592011
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,638 @@
+#![doc = include_str!("../README.md")]
+
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// The crazy macro_rules magic in this file is thanks to dtolnay@
+// and is a way of attaching rustdoc to each of the possible directives
+// within the include_cpp outer macro. None of the directives actually
+// do anything - all the magic is handled entirely by
+// autocxx_macro::include_cpp_impl.
+
+mod rvalue_param;
+pub mod subclass;
+mod value_param;
+
+#[cfg_attr(doc, aquamarine::aquamarine)]
+/// Include some C++ headers in your Rust project.
+///
+/// This macro allows you to include one or more C++ headers within
+/// your Rust code, and call their functions fairly naturally.
+///
+/// # Examples
+///
+/// C++ header (`input.h`):
+/// ```cpp
+/// #include <cstdint>
+///
+/// uint32_t do_math(uint32_t a);
+/// ```
+///
+/// Rust code:
+/// ```
+/// # use autocxx_macro::include_cpp_impl as include_cpp;
+/// include_cpp!(
+/// #   parse_only!()
+///     #include "input.h"
+///     generate!("do_math")
+///     safety!(unsafe)
+/// );
+///
+/// # mod ffi { pub fn do_math(a: u32) -> u32 { a+3 } }
+/// # fn main() {
+/// ffi::do_math(3);
+/// # }
+/// ```
+///
+/// The resulting bindings will use idiomatic Rust wrappers for types from the [cxx]
+/// crate, for example [`cxx::UniquePtr`] or [`cxx::CxxString`]. Due to the care and thought
+/// that's gone into the [cxx] crate, such bindings are pleasant and idiomatic to use
+/// from Rust, and usually don't require the `unsafe` keyword.
+///
+/// For full documentation, see [the manual](https://google.github.io/autocxx/).
+///
+/// # The [`include_cpp`] macro
+///
+/// Within the braces of the `include_cpp!{...}` macro, you should provide
+/// a list of at least the following:
+///
+/// * `#include "cpp_header.h"`: a header filename to parse and include
+/// * `generate!("type_or_function_name")`: a type or function name whose declaration
+///   should be made available to C++. (See the section on Allowlisting, below).
+/// * Optionally, `safety!(unsafe)` - see discussion of [`safety`].
+///
+/// Other directives are possible as documented in this crate.
+///
+/// Now, try to build your Rust project. `autocxx` may fail to generate bindings
+/// for some of the items you specified with [generate] directives: remove
+/// those directives for now, then see the next section for advice.
+///
+/// # Allowlisting
+///
+/// How do you inform autocxx which bindings to generate? There are three
+/// strategies:
+///
+/// * *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`].
+///   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
+///   generate Rust bindings for _any_ C++ type or function discovered in the
+///   header files. This is generally a disaster if you're including any
+///   remotely complex header file: we'll try to generate bindings for all sorts
+///   of STL types. This will be slow, and some may well cause problems.
+///   Effectively this is just a debug option to discover such problems. Don't
+///   use it!
+///
+/// # Internals
+///
+/// For documentation on how this all actually _works_, see
+/// `IncludeCppEngine` within the `autocxx_engine` crate.
+#[macro_export]
+macro_rules! include_cpp {
+    (
+        $(#$include:ident $lit:literal)*
+        $($mac:ident!($($arg:tt)*))*
+    ) => {
+        $($crate::$include!{__docs})*
+        $($crate::$mac!{__docs})*
+        $crate::include_cpp_impl! {
+            $(#include $lit)*
+            $($mac!($($arg)*))*
+        }
+    };
+}
+
+/// Include a C++ header. A directive to be included inside
+/// [include_cpp] - see [include_cpp] for details
+#[macro_export]
+macro_rules! include {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Generate Rust bindings for the given C++ type or function.
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+/// See also [generate_pod].
+#[macro_export]
+macro_rules! generate {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Generate as "plain old data" and add to allowlist.
+/// Generate Rust bindings for the given C++ type such that
+/// it can be passed and owned by value in Rust. This only works
+/// for C++ types which have trivial move constructors and no
+/// destructor - you'll encounter a compile error otherwise.
+/// If your type doesn't match that description, use [generate]
+/// instead, and own the type using [UniquePtr][cxx::UniquePtr].
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! generate_pod {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Generate Rust bindings for all C++ types and functions
+/// in a given namespace.
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+/// See also [generate].
+#[macro_export]
+macro_rules! generate_ns {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Generate Rust bindings for all C++ types and functions
+/// found. Highly experimental and not recommended.
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+/// See also [generate].
+#[macro_export]
+macro_rules! generate_all {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Generate as "plain old data". For use with [generate_all]
+/// and similarly experimental.
+#[macro_export]
+macro_rules! pod {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Skip the normal generation of a `make_string` function
+/// and other utilities which we might generate normally.
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! exclude_utilities {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Entirely block some type from appearing in the generated
+/// code. This can be useful if there is a type which is not
+/// understood by bindgen or autocxx, and incorrect code is
+/// otherwise generated.
+/// This is 'greedy' in the sense that any functions/methods
+/// which take or return such a type will _also_ be blocked.
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! block {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Avoid generating implicit constructors for this type.
+/// The rules for when to generate C++ implicit constructors
+/// are complex, and if autocxx gets it wrong, you can block
+/// such constructors using this.
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! block_constructors {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// The name of the mod to be generated with the FFI code.
+/// The default is `ffi`.
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! name {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// A concrete type to make, for example
+/// `concrete!("Container<Contents>")`.
+/// All types msut already be on the allowlist by having used
+/// `generate!` or similar.
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! concrete {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Specifies a global safety policy for functions generated
+/// from these headers. By default (without such a `safety!`
+/// directive) all such functions are marked as `unsafe` and
+/// therefore can only be called within an `unsafe {}` block
+/// or some `unsafe` function which you create.
+///
+/// Alternatively, by specifying a `safety!` block you can
+/// declare that most generated functions are in fact safe.
+/// Specifically, you'd specify:
+/// `safety!(unsafe)`
+/// or
+/// `safety!(unsafe_ffi)`
+/// These two options are functionally identical. If you're
+/// unsure, simply use `unsafe`. The reason for the
+/// latter option is if you have code review policies which
+/// might want to give a different level of scrutiny to
+/// C++ interop as opposed to other types of unsafe Rust code.
+/// Maybe in your organization, C++ interop is less scary than
+/// a low-level Rust data structure using pointer manipulation.
+/// Or maybe it's more scary. Either way, using `unsafe` for
+/// the data structure and using `unsafe_ffi` for the C++
+/// interop allows you to apply different linting tools and
+/// policies to the different options.
+///
+/// Irrespective, C++ code is of course unsafe. It's worth
+/// noting that use of C++ can cause unexpected unsafety at
+/// a distance in faraway Rust code. As with any use of the
+/// `unsafe` keyword in Rust, *you the human* are declaring
+/// that you've analyzed all possible ways that the code
+/// can be used and you are guaranteeing to the compiler that
+/// no badness can occur. Good luck.
+///
+/// Generated C++ APIs which use raw pointers remain `unsafe`
+/// no matter what policy you choose.
+#[macro_export]
+macro_rules! safety {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Whether to avoid generating [`cxx::UniquePtr`] and [`cxx::Vector`]
+/// implementations. This is primarily useful for reducing test cases and
+/// shouldn't be used in normal operation.
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! exclude_impls {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// 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.
+///
+/// The syntax is:
+/// `extern_cpp_type!("CppNameGoesHere", path::to::rust::type)`
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! extern_cpp_type {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// 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. Unlike
+/// `extern_cpp_type!`, there's no need for the size and alignment of this
+/// type to be correct.
+///
+/// The syntax is:
+/// `extern_cpp_opaque_type!("CppNameGoesHere", path::to::rust::type)`
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! extern_cpp_opaque_type {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Deprecated - use [`extern_rust_type`] instead.
+#[macro_export]
+#[deprecated]
+macro_rules! rust_type {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// See [`extern_rust::extern_rust_type`].
+#[macro_export]
+macro_rules! extern_rust_type {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// See [`subclass::subclass`].
+#[macro_export]
+macro_rules! subclass {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+/// Indicates that a C++ type can definitely be instantiated. This has effect
+/// only in a very specific case:
+/// * the type is a typedef to something else
+/// * the 'something else' can't be fully inspected by autocxx, possibly
+///   becaue it relies on dependent qualified types or some other template
+///   arrangement that bindgen cannot fully understand.
+/// In such circumstances, autocxx normally has to err on the side of caution
+/// and assume that some type within the 'something else' is itself a forward
+/// declaration. That means, the opaque typedef won't be storable within
+/// a [`cxx::UniquePtr`]. If you know that no forward declarations are involved,
+/// you can declare the typedef type is instantiable and then you'll be able to
+/// own it within Rust.
+///
+/// The syntax is:
+/// `instantiable!("CppNameGoesHere")`
+///
+/// A directive to be included inside
+/// [include_cpp] - see [include_cpp] for general information.
+#[macro_export]
+macro_rules! instantiable {
+    ($($tt:tt)*) => { $crate::usage!{$($tt)*} };
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! usage {
+    (__docs) => {};
+    ($($tt:tt)*) => {
+        compile_error! {r#"usage:  include_cpp! {
+                   #include "path/to/header.h"
+                   generate!(...)
+                   generate_pod!(...)
+               }
+"#}
+    };
+}
+
+use std::pin::Pin;
+
+#[doc(hidden)]
+pub use autocxx_macro::include_cpp_impl;
+
+#[doc(hidden)]
+pub use autocxx_macro::cpp_semantics;
+
+macro_rules! ctype_wrapper {
+    ($r:ident, $c:expr, $d:expr) => {
+        #[doc=$d]
+        #[derive(Debug, Eq, Copy, Clone, PartialEq, Hash)]
+        #[allow(non_camel_case_types)]
+        #[repr(transparent)]
+        pub struct $r(pub ::std::os::raw::$r);
+
+        /// # Safety
+        ///
+        /// We assert that the namespace and type ID refer to a C++
+        /// type which is equivalent to this Rust type.
+        unsafe impl cxx::ExternType for $r {
+            type Id = cxx::type_id!($c);
+            type Kind = cxx::kind::Trivial;
+        }
+
+        impl From<::std::os::raw::$r> for $r {
+            fn from(val: ::std::os::raw::$r) -> Self {
+                Self(val)
+            }
+        }
+
+        impl From<$r> for ::std::os::raw::$r {
+            fn from(val: $r) -> Self {
+                val.0
+            }
+        }
+    };
+}
+
+ctype_wrapper!(
+    c_ulonglong,
+    "c_ulonglong",
+    "Newtype wrapper for an unsigned long long"
+);
+ctype_wrapper!(c_longlong, "c_longlong", "Newtype wrapper for a long long");
+ctype_wrapper!(c_ulong, "c_ulong", "Newtype wrapper for an unsigned long");
+ctype_wrapper!(c_long, "c_long", "Newtype wrapper for a long");
+ctype_wrapper!(
+    c_ushort,
+    "c_ushort",
+    "Newtype wrapper for an unsigned short"
+);
+ctype_wrapper!(c_short, "c_short", "Newtype wrapper for an short");
+ctype_wrapper!(c_uint, "c_uint", "Newtype wrapper for an unsigned int");
+ctype_wrapper!(c_int, "c_int", "Newtype wrapper for an int");
+ctype_wrapper!(c_uchar, "c_uchar", "Newtype wrapper for an unsigned char");
+
+/// Newtype wrapper for a C void. Only useful as a `*c_void`
+#[allow(non_camel_case_types)]
+#[repr(transparent)]
+pub struct c_void(pub ::std::os::raw::c_void);
+
+/// # Safety
+///
+/// We assert that the namespace and type ID refer to a C++
+/// type which is equivalent to this Rust type.
+unsafe impl cxx::ExternType for c_void {
+    type Id = cxx::type_id!(c_void);
+    type Kind = cxx::kind::Trivial;
+}
+
+/// A C++ `char16_t`
+#[allow(non_camel_case_types)]
+#[repr(transparent)]
+pub struct c_char16_t(pub u16);
+
+/// # Safety
+///
+/// We assert that the namespace and type ID refer to a C++
+/// type which is equivalent to this Rust type.
+unsafe impl cxx::ExternType for c_char16_t {
+    type Id = cxx::type_id!(c_char16_t);
+    type Kind = cxx::kind::Trivial;
+}
+
+/// autocxx couldn't generate these bindings.
+/// If you come across a method, type or function which refers to this type,
+/// it indicates that autocxx couldn't generate that binding. A documentation
+/// comment should be attached indicating the reason.
+pub struct BindingGenerationFailure {
+    _unallocatable: [*const u8; 0],
+    _pinned: core::marker::PhantomData<core::marker::PhantomPinned>,
+}
+
+/// Tools to export Rust code to C++.
+// These are in a mod to avoid shadowing the definitions of the
+// directives above, which, being macro_rules, are unavoidably
+// in the crate root but must be function-style macros to keep
+// the include_cpp impl happy.
+pub mod extern_rust {
+
+    /// Declare that this is a Rust type which is to be exported to C++.
+    /// You can use this in two ways:
+    /// * as an attribute macro on a Rust type, for instance:
+    ///   ```
+    ///   # use autocxx_macro::extern_rust_type as extern_rust_type;
+    ///   #[extern_rust_type]
+    ///   struct Bar;
+    ///   ```
+    /// * as a directive within the [include_cpp] macro, in which case
+    ///   provide the type path in brackets:
+    ///   ```
+    ///   # use autocxx_macro::include_cpp_impl as include_cpp;
+    ///   include_cpp!(
+    ///   #   parse_only!()
+    ///       #include "input.h"
+    ///       extern_rust_type!(Bar)
+    ///       safety!(unsafe)
+    ///   );
+    ///   struct Bar;
+    ///   ```
+    /// These may be used within references in the signatures of C++ functions,
+    /// 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++.
+    pub use autocxx_macro::extern_rust_type;
+
+    /// Declare that a given function is a Rust function which is to be exported
+    /// to C++. This is used as an attribute macro on a Rust function, for instance:
+    /// ```
+    /// # use autocxx_macro::extern_rust_function as extern_rust_function;
+    /// #[extern_rust_function]
+    /// pub fn call_me_from_cpp() { }
+    /// ```
+    pub use autocxx_macro::extern_rust_function;
+}
+
+/// Equivalent to [`std::convert::AsMut`], but returns a pinned mutable reference
+/// such that cxx methods can be called on it.
+pub trait PinMut<T>: AsRef<T> {
+    /// Return a pinned mutable reference to a type.
+    fn pin_mut(&mut self) -> std::pin::Pin<&mut T>;
+}
+
+/// Provides utility functions to emplace any [`moveit::New`] into a
+/// [`cxx::UniquePtr`]. Automatically imported by the autocxx prelude
+/// and implemented by any (autocxx-related) [`moveit::New`].
+pub trait WithinUniquePtr {
+    type Inner: UniquePtrTarget + MakeCppStorage;
+    fn within_unique_ptr(self) -> cxx::UniquePtr<Self::Inner>;
+}
+
+/// Provides utility functions to emplace any [`moveit::New`] into a
+/// [`Box`]. Automatically imported by the autocxx prelude
+/// and implemented by any (autocxx-related) [`moveit::New`].
+pub trait WithinBox {
+    type Inner;
+    fn within_box(self) -> Pin<Box<Self::Inner>>;
+}
+
+use cxx::kind::Trivial;
+use cxx::ExternType;
+use moveit::MakeCppStorage;
+use moveit::{Emplace, EmplaceUnpinned};
+
+impl<N, T> WithinUniquePtr for N
+where
+    N: New<Output = T>,
+    T: UniquePtrTarget + MakeCppStorage,
+{
+    type Inner = T;
+    fn within_unique_ptr(self) -> cxx::UniquePtr<T> {
+        UniquePtr::emplace(self)
+    }
+}
+
+impl<N, T> WithinBox for N
+where
+    N: New<Output = T>,
+{
+    type Inner = T;
+    fn within_box(self) -> Pin<Box<T>> {
+        Box::emplace(self)
+    }
+}
+
+/// Emulates the [`WithinUniquePtr`] trait, but for trivial (plain old data) types.
+/// This allows such types to behave identically if a type is changed from
+/// `generate!` to `generate_pod!`.
+///
+/// (Ideally, this would be the exact same trait as [`WithinUniquePtr`] but this runs
+/// the risk of conflicting implementations. Negative trait bounds would solve
+/// this!)
+pub trait WithinUniquePtrTrivial: UniquePtrTarget + Sized + Unpin {
+    fn within_unique_ptr(self) -> cxx::UniquePtr<Self>;
+}
+
+impl<T> WithinUniquePtrTrivial for T
+where
+    T: UniquePtrTarget + ExternType<Kind = Trivial> + Sized + Unpin,
+{
+    fn within_unique_ptr(self) -> cxx::UniquePtr<T> {
+        UniquePtr::new(self)
+    }
+}
+
+/// Emulates the [`WithinBox`] trait, but for trivial (plain old data) types.
+/// This allows such types to behave identically if a type is changed from
+/// `generate!` to `generate_pod!`.
+///
+/// (Ideally, this would be the exact same trait as [`WithinBox`] but this runs
+/// the risk of conflicting implementations. Negative trait bounds would solve
+/// this!)
+pub trait WithinBoxTrivial: Sized + Unpin {
+    fn within_box(self) -> Pin<Box<Self>>;
+}
+
+impl<T> WithinBoxTrivial for T
+where
+    T: ExternType<Kind = Trivial> + Sized + Unpin,
+{
+    fn within_box(self) -> Pin<Box<T>> {
+        Pin::new(Box::new(self))
+    }
+}
+
+use cxx::memory::UniquePtrTarget;
+use cxx::UniquePtr;
+use moveit::New;
+pub use rvalue_param::RValueParam;
+pub use rvalue_param::RValueParamHandler;
+pub use value_param::as_copy;
+pub use value_param::as_mov;
+pub use value_param::as_new;
+pub use value_param::ValueParam;
+pub use value_param::ValueParamHandler;
+
+/// Imports which you're likely to want to use.
+pub mod prelude {
+    pub use crate::as_copy;
+    pub use crate::as_mov;
+    pub use crate::as_new;
+    pub use crate::c_int;
+    pub use crate::c_long;
+    pub use crate::c_longlong;
+    pub use crate::c_short;
+    pub use crate::c_uchar;
+    pub use crate::c_uint;
+    pub use crate::c_ulong;
+    pub use crate::c_ulonglong;
+    pub use crate::c_ushort;
+    pub use crate::c_void;
+    pub use crate::cpp_semantics;
+    pub use crate::include_cpp;
+    pub use crate::PinMut;
+    pub use crate::RValueParam;
+    pub use crate::ValueParam;
+    pub use crate::WithinBox;
+    pub use crate::WithinBoxTrivial;
+    pub use crate::WithinUniquePtr;
+    pub use crate::WithinUniquePtrTrivial;
+    pub use cxx::UniquePtr;
+    pub use moveit::moveit;
+    pub use moveit::new::New;
+    pub use moveit::Emplace;
+    pub use moveit::EmplaceUnpinned;
+}
+
+/// Re-export moveit for ease of consumers.
+pub use moveit;
+
+/// Re-export cxx such that clients can use the same version as
+/// us. This doesn't enable clients to avoid depending on the cxx
+/// crate too, unfortunately, since generated cxx::bridge code
+/// refers explicitly to ::cxx. See
+/// <https://github.com/google/autocxx/issues/36>
+pub use cxx;
diff --git a/src/rvalue_param.rs b/src/rvalue_param.rs
new file mode 100644
index 0000000..4acc52e
--- /dev/null
+++ b/src/rvalue_param.rs
@@ -0,0 +1,131 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! It would be highly desirable to share a lot of this code with `value_param.rs`
+//! but this proves to be surprisingly fiddly.
+
+use cxx::{memory::UniquePtrTarget, UniquePtr};
+use moveit::MoveRef;
+use std::{
+    marker::{PhantomData, PhantomPinned},
+    pin::Pin,
+};
+
+/// A trait representing a parameter to a C++ function which is received
+/// by rvalue (i.e. by move).
+///
+/// # Panics
+///
+/// The implementations of this trait which take a [`cxx::UniquePtr`] will
+/// panic if the pointer is NULL.
+///
+/// # Safety
+///
+/// Implementers must guarantee that the pointer returned by `get_ptr`
+/// is of the correct size and alignment of `T`.
+pub unsafe trait RValueParam<T>: Sized {
+    /// Retrieve the pointer to the underlying item, to be passed to C++.
+    /// Note that on the C++ side this is currently passed to `std::move`
+    /// and therefore may be mutated.
+    #[doc(hidden)]
+    fn get_ptr(stack: Pin<&mut Self>) -> *mut T;
+}
+
+unsafe impl<T> RValueParam<T> for UniquePtr<T>
+where
+    T: UniquePtrTarget,
+{
+    fn get_ptr(stack: Pin<&mut Self>) -> *mut T {
+        // Safety: we won't move/swap the contents of the outer pin, nor of the
+        // type stored within the UniquePtr.
+        unsafe {
+            (Pin::into_inner_unchecked(
+                (*Pin::into_inner_unchecked(stack))
+                    .as_mut()
+                    .expect("Passed a NULL UniquePtr as a C++ rvalue parameter"),
+            )) as *mut T
+        }
+    }
+}
+
+unsafe impl<T> RValueParam<T> for Pin<Box<T>> {
+    fn get_ptr(stack: Pin<&mut Self>) -> *mut T {
+        // Safety: we won't move/swap the contents of the outer pin, nor of the
+        // type stored within the UniquePtr.
+        unsafe {
+            (Pin::into_inner_unchecked((*Pin::into_inner_unchecked(stack)).as_mut())) as *mut T
+        }
+    }
+}
+
+unsafe impl<'a, T> RValueParam<T> for Pin<MoveRef<'a, T>> {
+    fn get_ptr(stack: Pin<&mut Self>) -> *mut T {
+        // Safety: we won't move/swap the contents of the outer pin, nor of the
+        // type stored within the UniquePtr.
+        unsafe {
+            (Pin::into_inner_unchecked((*Pin::into_inner_unchecked(stack)).as_mut())) as *mut T
+        }
+    }
+}
+
+/// Implementation detail for how we pass rvalue parameters into C++.
+/// This type is instantiated by auto-generated autocxx code each time we
+/// 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.
+#[doc(hidden)]
+pub struct RValueParamHandler<T, RVP>
+where
+    RVP: RValueParam<T>,
+{
+    // We can't populate this on 'new' because the object may move.
+    // Hence this is an Option - it's None until populate is called.
+    space: Option<RVP>,
+    _pinned: PhantomPinned,
+    _data: PhantomData<T>,
+}
+
+impl<T, RVP: RValueParam<T>> RValueParamHandler<T, RVP> {
+    /// Populate this stack space if needs be. Note safety guarantees
+    /// on [`get_ptr`].
+    ///
+    /// # Safety
+    ///
+    /// Callers must guarantee that this type will not move
+    /// in memory between calls to [`populate`] and [`get_ptr`].
+    /// Callers must call [`populate`] exactly once prior to calling [`get_ptr`].
+    pub unsafe fn populate(self: Pin<&mut Self>, param: RVP) {
+        // Structural pinning, as documented in [`std::pin`].
+        // Safety: we will not move the contents of the pin.
+        *Pin::into_inner_unchecked(self.map_unchecked_mut(|s| &mut s.space)) = Some(param)
+    }
+
+    /// Return a pointer to the underlying value which can be passed to C++.
+    /// Per the unsafety contract of [`populate`], the object must not have moved
+    /// since it was created, and [`populate`] has been called exactly once
+    /// prior to this call.
+    pub fn get_ptr(self: Pin<&mut Self>) -> *mut T {
+        // Structural pinning, as documented in [`std::pin`]. `map_unchecked_mut` doesn't play
+        // nicely with `unwrap`, so we have to do it manually.
+        unsafe {
+            RVP::get_ptr(Pin::new_unchecked(
+                self.get_unchecked_mut().space.as_mut().unwrap(),
+            ))
+        }
+    }
+}
+
+impl<T, VP: RValueParam<T>> Default for RValueParamHandler<T, VP> {
+    fn default() -> Self {
+        Self {
+            space: None,
+            _pinned: PhantomPinned,
+            _data: PhantomData,
+        }
+    }
+}
diff --git a/src/subclass.rs b/src/subclass.rs
new file mode 100644
index 0000000..d2827ca
--- /dev/null
+++ b/src/subclass.rs
@@ -0,0 +1,397 @@
+//! Module to make Rust subclasses of C++ classes. See [`CppSubclass`]
+//! for details.
+
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{
+    cell::RefCell,
+    pin::Pin,
+    rc::{Rc, Weak},
+};
+
+use cxx::{memory::UniquePtrTarget, UniquePtr};
+
+/// Deprecated - use [`subclass`] instead.
+#[deprecated]
+pub use autocxx_macro::subclass as is_subclass;
+
+/// Declare a Rust subclass of a C++ class.
+/// You can use this in two ways:
+/// * As an attribute macro on a struct which is to be a subclass.
+///   In this case, you must specify the superclass as described below.
+///   For instance,
+///   ```nocompile
+///   # use autocxx_macro::subclass as subclass;
+///   #[subclass(superclass("MyCppSuperclass"))]
+///   struct Bar {};
+///   ```
+/// * as a directive within the [include_cpp] macro, in which case you
+///   must provide two arguments of the superclass and then the
+///   subclass:
+///   ```
+///   # use autocxx_macro::include_cpp_impl as include_cpp;
+///   include_cpp!(
+///   #   parse_only!()
+///       #include "input.h"
+///       subclass!("MyCppSuperclass",Bar)
+///       safety!(unsafe)
+///   );
+///   struct Bar {
+///     // ...
+///   }
+///   ```
+///   In this latter case, you'll need to implement the trait
+///   [`CppSubclass`] for the struct, so it's
+///   generally easier to use the former option.
+///
+/// See [`CppSubclass`] for information about the
+/// multiple steps you need to take to be able to make Rust
+/// subclasses of a C++ class.
+pub use autocxx_macro::subclass;
+
+/// A prelude containing all the traits and macros required to create
+/// Rust subclasses of C++ classes. It's recommended that you:
+///
+/// ```rust
+/// use autocxx::subclass::prelude::*;
+/// ```
+pub mod prelude {
+    pub use super::{
+        is_subclass, subclass, CppPeerConstructor, CppSubclass, CppSubclassDefault,
+        CppSubclassRustPeerHolder, CppSubclassSelfOwned, CppSubclassSelfOwnedDefault,
+    };
+}
+
+/// A trait representing the C++ side of a Rust/C++ subclass pair.
+#[doc(hidden)]
+pub trait CppSubclassCppPeer: UniquePtrTarget {
+    fn relinquish_ownership(&self);
+}
+
+/// A type used for how the C++ side of a Rust/C++ subclass pair refers to
+/// the Rust side.
+#[doc(hidden)]
+pub enum CppSubclassRustPeerHolder<T> {
+    Owned(Rc<RefCell<T>>),
+    Unowned(Weak<RefCell<T>>),
+}
+
+impl<T> CppSubclassRustPeerHolder<T> {
+    pub fn get(&self) -> Option<Rc<RefCell<T>>> {
+        match self {
+            CppSubclassRustPeerHolder::Owned(strong) => Some(strong.clone()),
+            CppSubclassRustPeerHolder::Unowned(weak) => weak.upgrade(),
+        }
+    }
+    pub fn relinquish_ownership(self) -> Self {
+        match self {
+            CppSubclassRustPeerHolder::Owned(strong) => {
+                CppSubclassRustPeerHolder::Unowned(Rc::downgrade(&strong))
+            }
+            _ => self,
+        }
+    }
+}
+
+/// A type showing how the Rust side of a Rust/C++ subclass pair refers to
+/// the C++ side.
+#[doc(hidden)]
+pub enum CppSubclassCppPeerHolder<CppPeer: CppSubclassCppPeer> {
+    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 {
+            CppSubclassCppPeerHolder::Empty => panic!("Peer not set up"),
+            CppSubclassCppPeerHolder::Owned(peer) => peer.pin_mut(),
+            CppSubclassCppPeerHolder::Unowned(peer) => unsafe {
+                // Safety: guaranteed safe because this is a pointer to a C++ object,
+                // and C++ never moves things in memory.
+                Pin::new_unchecked(peer.as_mut().unwrap())
+            },
+        }
+    }
+    fn get(&self) -> &CppPeer {
+        match self {
+            CppSubclassCppPeerHolder::Empty => panic!("Peer not set up"),
+            CppSubclassCppPeerHolder::Owned(peer) => peer.as_ref(),
+            // Safety: guaranteed safe because this is a pointer to a C++ object,
+            // and C++ never moves things in memory.
+            CppSubclassCppPeerHolder::Unowned(peer) => unsafe { peer.as_ref().unwrap() },
+        }
+    }
+    fn set_owned(&mut self, peer: UniquePtr<CppPeer>) {
+        *self = Self::Owned(Box::new(peer));
+    }
+    fn set_unowned(&mut self, peer: &mut UniquePtr<CppPeer>) {
+        // Safety: guaranteed safe because this is a pointer to a C++ object,
+        // and C++ never moves things in memory.
+        *self = Self::Unowned(unsafe {
+            std::pin::Pin::<&mut CppPeer>::into_inner_unchecked(peer.pin_mut())
+        });
+    }
+}
+
+fn make_owning_peer<CppPeer, PeerConstructor, Subclass, PeerBoxer>(
+    me: Subclass,
+    peer_constructor: PeerConstructor,
+    peer_boxer: PeerBoxer,
+) -> Rc<RefCell<Subclass>>
+where
+    CppPeer: CppSubclassCppPeer,
+    Subclass: CppSubclass<CppPeer>,
+    PeerConstructor:
+        FnOnce(&mut Subclass, CppSubclassRustPeerHolder<Subclass>) -> UniquePtr<CppPeer>,
+    PeerBoxer: FnOnce(Rc<RefCell<Subclass>>) -> CppSubclassRustPeerHolder<Subclass>,
+{
+    let me = Rc::new(RefCell::new(me));
+    let holder = peer_boxer(me.clone());
+    let cpp_side = peer_constructor(&mut me.as_ref().borrow_mut(), holder);
+    me.as_ref()
+        .borrow_mut()
+        .peer_holder_mut()
+        .set_owned(cpp_side);
+    me
+}
+
+/// A trait to be implemented by a subclass which knows how to construct
+/// its C++ peer object. Specifically, the implementation here will
+/// arrange to call one or other of the `make_unique` methods to be
+/// found on the superclass of the C++ object. If the superclass
+/// has a single trivial constructor, then this is implemented
+/// automatically for you. If there are multiple constructors, or
+/// a single constructor which takes parameters, you'll need to implement
+/// this trait for your subclass in order to call the correct
+/// constructor.
+pub trait CppPeerConstructor<CppPeer: CppSubclassCppPeer>: Sized {
+    /// Create the C++ peer. This method will be automatically generated
+    /// for you *except* in cases where the superclass has multiple constructors,
+    /// or its only constructor takes parameters. In such a case you'll need
+    /// to implement this by calling a `make_unique` method on the
+    /// `<my subclass name>Cpp` type, passing `peer_holder` as the first
+    /// argument.
+    fn make_peer(&mut self, peer_holder: CppSubclassRustPeerHolder<Self>) -> UniquePtr<CppPeer>;
+}
+
+/// A subclass of a C++ type.
+///
+/// To create a Rust subclass of a C++ class, you must do these things:
+/// * Create a `struct` to act as your subclass, and add the #[`macro@crate::subclass`] attribute.
+///   This adds a field to your struct for autocxx record-keeping. You can
+///   instead choose to implement [`CppSubclass`] a different way, in which case
+///   you must provide the [`macro@crate::subclass`] inside your [`crate::include_cpp`]
+///   macro. (`autocxx` will do the required codegen for your subclass
+///   whether it discovers a [`macro@crate::subclass`] directive inside your
+///   [`crate::include_cpp`], or elsewhere used as an attribute macro,
+///   or both.)
+/// * Use the [`CppSubclass`] trait, and instantiate the subclass using
+///   [`CppSubclass::new_rust_owned`] or [`CppSubclass::new_cpp_owned`]
+///   constructors. (You can use [`CppSubclassSelfOwned`] if you need that
+///   instead; also, see [`CppSubclassSelfOwnedDefault`] and [`CppSubclassDefault`]
+///   to arrange for easier constructors to exist.
+/// * You _may_ need to implement [`CppPeerConstructor`] for your subclass,
+///   but only if autocxx determines that there are multiple possible superclass
+///   constructors so you need to call one explicitly (or if there's a single
+///   non-trivial superclass constructor.) autocxx will implemente this trait
+///   for you if there's no ambiguity.
+///
+/// # How to access your Rust structure from outside
+///
+/// Use [`CppSubclass::new_rust_owned`] then use [`std::cell::RefCell::borrow`]
+/// or [`std::cell::RefCell::borrow_mut`] to obtain the underlying Rust struct.
+///
+/// # How to call C++ methods on the subclass
+///
+/// Do the same. You should find that your subclass struct `impl`s all the
+/// C++ methods belonging to the superclass.
+///
+/// # How to implement virtual methods
+///
+/// Simply add an `impl` for the `struct`, implementing the relevant method.
+/// The C++ virtual function call will be redirected to your Rust implementation.
+///
+/// # How _not_ to implement virtual methods
+///
+/// If you don't want to implement a virtual method, don't: the superclass
+/// method will be called instead. Naturally, you must implement any pure virtual
+/// methods.
+///
+/// # How it works
+///
+/// This actually consists of two objects: this object itself and a C++-side
+/// peer. The ownership relationship between those two things can work in three
+/// different ways:
+/// 1. Neither object is owned by Rust. The C++ peer is owned by a C++
+///    [`UniquePtr`] held elsewhere in C++. That C++ peer then owns
+///    this Rust-side object via a strong [`Rc`] reference. This is the
+///    ownership relationship set up by [`CppSubclass::new_cpp_owned`].
+/// 2. The object pair is owned by Rust. Specifically, by a strong
+///    [`Rc`] reference to this Rust-side object. In turn, the Rust-side object
+///    owns the C++-side peer via a [`UniquePtr`]. This is what's set up by
+///    [`CppSubclass::new_rust_owned`]. The C++-side peer _does not_ own the Rust
+///    object; it just has a weak pointer. (Otherwise we'd get a reference
+///    loop and nothing would ever be freed.)
+/// 3. The object pair is self-owned and will stay around forever until
+///    [`CppSubclassSelfOwned::delete_self`] is called. In this case there's a strong reference
+///    from the C++ to the Rust and from the Rust to the C++. This is useful
+///    for cases where the subclass is listening for events, and needs to
+///    stick around until a particular event occurs then delete itself.
+///
+/// # Limitations
+///
+/// * *Re-entrancy*. The main thing to look out for is re-entrancy. If a
+///   (non-const) virtual method is called on your type, which then causes you
+///   to call back into C++, which results in a _second_ call into a (non-const)
+///   virtual method, we will try to create two mutable references to your
+///   subclass which isn't allowed in Rust and will therefore panic.
+///
+///   A future version of autocxx may provide the option of treating all
+///   non-const methods (in C++) as const methods on the Rust side, which will
+///   give the option of using interior mutability ([`std::cell::RefCell`])
+///   for you to safely handle this situation, whilst remaining compatible
+///   with existing C++ interfaces. If you need this, indicate support on
+///   [this issue](https://github.com/google/autocxx/issues/622).
+///
+/// * *Thread safety*. The subclass object is not thread-safe and shouldn't
+///   be passed to different threads in C++. A future version of this code
+///   will give the option to use `Arc` and `Mutex` internally rather than
+///   `Rc` and `RefCell`, solving this problem.
+///
+/// * *Protected methods.* We don't do anything clever here - they're public.
+///
+/// * *Non-trivial class hierarchies*. We don't yet consider virtual methods
+///   on base classes of base classes. This is a temporary limitation,
+///   [see this issue](https://github.com/google/autocxx/issues/610).
+pub trait CppSubclass<CppPeer: CppSubclassCppPeer>: CppPeerConstructor<CppPeer> {
+    /// Return the field which holds the C++ peer object. This is normally
+    /// implemented by the #[`is_subclass`] macro, but you're welcome to
+    /// implement it yourself if you prefer.
+    fn peer_holder(&self) -> &CppSubclassCppPeerHolder<CppPeer>;
+
+    /// Return the field which holds the C++ peer object. This is normally
+    /// implemented by the #[`is_subclass`] macro, but you're welcome to
+    /// implement it yourself if you prefer.
+    fn peer_holder_mut(&mut self) -> &mut CppSubclassCppPeerHolder<CppPeer>;
+
+    /// Return a reference to the C++ part of this object pair.
+    /// This can be used to register listeners, etc.
+    fn peer(&self) -> &CppPeer {
+        self.peer_holder().get()
+    }
+
+    /// Return a mutable reference to the C++ part of this object pair.
+    /// This can be used to register listeners, etc.
+    fn peer_mut(&mut self) -> Pin<&mut CppPeer> {
+        self.peer_holder_mut().pin_mut()
+    }
+
+    /// Creates a new instance of this subclass. This instance is owned by the
+    /// returned [`cxx::UniquePtr`] and thus would typically be returned immediately
+    /// to C++ such that it can be owned on the C++ side.
+    fn new_cpp_owned(me: Self) -> UniquePtr<CppPeer> {
+        let me = Rc::new(RefCell::new(me));
+        let holder = CppSubclassRustPeerHolder::Owned(me.clone());
+        let mut borrowed = me.as_ref().borrow_mut();
+        let mut cpp_side = borrowed.make_peer(holder);
+        borrowed.peer_holder_mut().set_unowned(&mut cpp_side);
+        cpp_side
+    }
+
+    /// Creates a new instance of this subclass. This instance is not owned
+    /// by C++, and therefore will be deleted when it goes out of scope in
+    /// Rust.
+    fn new_rust_owned(me: Self) -> Rc<RefCell<Self>> {
+        make_owning_peer(
+            me,
+            |obj, holder| obj.make_peer(holder),
+            |me| CppSubclassRustPeerHolder::Unowned(Rc::downgrade(&me)),
+        )
+    }
+}
+
+/// Trait to be implemented by subclasses which are self-owned, i.e. not owned
+/// externally by either Rust or C++ code, and thus need the ability to delete
+/// themselves when some virtual function is called.
+pub trait CppSubclassSelfOwned<CppPeer: CppSubclassCppPeer>: CppSubclass<CppPeer> {
+    /// Creates a new instance of this subclass which owns itself.
+    /// This is useful
+    /// for observers (etc.) which self-register to listen to events.
+    /// If an event occurs which would cause this to want to unregister,
+    /// use [`CppSubclassSelfOwned::delete_self`].
+    /// The return value may be useful to register this, etc. but can ultimately
+    /// be discarded without destroying this object.
+    fn new_self_owned(me: Self) -> Rc<RefCell<Self>> {
+        make_owning_peer(
+            me,
+            |obj, holder| obj.make_peer(holder),
+            CppSubclassRustPeerHolder::Owned,
+        )
+    }
+
+    /// Relinquishes ownership from the C++ side. If there are no outstanding
+    /// references from the Rust side, this will result in the destruction
+    /// of this subclass instance.
+    fn delete_self(&self) {
+        self.peer().relinquish_ownership()
+    }
+}
+
+/// Provides default constructors for subclasses which implement `Default`.
+pub trait CppSubclassDefault<CppPeer: CppSubclassCppPeer>: CppSubclass<CppPeer> + Default {
+    /// Create a Rust-owned instance of this subclass, initializing with default values. See
+    /// [`CppSubclass`] for more details of the ownership models available.
+    fn default_rust_owned() -> Rc<RefCell<Self>>;
+
+    /// Create a C++-owned instance of this subclass, initializing with default values. See
+    /// [`CppSubclass`] for more details of the ownership models available.
+    fn default_cpp_owned() -> UniquePtr<CppPeer>;
+}
+
+impl<T, CppPeer> CppSubclassDefault<CppPeer> for T
+where
+    T: CppSubclass<CppPeer> + Default,
+    CppPeer: CppSubclassCppPeer,
+{
+    fn default_rust_owned() -> Rc<RefCell<Self>> {
+        Self::new_rust_owned(Self::default())
+    }
+
+    fn default_cpp_owned() -> UniquePtr<CppPeer> {
+        Self::new_cpp_owned(Self::default())
+    }
+}
+
+/// Provides default constructors for subclasses which implement `Default`
+/// and are self-owning.
+pub trait CppSubclassSelfOwnedDefault<CppPeer: CppSubclassCppPeer>:
+    CppSubclassSelfOwned<CppPeer> + Default
+{
+    /// Create a self-owned instance of this subclass, initializing with default values. See
+    /// [`CppSubclass`] for more details of the ownership models available.
+    fn default_self_owned() -> Rc<RefCell<Self>>;
+}
+
+impl<T, CppPeer> CppSubclassSelfOwnedDefault<CppPeer> for T
+where
+    T: CppSubclassSelfOwned<CppPeer> + Default,
+    CppPeer: CppSubclassCppPeer,
+{
+    fn default_self_owned() -> Rc<RefCell<Self>> {
+        Self::new_self_owned(Self::default())
+    }
+}
diff --git a/src/value_param.rs b/src/value_param.rs
new file mode 100644
index 0000000..8e564a1
--- /dev/null
+++ b/src/value_param.rs
@@ -0,0 +1,300 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cxx::{memory::UniquePtrTarget, UniquePtr};
+use moveit::{CopyNew, DerefMove, MoveNew, New};
+use std::{marker::PhantomPinned, mem::MaybeUninit, ops::Deref, pin::Pin};
+
+/// A trait representing a parameter to a C++ function which is received
+/// by value.
+///
+/// Rust has the concept of receiving parameters by _move_ or by _reference_.
+/// C++ has the concept of receiving a parameter by 'value', which means
+/// the parameter gets copied.
+///
+/// To make it easy to pass such parameters from Rust, this trait exists.
+/// It is implemented both for references `&T` and for `UniquePtr<T>`,
+/// subject to the presence or absence of suitable copy and move constructors.
+/// This allows you to pass in parameters by copy (as is ergonomic and normal
+/// in C++) retaining the original parameter; or by move semantics thus
+/// destroying the object you're passing in. Simply use a reference if you want
+/// copy semantics, or the item itself if you want move semantics.
+///
+/// It is not recommended that you implement this trait, nor that you directly
+/// use its methods, which are for use by `autocxx` generated code only.
+///
+/// # Use of `moveit` traits
+///
+/// Most of the implementations of this trait require the type to implement
+/// [`CopyNew`], which is simply the `autocxx`/`moveit` way of saying that
+/// the type has a copy constructor in C++.
+///
+/// # Being explicit
+///
+/// If you wish to explicitly force either a move or a copy of some type,
+/// use [`as_mov`] or [`as_copy`].
+///
+/// # Performance
+///
+/// At present, some additional copying occurs for all implementations of
+/// this trait other than that for [`cxx::UniquePtr`]. In the future it's
+/// hoped that the implementation for `&T where T: CopyNew` can also avoid
+/// this extra copying.
+///
+/// # Panics
+///
+/// The implementations of this trait which take a [`cxx::UniquePtr`] will
+/// panic if the pointer is NULL.
+///
+/// # Safety
+///
+/// Implementers must guarantee that the pointer returned by `get_ptr`
+/// is of the correct size and alignment of `T`.
+pub unsafe trait ValueParam<T> {
+    /// Any stack storage required. If, as part of passing to C++,
+    /// we need to store a temporary copy of the value, this will be `T`,
+    /// otherwise `()`.
+    #[doc(hidden)]
+    type StackStorage;
+    /// Populate the stack storage given as a parameter. Only called if you
+    /// return `true` from `needs_stack_space`.
+    ///
+    /// # Safety
+    ///
+    /// Callers must guarantee that this object will not move in memory
+    /// between this call and any subsequent `get_ptr` call or drop.
+    #[doc(hidden)]
+    unsafe fn populate_stack_space(self, this: Pin<&mut Option<Self::StackStorage>>);
+    /// Retrieve the pointer to the underlying item, to be passed to C++.
+    /// Note that on the C++ side this is currently passed to `std::move`
+    /// and therefore may be mutated.
+    #[doc(hidden)]
+    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut T;
+    #[doc(hidden)]
+    /// Any special drop steps required for the stack storage. This is not
+    /// necessary if the `StackStorage` type is something self-dropping
+    /// such as `UniquePtr`; it's only necessary if it's something where
+    /// manual management is required such as `MaybeUninit`.
+    fn do_drop(_stack: Pin<&mut Self::StackStorage>) {}
+}
+
+unsafe impl<T> ValueParam<T> for &T
+where
+    T: CopyNew,
+{
+    type StackStorage = MaybeUninit<T>;
+
+    unsafe fn populate_stack_space(self, mut stack: Pin<&mut Option<Self::StackStorage>>) {
+        // Safety: we won't move/swap things within the pin.
+        let slot = Pin::into_inner_unchecked(stack.as_mut());
+        *slot = Some(MaybeUninit::uninit());
+        crate::moveit::new::copy(self).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
+        // 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 }
+    }
+
+    fn do_drop(stack: Pin<&mut Self::StackStorage>) {
+        // Switch to MaybeUninit::assume_init_drop when stabilized
+        // Safety: per caller guarantees of populate_stack_space, we know this hasn't moved.
+        unsafe { std::ptr::drop_in_place(Pin::into_inner_unchecked(stack).assume_init_mut()) };
+    }
+}
+
+unsafe impl<T> ValueParam<T> for UniquePtr<T>
+where
+    T: UniquePtrTarget,
+{
+    type StackStorage = UniquePtr<T>;
+
+    unsafe fn populate_stack_space(self, mut stack: Pin<&mut Option<Self::StackStorage>>) {
+        // Safety: we will not move the contents of the pin.
+        *Pin::into_inner_unchecked(stack.as_mut()) = Some(self)
+    }
+
+    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut T {
+        // Safety: we won't move/swap the contents of the outer pin, nor of the
+        // type stored within the UniquePtr.
+        unsafe {
+            (Pin::into_inner_unchecked(
+                (*Pin::into_inner_unchecked(stack))
+                    .as_mut()
+                    .expect("Passed a NULL UniquePtr as a C++ value parameter"),
+            )) as *mut T
+        }
+    }
+}
+
+unsafe impl<T> ValueParam<T> for Pin<Box<T>> {
+    type StackStorage = Pin<Box<T>>;
+
+    unsafe fn populate_stack_space(self, mut stack: Pin<&mut Option<Self::StackStorage>>) {
+        // Safety: we will not move the contents of the pin.
+        *Pin::into_inner_unchecked(stack.as_mut()) = Some(self)
+    }
+
+    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut T {
+        // Safety: we won't move/swap the contents of the outer pin, nor of the
+        // type stored within the UniquePtr.
+        unsafe {
+            (Pin::into_inner_unchecked((*Pin::into_inner_unchecked(stack)).as_mut())) as *mut T
+        }
+    }
+}
+
+unsafe impl<'a, T: 'a> ValueParam<T> for &'a UniquePtr<T>
+where
+    T: UniquePtrTarget + CopyNew,
+{
+    type StackStorage = <&'a T as ValueParam<T>>::StackStorage;
+
+    unsafe fn populate_stack_space(self, stack: Pin<&mut Option<Self::StackStorage>>) {
+        self.as_ref()
+            .expect("Passed a NULL &UniquePtr as a C++ value parameter")
+            .populate_stack_space(stack)
+    }
+
+    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut T {
+        <&'a T as ValueParam<T>>::get_ptr(stack)
+    }
+
+    fn do_drop(stack: Pin<&mut Self::StackStorage>) {
+        <&'a T as ValueParam<T>>::do_drop(stack)
+    }
+}
+
+unsafe impl<'a, T: 'a> ValueParam<T> for &'a Pin<Box<T>>
+where
+    T: CopyNew,
+{
+    type StackStorage = <&'a T as ValueParam<T>>::StackStorage;
+
+    unsafe fn populate_stack_space(self, stack: Pin<&mut Option<Self::StackStorage>>) {
+        self.as_ref().get_ref().populate_stack_space(stack)
+    }
+
+    fn get_ptr(stack: Pin<&mut Self::StackStorage>) -> *mut T {
+        <&'a T as ValueParam<T>>::get_ptr(stack)
+    }
+
+    fn do_drop(stack: Pin<&mut Self::StackStorage>) {
+        <&'a T as ValueParam<T>>::do_drop(stack)
+    }
+}
+
+/// 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> {
+    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>
+where
+    T: 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>
+where
+    P: DerefMove,
+    P::Target: MoveNew,
+{
+    ByNew(crate::moveit::new::mov(ptr))
+}
+
+#[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 fn populate_stack_space(self, mut stack: Pin<&mut Option<Self::StackStorage>>) {
+        // Safety: we won't move/swap things within the pin.
+        let slot = Pin::into_inner_unchecked(stack.as_mut());
+        *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
+        // 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 }
+    }
+
+    fn do_drop(stack: Pin<&mut Self::StackStorage>) {
+        // Switch to MaybeUninit::assume_init_drop when stabilized
+        // Safety: per caller guarantees of populate_stack_space, we know this hasn't moved.
+        unsafe { std::ptr::drop_in_place(Pin::into_inner_unchecked(stack).assume_init_mut()) };
+    }
+}
+
+/// Implementation detail for how we pass value parameters into C++.
+/// This type is instantiated by auto-generated autocxx code each time we
+/// need to pass a value parameter into C++, and will take responsibility
+/// for extracting that value parameter from the [`ValueParam`] and doing
+/// any later cleanup.
+#[doc(hidden)]
+pub struct ValueParamHandler<T, VP: ValueParam<T>> {
+    // We can't populate this on 'new' because the object may move.
+    // Hence this is an Option - it's None until populate is called.
+    space: Option<VP::StackStorage>,
+    _pinned: PhantomPinned,
+}
+
+impl<T, VP: ValueParam<T>> ValueParamHandler<T, VP> {
+    /// Populate this stack space if needs be. Note safety guarantees
+    /// on [`get_ptr`].
+    ///
+    /// # Safety
+    ///
+    /// Callers must call [`populate`] exactly once prior to calling [`get_ptr`].
+    pub unsafe fn populate(self: Pin<&mut Self>, param: VP) {
+        // Structural pinning, as documented in [`std::pin`].
+        param.populate_stack_space(self.map_unchecked_mut(|s| &mut s.space))
+    }
+
+    /// Return a pointer to the underlying value which can be passed to C++.
+    ///
+    /// Per the unsafety contract of [`populate`], [`populate`] has been called exactly once
+    /// prior to this call.
+    pub fn get_ptr(self: Pin<&mut Self>) -> *mut T {
+        // Structural pinning, as documented in [`std::pin`]. `map_unchecked_mut` doesn't play
+        // nicely with `unwrap`, so we have to do it manually.
+        unsafe {
+            VP::get_ptr(Pin::new_unchecked(
+                self.get_unchecked_mut().space.as_mut().unwrap(),
+            ))
+        }
+    }
+}
+
+impl<T, VP: ValueParam<T>> Default for ValueParamHandler<T, VP> {
+    fn default() -> Self {
+        Self {
+            space: None,
+            _pinned: PhantomPinned,
+        }
+    }
+}
+
+impl<T, VP: ValueParam<T>> Drop for ValueParamHandler<T, VP> {
+    fn drop(&mut self) {
+        if let Some(space) = self.space.as_mut() {
+            unsafe { VP::do_drop(Pin::new_unchecked(space)) }
+        }
+    }
+}