Squashed 'third_party/autocxx/' changes from 629e8fa53..c35090b75

c35090b75 Merge pull request #1131 from google/rev-0.22.3
94f20d716 Revise to 0.22.3.
b4776fdd5 Merge pull request #1070 from google/reference-wrapper
25f08f567 Better encapsulate TypeConversionPolicy. No functional changes.
b389afdeb Add reference wrapper safety policy.
cd169853b Merge pull request #1126 from google/issue-1125
92f48fa30 Merge pull request #1123 from google/segfault-detection
ca60bacca Add comment
724a4971d Add test for issue 1125.
d8a9a8ca7 Detect segfaults in reduction
e147efc7c Merge pull request #1122 from google/rev-0.22.2
dfa9b99a4 Revise to 0.22.2.
4cb1da848 Merge pull request #1120 from chbaker0/main
79afb97d9 Replace lingering tempdir usages with tempfile
f945331a3 Merge pull request #1118 from google/fix-test-fixed-num
5a8b28751 Merge pull request #1117 from google/docs-tweaks
b5486faa1 Merge pull request #1109 from bsilver8192/bindgen-skip-rustfmt
f62c17273 Fix faulty test_fixed_num test.
ad954fa72 Minor doc updates.
eaa1f8737 Leave bindgen enabled when logging is
bdff5db56 Merge pull request #1110 from bsilver8192/subclass-std
922f98be4 Merge pull request #1111 from bsilver8192/subclass-unsafe
bfbcc6b94 Merge pull request #1114 from google/rev-0.22.1
4f68a2e59 Merge pull request #1112 from bsilver8192/subclass-upcast-uniqueptr
993c5705b Revise to 0.22.1.
7bf667bbf Add a function to upcast UniquePtr
733d751a2 Fix clippy and docs
8023cee43 Fix and test subclass without `safety!(unsafe)`
4ae4d47e4 Fix and test subclasses with C++ std in scope
c50b1ee7e Tell bindgen to skip rustfmt
f9b24b90e Merge pull request #1107 from google/reject-anon-namespace-typedefs
070c9755d Merge pull request #1093 from google/always-output-rs
8eb71c5e7 Merge pull request #1095 from google/issue-1094
c86f1ce7e Reject forward declared nested types.
c118dba64 Merge branch 'main' into reject-anon-namespace-typedefs
243079997 Merge pull request #1108 from google/reject-type-param-typedefs
f803c3ba5 Reject type params - fixes #1098
f3381ba52 Reject typedefs to anon namespaces.
669d932a7 Merge pull request #1106 from google/lotsa-failing-tests
f0e8487fe Marking tests as ignored.
524c2bbfc Add tests for multiple issues.
67e16ac2a Merge branch 'main' of github.com:google/autocxx into always-output-rs
5f62daf3f Merge pull request #1104 from google/roll-cxx
43ee55ca2 Further upgrade from 1.0.67 to 1.0.68
e29e3c899 Merge pull request #1100 from bsilver8192/extern_cpp_type-namespace
d2c8edef4 Merge pull request #1101 from google/fix-1081
094dbd957 Roll cxx minimal version.
94c39f35b Merge pull request #1102 from google/fix-book-build
8764f1218 Alter mdbook-mermaid installation.
85543656f Test for issue 1081
b170df056 Fix and test extern_cpp_type with type in a C++ namespace
e4b56dd49 Fix gen tests.
5457e615d Fix #1092.

git-subtree-dir: third_party/autocxx
git-subtree-split: c35090b754619531b4eebdf4d8b583db72349943
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
Change-Id: Ia34285bc1c30f7e3c71fa9e7b677a58902648843
diff --git a/engine/src/conversion/codegen_rs/mod.rs b/engine/src/conversion/codegen_rs/mod.rs
index d488d52..5dd4cbb 100644
--- a/engine/src/conversion/codegen_rs/mod.rs
+++ b/engine/src/conversion/codegen_rs/mod.rs
@@ -17,13 +17,14 @@
 use indexmap::map::IndexMap as HashMap;
 use indexmap::set::IndexSet as HashSet;
 
-use autocxx_parser::{ExternCppType, IncludeCppConfig, RustFun};
+use autocxx_parser::{ExternCppType, IncludeCppConfig, RustFun, UnsafePolicy};
 
 use itertools::Itertools;
 use proc_macro2::{Span, TokenStream};
 use syn::{
     parse_quote, punctuated::Punctuated, token::Comma, Attribute, Expr, FnArg, ForeignItem,
-    ForeignItemFn, Ident, ImplItem, Item, ItemForeignMod, ItemMod, TraitItem, TypePath,
+    ForeignItemFn, Ident, ImplItem, Item, ItemForeignMod, ItemMod, Lifetime, TraitItem, Type,
+    TypePath,
 };
 
 use crate::{
@@ -61,10 +62,16 @@
 use super::{convert_error::ErrorContext, ConvertError};
 use quote::quote;
 
+#[derive(Clone, Hash, PartialEq, Eq)]
+struct ImplBlockKey {
+    ty: Type,
+    lifetime: Option<Lifetime>,
+}
+
 /// An entry which needs to go into an `impl` block for a given type.
 struct ImplBlockDetails {
     item: ImplItem,
-    ty: Ident,
+    ty: ImplBlockKey,
 }
 
 struct TraitImplBlockDetails {
@@ -130,10 +137,96 @@
     .to_vec()
 }
 
+fn get_cppref_items() -> Vec<Item> {
+    [
+        Item::Struct(parse_quote! {
+            #[repr(transparent)]
+            pub struct CppRef<'a, T>(pub *const T, pub ::std::marker::PhantomData<&'a T>);
+        }),
+        Item::Impl(parse_quote! {
+            impl<'a, T> autocxx::CppRef<'a, T> for CppRef<'a, T> {
+                fn as_ptr(&self) -> *const T {
+                    self.0
+                }
+            }
+        }),
+        Item::Struct(parse_quote! {
+            #[repr(transparent)]
+            pub struct CppMutRef<'a, T>(pub *mut T, pub ::std::marker::PhantomData<&'a T>);
+        }),
+        Item::Impl(parse_quote! {
+            impl<'a, T> autocxx::CppRef<'a, T> for CppMutRef<'a, T> {
+                fn as_ptr(&self) -> *const T {
+                    self.0
+                }
+            }
+        }),
+        Item::Impl(parse_quote! {
+            impl<'a, T> autocxx::CppMutRef<'a, T> for CppMutRef<'a, T> {
+                fn as_mut_ptr(&self) -> *mut T {
+                    self.0
+                }
+            }
+        }),
+        Item::Impl(parse_quote! {
+            impl<'a, T: ::cxx::private::UniquePtrTarget> CppMutRef<'a, T> {
+                /// Create a const C++ reference from this mutable C++ reference.
+                pub fn as_cpp_ref(&self) -> CppRef<'a, T> {
+                    use autocxx::CppRef;
+                    CppRef(self.as_ptr(), ::std::marker::PhantomData)
+                }
+            }
+        }),
+        Item::Struct(parse_quote! {
+            /// "Pins" a `UniquePtr` to an object, so that C++-compatible references can be created.
+            /// See [`::autocxx::CppPin`]
+            #[repr(transparent)]
+            pub struct CppUniquePtrPin<T: ::cxx::private::UniquePtrTarget>(::cxx::UniquePtr<T>);
+        }),
+        Item::Impl(parse_quote! {
+            impl<'a, T: 'a + ::cxx::private::UniquePtrTarget> autocxx::CppPin<'a, T> for CppUniquePtrPin<T>
+            {
+                type CppRef = CppRef<'a, T>;
+                type CppMutRef = CppMutRef<'a, T>;
+                fn as_ptr(&self) -> *const T {
+                    // TODO add as_ptr to cxx to avoid the ephemeral reference
+                    self.0.as_ref().unwrap() as *const T
+                }
+                fn as_mut_ptr(&mut self) -> *mut T {
+                    unsafe { ::std::pin::Pin::into_inner_unchecked(self.0.as_mut().unwrap()) as *mut T  }
+                }
+                fn as_cpp_ref(&self) -> Self::CppRef {
+                    CppRef(self.as_ptr(), ::std::marker::PhantomData)
+                }
+                fn as_cpp_mut_ref(&mut self) -> Self::CppMutRef {
+                    CppMutRef(self.as_mut_ptr(), ::std::marker::PhantomData)
+                }
+            }
+        }),
+        Item::Impl(parse_quote! {
+            impl<T: ::cxx::private::UniquePtrTarget> CppUniquePtrPin<T> {
+                pub fn new(item: ::cxx::UniquePtr<T>) -> Self {
+                    Self(item)
+                }
+            }
+        }),
+        Item::Fn(parse_quote! {
+            /// Pin this item so that we can create C++ references to it.
+            /// This makes it impossible to hold Rust references because Rust
+            /// references are fundamentally incompatible with C++ references.
+            pub fn cpp_pin_uniqueptr<T: ::cxx::private::UniquePtrTarget> (item: ::cxx::UniquePtr<T>) -> CppUniquePtrPin<T> {
+                CppUniquePtrPin::new(item)
+            }
+        })
+    ]
+    .to_vec()
+}
+
 /// Type which handles generation of Rust code.
 /// In practice, much of the "generation" involves connecting together
 /// existing lumps of code within the Api structures.
 pub(crate) struct RsCodeGenerator<'a> {
+    unsafe_policy: &'a UnsafePolicy,
     include_list: &'a [String],
     bindgen_mod: ItemMod,
     original_name_map: CppNameMap,
@@ -145,12 +238,14 @@
     /// Generate code for a set of APIs that was discovered during parsing.
     pub(crate) fn generate_rs_code(
         all_apis: ApiVec<FnPhase>,
+        unsafe_policy: &'a UnsafePolicy,
         include_list: &'a [String],
         bindgen_mod: ItemMod,
         config: &'a IncludeCppConfig,
         header_name: Option<String>,
     ) -> Vec<Item> {
         let c = Self {
+            unsafe_policy,
             include_list,
             bindgen_mod,
             original_name_map: original_name_map_from_apis(&all_apis),
@@ -219,6 +314,9 @@
         let mut extern_rust_mod_items = extern_rust_mod_items.into_iter().flatten().collect();
         // And a list of global items to include at the top level.
         let mut all_items: Vec<Item> = all_items.into_iter().flatten().collect();
+        if self.config.unsafe_policy.requires_cpprefs() {
+            all_items.append(&mut get_cppref_items())
+        }
         // And finally any C++ we need to generate. And by "we" I mean autocxx not cxx.
         let has_additional_cpp_needs = additional_cpp_needs.into_iter().any(std::convert::identity);
         extern_c_mod_items.extend(self.build_include_foreign_items(has_additional_cpp_needs));
@@ -357,23 +455,24 @@
     }
 
     fn append_uses_for_ns(&mut self, items: &mut Vec<Item>, ns: &Namespace) {
+        let mut imports_from_super = vec!["cxxbridge"];
+        if !self.config.exclude_utilities() {
+            imports_from_super.push("ToCppString");
+        }
+        if self.config.unsafe_policy.requires_cpprefs() {
+            imports_from_super.extend(["CppRef", "CppMutRef"]);
+        }
+        let imports_from_super = imports_from_super.into_iter().map(make_ident);
         let super_duper = std::iter::repeat(make_ident("super")); // I'll get my coat
         let supers = super_duper.clone().take(ns.depth() + 2);
         items.push(Item::Use(parse_quote! {
             #[allow(unused_imports)]
             use self::
                 #(#supers)::*
-            ::cxxbridge;
+            ::{
+                #(#imports_from_super),*
+            };
         }));
-        if !self.config.exclude_utilities() {
-            let supers = super_duper.clone().take(ns.depth() + 2);
-            items.push(Item::Use(parse_quote! {
-                #[allow(unused_imports)]
-                use self::
-                    #(#supers)::*
-                ::ToCppString;
-            }));
-        }
         let supers = super_duper.take(ns.depth() + 1);
         items.push(Item::Use(parse_quote! {
             #[allow(unused_imports)]
@@ -407,8 +506,10 @@
             }
         }
         for (ty, entries) in impl_entries_by_type.into_iter() {
+            let lt = ty.lifetime.map(|lt| quote! { < #lt > });
+            let ty = ty.ty;
             output_items.push(Item::Impl(parse_quote! {
-                impl #ty {
+                impl #lt #ty {
                     #(#entries)*
                 }
             }))
@@ -487,6 +588,7 @@
                 analysis,
                 cpp_call_name,
                 non_pod_types,
+                self.config,
             ),
             Api::Const { const_item, .. } => RsCodegenResult {
                 bindgen_mod_items: vec![Item::Const(const_item)],
@@ -609,8 +711,11 @@
                 name, superclass, ..
             } => {
                 let methods = associated_methods.get(&superclass);
-                let generate_peer_constructor =
-                    subclasses_with_a_single_trivial_constructor.contains(&name.0.name);
+                let generate_peer_constructor = subclasses_with_a_single_trivial_constructor.contains(&name.0.name) &&
+                    // TODO: Create an UnsafeCppPeerConstructor trait for calling an unsafe
+                    // constructor instead? Need to create unsafe versions of everything that uses
+                    // it too.
+                    matches!(self.unsafe_policy, UnsafePolicy::AllFunctionsSafe);
                 self.generate_subclass(name, &superclass, methods, generate_peer_constructor)
             }
             Api::ExternCppType {
@@ -723,6 +828,10 @@
         extern_c_mod_items.push(parse_quote! {
             fn #as_mut_id(self: Pin<&mut #cpp_id>) -> Pin<&mut #super_cxxxbridge_id>;
         });
+        let as_unique_ptr_id = make_ident(format!("{}_As_{}_UniquePtr", cpp_id, super_name));
+        extern_c_mod_items.push(parse_quote! {
+            fn #as_unique_ptr_id(u: UniquePtr<#cpp_id>) -> UniquePtr<#super_cxxxbridge_id>;
+        });
         bindgen_mod_items.push(parse_quote! {
             impl AsRef<#super_path> for super::super::super::#id {
                 fn as_ref(&self) -> &cxxbridge::#super_cxxxbridge_id {
@@ -740,6 +849,14 @@
                 }
             }
         });
+        let rs_as_unique_ptr_id = make_ident(format!("as_{}_unique_ptr", super_name));
+        bindgen_mod_items.push(parse_quote! {
+            impl super::super::super::#id {
+                pub fn #rs_as_unique_ptr_id(u: cxx::UniquePtr<#cpp_id>) -> cxx::UniquePtr<cxxbridge::#super_cxxxbridge_id> {
+                    cxxbridge::#as_unique_ptr_id(u)
+                }
+            }
+        });
         let remove_ownership = sub.remove_ownership();
         global_items.push(parse_quote! {
             #[allow(non_snake_case)]
@@ -813,7 +930,7 @@
                         .as_ref()
                         .#borrow()
                         .expect(#reentrancy_panic_msg);
-                    let r = std::ops::#deref_ty::#deref_call(& #mut_token b);
+                    let r = ::std::ops::#deref_ty::#deref_call(& #mut_token b);
                     #methods_trait :: #method_name
                         (r,
                         #args)
@@ -1012,7 +1129,7 @@
         rust_path: TypePath,
         ns_depth: usize,
     ) -> RsCodegenResult {
-        let id = name.get_final_ident();
+        let id = name.type_path_from_root();
         let super_duper = std::iter::repeat(make_ident("super"));
         let supers = super_duper.take(ns_depth + 2);
         let use_statement = parse_quote! {
@@ -1057,7 +1174,10 @@
                         fn #method(_uhoh: autocxx::BindingGenerationFailure) {
                         }
                     },
-                    ty: self_ty,
+                    ty: ImplBlockKey {
+                        ty: parse_quote! { #self_ty },
+                        lifetime: None,
+                    },
                 })),
                 None,
                 None,