diff --git a/Cargo.toml b/Cargo.toml index dfbbaaf00..14ad13cbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ rust-version = "1.77" resolver = "2" [features] -arbitrary_self_types_pointers = [] +arbitrary_self_types = [] [dependencies] autocxx-macro = { path="macro", version="0.27.1" } diff --git a/demo/src/main.rs b/demo/src/main.rs index 798f93245..81edf4922 100644 --- a/demo/src/main.rs +++ b/demo/src/main.rs @@ -6,6 +6,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(arbitrary_self_types)] + use autocxx::prelude::*; include_cpp! { #include "input.h" @@ -16,9 +18,9 @@ include_cpp! { fn main() { println!("Hello, world! - C++ math should say 12={}", ffi::DoMath(4)); - let mut goat = ffi::Goat::new().within_box(); - goat.as_mut().add_a_horn(); - goat.as_mut().add_a_horn(); + let goat = ffi::Goat::new().within_cpp_pin(); + goat.add_a_horn(); + goat.add_a_horn(); assert_eq!( goat.describe().as_ref().unwrap().to_string_lossy(), "This goat has 2 horns." diff --git a/engine/src/conversion/analysis/fun/mod.rs b/engine/src/conversion/analysis/fun/mod.rs index 6dd46b57d..ea7a0f824 100644 --- a/engine/src/conversion/analysis/fun/mod.rs +++ b/engine/src/conversion/analysis/fun/mod.rs @@ -1530,13 +1530,15 @@ impl<'a> FnAnalyzer<'a> { let from_type = self_ty.as_ref().unwrap(); let from_type_path = from_type.to_type_path(); let to_type = to_type.to_type_path(); - let (trait_signature, ty, method_name) = match *mutable { + let (trait_signature, ty, method_name): (_, Type, _) = match *mutable { CastMutability::ConstToConst => ( parse_quote! { - AsRef < #to_type > + autocxx::AsCppRef < #to_type > }, - Type::Path(from_type_path), - "as_ref", + parse_quote! { + autocxx::CppRef< #from_type_path > + }, + "as_cpp_ref", ), CastMutability::MutToConst => ( parse_quote! { diff --git a/engine/src/conversion/codegen_rs/function_wrapper_rs.rs b/engine/src/conversion/codegen_rs/function_wrapper_rs.rs index 4afe3c722..3a0912ad1 100644 --- a/engine/src/conversion/codegen_rs/function_wrapper_rs.rs +++ b/engine/src/conversion/codegen_rs/function_wrapper_rs.rs @@ -172,9 +172,12 @@ impl TypeConversionPolicy { _ => panic!("Not a pointer"), }; let (ty, wrapper_name) = if is_mut { - (parse_quote! { autocxx::CppMutRef<'a, #ty> }, "CppMutRef") + ( + parse_quote! { autocxx::CppMutLtRef<'a, #ty> }, + "CppMutLtRef", + ) } else { - (parse_quote! { autocxx::CppRef<'a, #ty> }, "CppRef") + (parse_quote! { autocxx::CppLtRef<'a, #ty> }, "CppLtRef") }; let wrapper_name = make_ident(wrapper_name); RustParamConversion::Param { @@ -194,9 +197,9 @@ impl TypeConversionPolicy { _ => panic!("Not a pointer"), }; let ty = if is_mut { - parse_quote! { &mut autocxx::CppMutRef<'a, #ty> } + parse_quote! { autocxx::CppMutRef<#ty> } } else { - parse_quote! { &autocxx::CppRef<'a, #ty> } + parse_quote! { autocxx::CppRef<#ty> } }; RustParamConversion::Param { ty, diff --git a/engine/src/conversion/codegen_rs/mod.rs b/engine/src/conversion/codegen_rs/mod.rs index 9185f7fef..226794474 100644 --- a/engine/src/conversion/codegen_rs/mod.rs +++ b/engine/src/conversion/codegen_rs/mod.rs @@ -17,7 +17,7 @@ pub(crate) mod unqualify; use indexmap::map::IndexMap as HashMap; use indexmap::set::IndexSet as HashSet; -use autocxx_parser::{ExternCppType, IncludeCppConfig, RustFun, UnsafePolicy}; +use autocxx_parser::{ExternCppType, IncludeCppConfig, RustFun}; use itertools::Itertools; use proc_macro2::{Span, TokenStream}; @@ -131,7 +131,6 @@ fn get_string_items() -> Vec { /// 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, @@ -143,14 +142,12 @@ impl<'a> RsCodeGenerator<'a> { /// Generate code for a set of APIs that was discovered during parsing. pub(crate) fn generate_rs_code( all_apis: ApiVec, - unsafe_policy: &'a UnsafePolicy, include_list: &'a [String], bindgen_mod: ItemMod, config: &'a IncludeCppConfig, header_name: Option, ) -> Vec { let c = Self { - unsafe_policy, include_list, bindgen_mod, original_name_map: CppNameMap::new_from_apis(&all_apis), @@ -617,11 +614,8 @@ impl<'a> RsCodeGenerator<'a> { name, superclass, .. } => { let methods = associated_methods.get(&superclass); - 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); + let generate_peer_constructor = + subclasses_with_a_single_trivial_constructor.contains(&name.0.name); self.generate_subclass(name, &superclass, methods, generate_peer_constructor) } Api::ExternCppType { diff --git a/engine/src/conversion/conversion_tests.rs b/engine/src/conversion/conversion_tests.rs index e74888e8e..8279ad133 100644 --- a/engine/src/conversion/conversion_tests.rs +++ b/engine/src/conversion/conversion_tests.rs @@ -31,7 +31,7 @@ fn do_test(input: ItemMod) { let inclusions = "".into(); bc.convert( input, - UnsafePolicy::AllFunctionsSafe, + UnsafePolicy::ReferencesWrappedAllFunctionsSafe, inclusions, &CodegenOptions::default(), "", diff --git a/engine/src/conversion/mod.rs b/engine/src/conversion/mod.rs index 57f8d9fef..abaf874ff 100644 --- a/engine/src/conversion/mod.rs +++ b/engine/src/conversion/mod.rs @@ -192,7 +192,6 @@ impl<'a> BridgeConverter<'a> { .map_err(ConvertError::Cpp)?; let rs = RsCodeGenerator::generate_rs_code( analyzed_apis, - &unsafe_policy, self.include_list, bindgen_mod, self.config, diff --git a/examples/reference-wrappers/src/main.rs b/examples/reference-wrappers/src/main.rs index 91998fe5c..ca3e0cdc3 100644 --- a/examples/reference-wrappers/src/main.rs +++ b/examples/reference-wrappers/src/main.rs @@ -25,7 +25,7 @@ // Necessary to be able to call methods on reference wrappers. // For that reason, this example only builds on nightly Rust. -#![feature(arbitrary_self_types_pointers)] +#![feature(arbitrary_self_types)] use autocxx::prelude::*; use std::pin::Pin; diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index 408123ec3..9e2ed5f1d 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -380,6 +380,7 @@ pub fn do_run_test( let safety_policy = format_ident!("{}", safety_policy); let unexpanded_rust = quote! { #module_attributes + #![feature(arbitrary_self_types)] use autocxx::prelude::*; diff --git a/integration-tests/tests/cpprefs_test.rs b/integration-tests/tests/cpprefs_test.rs index 46349ed7b..902a4c856 100644 --- a/integration-tests/tests/cpprefs_test.rs +++ b/integration-tests/tests/cpprefs_test.rs @@ -27,7 +27,7 @@ fn run_cpprefs_test( generate_pods: &[&str], ) { if !arbitrary_self_types_supported() { - // "unsafe_references_wrapped" requires arbitrary_self_types_pointers, which requires nightly. + // "unsafe_references_wrapped" requires arbitrary_self_types, which requires nightly. return; } do_run_test( @@ -127,7 +127,7 @@ fn test_return_reference_cpprefs() { let rs = quote! { let b = CppPin::new(ffi::Bob { a: 3, b: 4 }); let b_ref = b.as_cpp_ref(); - let bob = ffi::give_bob(&b_ref); + let bob = ffi::give_bob(b_ref); let val = unsafe { bob.as_ref() }; assert_eq!(val.b, 4); }; diff --git a/integration-tests/tests/integration_test.rs b/integration-tests/tests/integration_test.rs index be7f62397..08f2bdfef 100644 --- a/integration-tests/tests/integration_test.rs +++ b/integration-tests/tests/integration_test.rs @@ -129,6 +129,7 @@ fn test_nested_module() { "}; let hexathorpe = Token![#](Span::call_site()); let unexpanded_rust = quote! { + #![feature(arbitrary_self_types)] mod a { use autocxx::prelude::*; @@ -203,7 +204,7 @@ fn test_give_up_int() { std::unique_ptr give_up(); "}; let rs = quote! { - assert_eq!(ffi::give_up().as_ref().unwrap(), 12); + assert_eq!(ffi::give_up().as_cpp_ref(), 12); }; run_test(cxx, hdr, rs, &["give_up"], &[]); } @@ -221,7 +222,7 @@ fn test_give_up_ctype() { std::unique_ptr give_up(); "}; let rs = quote! { - assert_eq!(ffi::give_up().as_ref().unwrap(), autocxx::c_int(12)); + assert_eq!(ffi::give_up().as_cpp_ref(), autocxx::c_int(12)); }; run_test(cxx, hdr, rs, &["give_up"], &[]); } @@ -239,7 +240,7 @@ fn test_give_string_up() { std::unique_ptr give_str_up(); "}; let rs = quote! { - assert_eq!(ffi::give_str_up().as_ref().unwrap().to_str().unwrap(), "Bob"); + assert_eq!(ffi::give_str_up().to_str().unwrap(), "Bob"); }; run_test(cxx, hdr, rs, &["give_str_up"], &[]); } @@ -328,7 +329,7 @@ fn test_cycle_string_by_ref() { "}; let rs = quote! { let s = ffi::give_str(); - assert_eq!(ffi::take_str(s.as_ref().unwrap()), 3); + assert_eq!(ffi::take_str(s.as_cpp_ref()), 3); }; let generate = &["give_str", "take_str"]; run_test(cxx, hdr, rs, generate, &[]); @@ -472,7 +473,7 @@ fn test_negative_take_as_pod_with_destructor() { uint32_t take_bob(Bob a); "}; let rs = quote! { - let a = ffi::Bob { a: 12, b: 13 }; + let a = CppPin::new(ffi::Bob { a: 12, b: 13 }); assert_eq!(ffi::take_bob(a), 12); }; run_test_expect_fail(cxx, hdr, rs, &["take_bob"], &["Bob"]); @@ -496,7 +497,7 @@ fn test_negative_take_as_pod_with_move_constructor() { uint32_t take_bob(Bob a); "}; let rs = quote! { - let a = ffi::Bob { a: 12, b: 13 }; + let a = CppPin::new(ffi::Bob { a: 12, b: 13 }); assert_eq!(ffi::take_bob(a), 12); }; run_test_expect_fail(cxx, hdr, rs, &["take_bob"], &["Bob"]); @@ -524,7 +525,7 @@ fn test_take_as_pod_with_is_relocatable() { uint32_t take_bob(Bob a); "}; let rs = quote! { - let a = ffi::Bob { a: 12, b: 13 }; + let a = CppPin::new(ffi::Bob { a: 12, b: 13 }); assert_eq!(ffi::take_bob(a), 12); }; run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]); @@ -546,8 +547,8 @@ fn test_take_pod_by_ref() { uint32_t take_bob(const Bob& a); "}; let rs = quote! { - let a = ffi::Bob { a: 12, b: 13 }; - assert_eq!(ffi::take_bob(&a), 12); + let a = CppPin::new(ffi::Bob { a: 12, b: 13 }); + assert_eq!(ffi::take_bob(a.as_cpp_ref()), 12); }; run_test(cxx, hdr, rs, &["take_bob"], &["Bob"]); } @@ -572,8 +573,8 @@ fn test_take_pod_by_ref_and_ptr() { uint32_t take_bob_ptr(const Bob* a); "}; let rs = quote! { - let a = ffi::Bob { a: 12, b: 13 }; - assert_eq!(ffi::take_bob_ref(&a), 12); + let a = CppPin::new(ffi::Bob { a: 12, b: 13 }); + assert_eq!(ffi::take_bob_ref(a.as_cpp_ref()), 12); }; run_test(cxx, hdr, rs, &["take_bob_ref", "take_bob_ptr"], &["Bob"]); } @@ -596,9 +597,9 @@ fn test_return_pod_by_ref_and_ptr() { } "}; let rs = quote! { - let a = ffi::A { b: ffi::B { a: 3 } }; - assert_eq!(ffi::return_b_ref(&a).a, 3); - let b_ptr = ffi::return_b_ptr(&a); + let a = CppPin::new(ffi::A { b: ffi::B { a: 3 } }); + assert_eq!(unsafe { ffi::return_b_ref(a.as_cpp_ref()).as_ref()}.a, 3); + let b_ptr = ffi::return_b_ptr(a.as_cpp_ref()); assert_eq!(unsafe { b_ptr.as_ref() }.unwrap().a, 3); }; run_test("", hdr, rs, &["return_b_ref", "return_b_ptr"], &["A", "B"]); @@ -705,7 +706,7 @@ fn test_take_nonpod_by_ref() { "}; let rs = quote! { let a = ffi::make_bob(12); - assert_eq!(ffi::take_bob(&a), 12); + assert_eq!(ffi::take_bob(a.as_cpp_ref()), 12); }; run_test(cxx, hdr, rs, &["take_bob", "Bob", "make_bob"], &[]); } @@ -796,9 +797,9 @@ fn test_take_nonpod_by_ptr_in_method() { "}; let rs = quote! { let a = ffi::A::new().within_unique_ptr(); - let b = a.as_ref().unwrap().make_bob(12); + let b = a.as_cpp_ref().make_bob(12); let b_ptr = b.into_raw(); - assert_eq!(unsafe { a.as_ref().unwrap().take_bob(b_ptr) }, 12); + assert_eq!(unsafe { a.as_cpp_ref().take_bob(b_ptr) }, 12); unsafe { cxx::UniquePtr::from_raw(b_ptr) }; // so we drop }; run_test("", hdr, rs, &["A", "Bob"], &[]); @@ -834,9 +835,9 @@ fn test_take_nonpod_by_ptr_in_wrapped_method() { let rs = quote! { let a = ffi::A::new().within_unique_ptr(); let c = ffi::C::new().within_unique_ptr(); - let b = a.as_ref().unwrap().make_bob(12); + let b = a.as_cpp_ref().make_bob(12); let b_ptr = b.into_raw(); - assert_eq!(unsafe { a.as_ref().unwrap().take_bob(b_ptr, c) }, 12); + assert_eq!(unsafe { a.as_cpp_ref().take_bob(b_ptr, c) }, 12); unsafe { cxx::UniquePtr::from_raw(b_ptr) }; // so we drop }; run_test("", hdr, rs, &["A", "Bob", "C"], &[]); @@ -868,9 +869,9 @@ fn run_char_test(builder_modifier: Option) { let a = ffi::A::new().within_unique_ptr(); let c1 = ffi::C::new().within_unique_ptr(); let c2 = ffi::C::new().within_unique_ptr(); - let ch = a.as_ref().unwrap().make_char(c1); + let ch = a.as_cpp_ref().make_char(c1); assert_eq!(unsafe { ch.as_ref()}.unwrap(), &104i8); - assert_eq!(unsafe { a.as_ref().unwrap().take_char(ch, c2) }, 104); + assert_eq!(unsafe { a.as_cpp_ref().take_char(ch, c2) }, 104); }; run_test_ex( "", @@ -916,7 +917,7 @@ fn test_take_nonpod_by_mut_ref() { "}; let rs = quote! { let mut a = ffi::make_bob(12); - assert_eq!(ffi::take_bob(a.pin_mut()), 12); + assert_eq!(ffi::take_bob(a.as_cpp_ref().const_cast()), 12); }; // TODO confirm that the object really was mutated by C++ in this // and similar tests. @@ -1015,7 +1016,7 @@ fn test_cycle_nonpod_with_str_by_ref() { "}; let rs = quote! { let a = ffi::make_bob(); - assert_eq!(ffi::take_bob(a.as_ref().unwrap()), 32); + assert_eq!(ffi::take_bob(a.as_cpp_ref()), 32); }; run_test(cxx, hdr, rs, &["take_bob", "Bob", "make_bob"], &[]); } @@ -1040,7 +1041,7 @@ fn test_make_up() { "}; let rs = quote! { let a = ffi::Bob::new().within_unique_ptr(); // TODO test with all sorts of arguments. - assert_eq!(ffi::take_bob(a.as_ref().unwrap()), 3); + assert_eq!(ffi::take_bob(a.as_cpp_ref()), 3); }; run_test(cxx, hdr, rs, &["Bob", "take_bob"], &[]); } @@ -1064,8 +1065,8 @@ fn test_make_up_with_args() { uint32_t take_bob(const Bob& a); "}; let rs = quote! { - let a = ffi::Bob::new(12, 13).within_unique_ptr(); - assert_eq!(ffi::take_bob(a.as_ref().unwrap()), 12); + let a = ffi::Bob::new(12, 13).within_cpp_pin(); + assert_eq!(ffi::take_bob(a.as_cpp_ref()), 12); }; run_test(cxx, hdr, rs, &["take_bob", "Bob"], &[]); } @@ -1087,7 +1088,7 @@ fn test_make_up_int() { "}; let rs = quote! { let a = ffi::Bob::new(3).within_unique_ptr(); - assert_eq!(a.as_ref().unwrap().b, 3); + assert_eq!(a.as_cpp_ref().b, 3); }; run_test(cxx, hdr, rs, &["Bob"], &[]); } @@ -1227,7 +1228,7 @@ fn test_pod_method() { }; "}; let rs = quote! { - let a = ffi::Bob { a: 12, b: 13 }; + let a = CppPin::new(ffi::Bob { a: 12, b: 13 }); assert_eq!(a.get_bob(), 12); }; run_test(cxx, hdr, rs, &[], &["Bob"]); @@ -1405,7 +1406,7 @@ fn test_method_pass_pod_by_value() { "}; let rs = quote! { let a = ffi::Anna { a: 14 }; - let b = ffi::Bob { a: 12, b: 13 }; + let b = CppPin::new(ffi::Bob { a: 12, b: 13 }); assert_eq!(b.get_bob(a), 12); }; run_test(cxx, hdr, rs, &[], &["Bob", "Anna"]); @@ -1470,7 +1471,7 @@ fn test_inline_method() { "}; let rs = quote! { let a = ffi::Anna { a: 14 }; - let b = ffi::Bob { a: 12, b: 13 }; + let b = CppPin::new(ffi::Bob { a: 12, b: 13 }); assert_eq!(b.get_bob(a), 12); }; run_test("", hdr, rs, &[], &["Bob", "Anna"]); @@ -1496,9 +1497,9 @@ fn test_method_pass_pod_by_reference() { }; "}; let rs = quote! { - let a = ffi::Anna { a: 14 }; - let b = ffi::Bob { a: 12, b: 13 }; - assert_eq!(b.get_bob(&a), 12); + let a = CppPin::new(ffi::Anna { a: 14 }); + let b = CppPin::new(ffi::Bob { a: 12, b: 13 }); + assert_eq!(b.get_bob(a.as_cpp_ref()), 12); }; run_test(cxx, hdr, rs, &[], &["Bob", "Anna"]); } @@ -1524,7 +1525,7 @@ fn test_method_pass_pod_by_mut_reference() { "}; let rs = quote! { let mut a = Box::pin(ffi::Anna { a: 14 }); - let b = ffi::Bob { a: 12, b: 13 }; + let b = CppPin::new(ffi::Bob { a: 12, b: 13 }); assert_eq!(b.get_bob(a.as_mut()), 12); }; run_test(cxx, hdr, rs, &[], &["Bob", "Anna"]); @@ -1552,7 +1553,7 @@ fn test_method_pass_pod_by_up() { "}; let rs = quote! { let a = ffi::Anna { a: 14 }; - let b = ffi::Bob { a: 12, b: 13 }; + let b = CppPin::new(ffi::Bob { a: 12, b: 13 }); assert_eq!(b.get_bob(cxx::UniquePtr::new(a)), 12); }; run_test(cxx, hdr, rs, &[], &["Bob", "Anna"]); @@ -1587,7 +1588,7 @@ fn test_method_pass_nonpod_by_value() { "}; let rs = quote! { let a = ffi::give_anna().within_box(); - let b = ffi::Bob { a: 12, b: 13 }; + let b = CppPin::new(ffi::Bob { a: 12, b: 13 }); assert_eq!(b.get_bob(a), 12); }; run_test(cxx, hdr, rs, &["Anna", "give_anna"], &["Bob"]); @@ -1696,7 +1697,7 @@ fn test_method_pass_nonpod_by_value_with_up() { let rs = quote! { let a = ffi::give_anna().within_unique_ptr(); let a2 = ffi::give_anna().within_unique_ptr(); - let b = ffi::Bob { a: 12, b: 13 }; + let b = CppPin::new(ffi::Bob { a: 12, b: 13 }); assert_eq!(b.get_bob(a, a2), 12); }; run_test(cxx, hdr, rs, &["Anna", "give_anna"], &["Bob"]); @@ -1763,8 +1764,8 @@ fn test_method_pass_nonpod_by_reference() { "}; let rs = quote! { let a = ffi::give_anna().within_box(); - let b = ffi::Bob { a: 12, b: 13 }; - assert_eq!(b.get_bob(a.as_ref().get_ref()), 12); + let b = CppPin::new(ffi::Bob { a: 12, b: 13 }); + assert_eq!(b.get_bob(a.as_cpp_ref()), 12); }; run_test(cxx, hdr, rs, &["Anna", "give_anna"], &["Bob"]); } @@ -1798,8 +1799,8 @@ fn test_method_pass_nonpod_by_mut_reference() { "}; let rs = quote! { let mut a = ffi::give_anna().within_unique_ptr(); - let b = ffi::Bob { a: 12, b: 13 }; - assert_eq!(b.get_bob(a.as_mut().unwrap()), 12); + let b = CppPin::new(ffi::Bob { a: 12, b: 13 }); + assert_eq!(b.get_bob(a.as_cpp_ref().const_cast()), 12); }; run_test(cxx, hdr, rs, &["Anna", "give_anna"], &["Bob"]); } @@ -1834,7 +1835,7 @@ fn test_method_pass_nonpod_by_up() { "}; let rs = quote! { let a = ffi::give_anna().within_unique_ptr(); - let b = ffi::Bob { a: 12, b: 13 }; + let b = CppPin::new(ffi::Bob { a: 12, b: 13 }); assert_eq!(b.get_bob(a), 12); }; run_test(cxx, hdr, rs, &["give_anna"], &["Bob"]); @@ -1864,7 +1865,7 @@ fn test_method_return_nonpod_by_value() { }; "}; let rs = quote! { - let b = ffi::Bob { a: 12, b: 13 }; + let b = CppPin::new(ffi::Bob { a: 12, b: 13 }); let a = b.get_anna().within_unique_ptr(); assert!(!a.is_null()); }; @@ -1909,7 +1910,7 @@ fn test_return_string_by_value() { "}; let rs = quote! { let a = ffi::get_msg(); - assert!(a.as_ref().unwrap() == "hello"); + assert!(a.as_cpp_ref() == "hello"); }; run_test(cxx, hdr, rs, &["get_msg"], &[]); } @@ -1939,7 +1940,7 @@ fn test_method_pass_string_by_value() { "}; let rs = quote! { let a = ffi::get_msg(); - let b = ffi::Bob { a: 12, b: 13 }; + let b = CppPin::new(ffi::Bob { a: 12, b: 13 }); let c = b.measure_string(a); assert_eq!(c, 5); }; @@ -1964,7 +1965,7 @@ fn test_method_return_string_by_value() { }; "}; let rs = quote! { - let b = ffi::Bob { a: 12, b: 13 }; + let b = CppPin::new(ffi::Bob { a: 12, b: 13 }); let a = b.get_msg(); assert!(a.as_ref().unwrap() == "hello"); }; @@ -2103,13 +2104,13 @@ fn test_multiple_classes_with_methods() { let mut os= make_opaque_struct().within_unique_ptr(); assert_eq!(os.get(), 2); - assert_eq!(os.pin_mut().inc(), 3); - assert_eq!(os.pin_mut().inc(), 4); + assert_eq!(os.as_cpp_mut_ref().inc(), 3); + assert_eq!(os.as_cpp_mut_ref().inc(), 4); let mut oc = make_opaque_class().within_unique_ptr(); assert_eq!(oc.get(), 3); - assert_eq!(oc.pin_mut().inc(), 4); - assert_eq!(oc.pin_mut().inc(), 5); + assert_eq!(oc.as_cpp_mut_ref().inc(), 4); + assert_eq!(oc.as_cpp_mut_ref().inc(), 5); }; run_test( cxx, @@ -2356,7 +2357,7 @@ fn test_overload_methods() { "}; let rs = quote! { use ffi::ToCppString; - let a = ffi::Bob { a: 12 }; + let a = CppPin::new(ffi::Bob { a: 12 }); a.daft(32); a.daft1(8); a.daft2("hello".into_cpp()); @@ -2497,8 +2498,8 @@ fn test_return_reference() { const Bob& give_bob(const Bob& input_bob); "}; let rs = quote! { - let b = ffi::Bob { a: 3, b: 4 }; - assert_eq!(ffi::give_bob(&b).b, 4); + let b = CppPin::new(ffi::Bob { a: 3, b: 4 }); + assert_eq!(ffi::give_bob(b.as_cpp_ref()).b, 4); }; run_test(cxx, hdr, rs, &["give_bob"], &["Bob"]); } @@ -2559,7 +2560,7 @@ fn test_member_return_reference() { "}; let rs = quote! { let mut b = ffi::A::new().within_unique_ptr(); - b.pin_mut().get_str(); + b.as_cpp_ref().const_cast().get_str(); }; run_test("", hdr, rs, &["A"], &[]); } @@ -2616,6 +2617,7 @@ fn test_destructor_no_safety() { "}; let hexathorpe = Token![#](Span::call_site()); let unexpanded_rust = quote! { + #![feature(arbitrary_self_types)] use autocxx::prelude::*; include_cpp!( @@ -2771,7 +2773,7 @@ fn test_give_nonpod_typedef_by_value() { inline uint32_t take_horace(const Horace& horace) { return horace.b; } "}; let rs = quote! { - assert_eq!(ffi::take_horace(&moveit!(ffi::give_bob())), 4); + assert_eq!(ffi::take_horace(moveit!(ffi::give_bob())), 4); }; run_test(cxx, hdr, rs, &["give_bob", "take_horace"], &[]); } @@ -2848,8 +2850,8 @@ fn test_conflicting_methods() { }; "}; let rs = quote! { - let a = ffi::Bob { a: 10 }; - let b = ffi::Fred { b: 20 }; + let a = CppPin::new(ffi::Bob { a: 10 }); + let b = CppPin::new(ffi::Fred { b: 20 }); assert_eq!(a.get(), 10); assert_eq!(b.get(), 20); }; @@ -2889,8 +2891,8 @@ fn test_conflicting_up_wrapper_methods_not_in_ns() { let rs = quote! { let a = ffi::Bob::new().within_unique_ptr(); let b = ffi::Fred::new().within_unique_ptr(); - assert_eq!(a.get().as_ref().unwrap().to_str().unwrap(), "hello"); - assert_eq!(b.get().as_ref().unwrap().to_str().unwrap(), "goodbye"); + assert_eq!(a.as_cpp_ref().get().to_str().unwrap(), "hello"); + assert_eq!(b.as_cpp_ref().get().to_str().unwrap(), "goodbye"); }; run_test(cxx, hdr, rs, &["Bob", "Fred"], &[]); } @@ -2917,8 +2919,8 @@ fn test_conflicting_methods_in_ns() { } "}; let rs = quote! { - let a = ffi::A::Bob { a: 10 }; - let b = ffi::B::Fred { b: 20 }; + let a = CppPin::new(ffi::A::Bob { a: 10 }); + let b = CppPin::new(ffi::B::Fred { b: 20 }); assert_eq!(a.get(), 10); assert_eq!(b.get(), 20); }; @@ -2954,8 +2956,8 @@ fn test_conflicting_up_wrapper_methods_in_ns() { let rs = quote! { let a = ffi::A::Bob::new().within_unique_ptr(); let b = ffi::B::Fred::new().within_unique_ptr(); - assert_eq!(a.get().as_ref().unwrap().to_str().unwrap(), "hello"); - assert_eq!(b.get().as_ref().unwrap().to_str().unwrap(), "goodbye"); + assert_eq!(a.as_cpp_ref().get().to_str().unwrap(), "hello"); + assert_eq!(b.as_cpp_ref().get().to_str().unwrap(), "goodbye"); }; run_test(cxx, hdr, rs, &["A::Bob", "B::Fred"], &[]); } @@ -3075,7 +3077,8 @@ fn test_string_let_cxx_string() { "}; let rs = quote! { autocxx::cxx::let_cxx_string!(s = "hello"); - ffi::take_string(&s); + let s = CppRef::from_ptr(&s); + ffi::take_string(s); }; run_test("", hdr, rs, &["take_string"], &[]); } @@ -3167,7 +3170,7 @@ fn test_non_pod_constant() { let a = ffi::BOB; // following line assumes that 'a' is a &Bob // but who knows how we'll really do this. - assert_eq!(a.get().as_ref().unwrap().to_str().unwrap(), "hello"); + assert_eq!(a.get().as_cpp_ref().to_str().unwrap(), "hello"); }; run_test("", hdr, rs, &["BOB"], &[]); } @@ -3398,8 +3401,8 @@ fn test_associated_type_templated_typedef() { inline void take_string_piece(const StringPiece&) {} "}; let rs = quote! { - let sp = ffi::Container::new().within_box(); - ffi::take_string_piece(sp.get_string_piece()); + let sp = ffi::Container::new().within_cpp_pin(); + ffi::take_string_piece(&sp.get_string_piece()); }; run_test("", hdr, rs, &["take_string_piece", "Container"], &[]); } @@ -3490,8 +3493,8 @@ fn test_associated_type_templated_typedef_by_value_forward_declaration() { // As this template is forward declared we shouldn't be able to pass it by // value, but we still want to be able to use it by reference. let rs = quote! { - let cont = ffi::Container::new().within_box(); - ffi::take_string_piece_by_ref(cont.as_ref().get_string_piece()); + let cont = ffi::Container::new().within_cpp_pin(); + ffi::take_string_piece_by_ref(&cont.get_string_piece()); }; run_test( cpp, @@ -3625,7 +3628,7 @@ fn test_foreign_ns_meth_arg_pod() { "}; let rs = quote! { let a = ffi::A::Bob { a: 12 }; - let b = ffi::B::C { a: 12 }; + let b = CppPin::new(ffi::B::C { a: 12 }); assert_eq!(b.daft(a), 12); }; run_test("", hdr, rs, &[], &["A::Bob", "B::C"]); @@ -3651,7 +3654,7 @@ fn test_foreign_ns_meth_arg_nonpod() { "}; let rs = quote! { let a = ffi::A::Bob::new(12).within_unique_ptr(); - let b = ffi::B::C { a: 12 }; + let b = CppPin::new(ffi::B::C { a: 12 }); assert_eq!(b.daft(a), 12); }; run_test("", hdr, rs, &["A::Bob"], &["B::C"]); @@ -3675,8 +3678,8 @@ fn test_foreign_ns_cons_arg_pod() { } "}; let rs = quote! { - let a = ffi::A::Bob { a: 12 }; - let b = ffi::B::C::new(&a).within_unique_ptr(); + let a = CppPin::new(ffi::A::Bob { a: 12 }); + let b = ffi::B::C::new(a.as_cpp_ref()).within_unique_ptr(); assert_eq!(b.as_ref().unwrap().a, 12); }; run_test("", hdr, rs, &[], &["B::C", "A::Bob"]); @@ -3702,8 +3705,8 @@ fn test_foreign_ns_cons_arg_nonpod() { "}; let rs = quote! { let a = ffi::A::Bob::new(12).within_unique_ptr(); - let b = ffi::B::C::new(&a).within_unique_ptr(); - assert_eq!(b.as_ref().unwrap().a, 12); + let b = ffi::B::C::new(a.as_cpp_ref()).within_unique_ptr(); + assert_eq!(unsafe { b.as_cpp_ref().as_ref().a }, 12); }; run_test("", hdr, rs, &["A::Bob"], &["B::C"]); } @@ -3766,7 +3769,7 @@ fn test_foreign_ns_meth_ret_pod() { } "}; let rs = quote! { - let b = ffi::B::C { a: 12 }; + let b = CppPin::new(ffi::B::C { a: 12 }); assert_eq!(b.daft().a, 12); }; run_test("", hdr, rs, &[], &["A::Bob", "B::C"]); @@ -3790,8 +3793,8 @@ fn test_foreign_ns_meth_ret_nonpod() { } "}; let rs = quote! { - let b = ffi::B::C { a: 14 }; - b.daft().within_unique_ptr().as_ref().unwrap(); + let b = CppPin::new(ffi::B::C { a: 14 }); + b.daft().within_unique_ptr().as_cpp_ref(); }; run_test("", hdr, rs, &["A::Bob"], &["B::C"]); } @@ -3852,7 +3855,7 @@ fn test_root_ns_meth_arg_pod() { "}; let rs = quote! { let a = ffi::Bob { a: 12 }; - let b = ffi::B::C { a: 12 }; + let b = CppPin::new(ffi::B::C { a: 12 }); assert_eq!(b.daft(a), 12); }; run_test("", hdr, rs, &[], &["Bob", "B::C"]); @@ -3876,7 +3879,7 @@ fn test_root_ns_meth_arg_nonpod() { "}; let rs = quote! { let a = ffi::Bob::new(12).within_unique_ptr(); - let b = ffi::B::C { a: 12 }; + let b = CppPin::new(ffi::B::C { a: 12 }); assert_eq!(b.daft(a), 12); }; run_test("", hdr, rs, &["Bob"], &["B::C"]); @@ -3898,9 +3901,9 @@ fn test_root_ns_cons_arg_pod() { } "}; let rs = quote! { - let a = ffi::Bob { a: 12 }; - let b = ffi::B::C::new(&a).within_unique_ptr(); - assert_eq!(b.as_ref().unwrap().a, 12); + let a = CppPin::new(ffi::Bob { a: 12 }); + let b = ffi::B::C::new(a.as_cpp_ref()).within_unique_ptr(); + assert_eq!(b.as_ref().a, 12); }; run_test("", hdr, rs, &[], &["B::C", "Bob"]); } @@ -3923,7 +3926,7 @@ fn test_root_ns_cons_arg_nonpod() { "}; let rs = quote! { let a = ffi::Bob::new(12).within_unique_ptr(); - let b = ffi::B::C::new(&a).within_unique_ptr(); + let b = ffi::B::C::new(a.as_cpp_ref()).within_unique_ptr(); assert_eq!(b.as_ref().unwrap().a, 12); }; run_test("", hdr, rs, &["Bob"], &["B::C"]); @@ -3960,7 +3963,7 @@ fn test_root_ns_func_ret_nonpod() { } "}; let rs = quote! { - ffi::B::daft().within_unique_ptr().as_ref().unwrap(); + ffi::B::daft().within_unique_ptr().as_cpp_ref(); }; run_test("", hdr, rs, &["B::daft", "Bob"], &[]); } @@ -3981,7 +3984,7 @@ fn test_root_ns_meth_ret_pod() { } "}; let rs = quote! { - let b = ffi::B::C { a: 12 }; + let b = CppPin::new(ffi::B::C { a: 12 }); assert_eq!(b.daft().a, 12); }; run_test("", hdr, rs, &[], &["Bob", "B::C"]); @@ -4003,8 +4006,8 @@ fn test_root_ns_meth_ret_nonpod() { } "}; let rs = quote! { - let b = ffi::B::C { a: 12 }; - b.daft().within_unique_ptr().as_ref().unwrap(); + let b = CppPin::new(ffi::B::C { a: 12 }); + b.daft().within_unique_ptr().as_cpp_ref(); }; run_test("", hdr, rs, &["Bob"], &["B::C"]); } @@ -4053,7 +4056,8 @@ fn test_forward_declaration() { let rs = quote! { let b = ffi::B::new().within_unique_ptr(); let a = ffi::get_a(); - b.daft(unsafe { a.as_ref().unwrap() }); + let a_ref = CppRef::from_ptr(ffi::get_a()); + b.as_cpp_ref().daft(a_ref); unsafe { ffi::delete_a(a) }; }; run_test(cpp, hdr, rs, &["B", "get_a", "delete_a"], &[]); @@ -4107,7 +4111,7 @@ fn test_ulong_method() { "}; let rs = quote! { let a = ffi::A::new().within_unique_ptr(); - assert_eq!(a.as_ref().unwrap().daft(autocxx::c_ulong(34)), autocxx::c_ulong(34)); + assert_eq!(a.as_cpp_ref().daft(autocxx::c_ulong(34)), autocxx::c_ulong(34)); }; run_test("", hdr, rs, &["A"], &[]); } @@ -4129,7 +4133,7 @@ fn test_ulong_wrapped_method() { let rs = quote! { let b = ffi::B::new().within_unique_ptr(); let a = ffi::A::new().within_unique_ptr(); - assert_eq!(a.as_ref().unwrap().daft(autocxx::c_ulong(34), b), autocxx::c_ulong(34)); + assert_eq!(a.as_cpp_ref().daft(autocxx::c_ulong(34), b), autocxx::c_ulong(34)); }; run_test("", hdr, rs, &["A", "B"], &[]); } @@ -4173,7 +4177,7 @@ fn test_nested_type() { let rs = quote! { let _ = ffi::A::new().within_unique_ptr(); let b = ffi::B::new().within_unique_ptr(); - b.as_ref().unwrap().method_on_top_level_type(); + b.as_cpp_ref().method_on_top_level_type(); }; run_test("", hdr, rs, &["A", "B", "take_A_B", "take_A_C"], &[]); } @@ -4277,7 +4281,7 @@ fn test_nested_type_constructor() { }; "}; let rs = quote! { - ffi::A_B::new(&ffi::make_string("Hello")).within_unique_ptr(); + ffi::A_B::new(ffi::make_string("Hello").as_cpp_ref()).within_unique_ptr(); }; run_test("", hdr, rs, &["A_B"], &[]); } @@ -4302,7 +4306,7 @@ fn test_generic_type() { let rs = quote! { use ffi::ToCppString; let item = ffi::Secondary::new().within_unique_ptr(); - assert_eq!(item.take_c("hello".into_cpp()), 15) + assert_eq!(item.as_cpp_ref().take_c("hello".into_cpp()), 15) }; run_test("", hdr, rs, &["Secondary"], &[]); } @@ -4351,9 +4355,9 @@ fn test_virtual_fns() { "}; let rs = quote! { let mut a = ffi::A::new(12).within_unique_ptr(); - assert_eq!(a.pin_mut().foo(2), 3); + assert_eq!(a.as_cpp_mut_ref().foo(2), 3); let mut b = ffi::B::new().within_unique_ptr(); - assert_eq!(b.pin_mut().foo(2), 4); + assert_eq!(b.as_cpp_mut_ref().foo(2), 4); }; run_test("", hdr, rs, &["A", "B"], &[]); } @@ -4378,9 +4382,9 @@ fn test_const_virtual_fns() { "}; let rs = quote! { let a = ffi::A::new(12).within_unique_ptr(); - assert_eq!(a.foo(2), 3); + assert_eq!(a.as_cpp_ref().foo(2), 3); let b = ffi::B::new().within_unique_ptr(); - assert_eq!(b.foo(2), 4); + assert_eq!(b.as_cpp_ref().foo(2), 4); }; run_test("", hdr, rs, &["A", "B"], &[]); } @@ -4405,7 +4409,7 @@ fn test_virtual_fns_inheritance() { "}; let rs = quote! { let mut b = ffi::B::new().within_unique_ptr(); - assert_eq!(b.pin_mut().foo(2), 3); + assert_eq!(b.as_cpp_mut_ref().foo(2), 3); }; run_test("", hdr, rs, &["B"], &[]); } @@ -4785,7 +4789,7 @@ fn test_dependent_qualified_type() { "}; let rs = quote! { let sv = ffi::make_string_view(); - assert_eq!(ffi::take_string_view(sv.as_ref().unwrap()), 2); + assert_eq!(ffi::take_string_view(sv.as_cpp_ref()), 2); }; run_test("", hdr, rs, &["take_string_view", "make_string_view"], &[]); } @@ -5057,7 +5061,7 @@ fn test_union_ignored() { "}; let rs = quote! { let b = ffi::B::new().within_unique_ptr(); - assert_eq!(b.get_a(), 2); + assert_eq!(b.as_cpp_ref().get_a(), 2); }; run_test("", hdr, rs, &["B"], &[]); } @@ -5199,7 +5203,7 @@ fn test_double_underscore_typedef_ignored() { "}; let rs = quote! { let b = ffi::B::new().within_unique_ptr(); - assert_eq!(b.get_a(), 2); + assert_eq!(b.as_cpp_ref().get_a(), 2); }; run_test("", hdr, rs, &["B"], &[]); } @@ -5370,7 +5374,7 @@ fn test_get_pure_virtual() { "}; let rs = quote! { let a = ffi::get_a(); - let a_ref = unsafe { a.as_ref() }.unwrap(); + let a_ref = CppRef::from_ptr(a); assert_eq!(a_ref.get_val(), 3); }; run_test("", hdr, rs, &["A", "get_a"], &[]); @@ -5677,7 +5681,7 @@ fn test_string_transparent_method() { "}; let rs = quote! { let a = ffi::A::new().within_unique_ptr(); - assert_eq!(a.take_string("hello"), 5); + assert_eq!(a.as_cpp_ref().take_string("hello"), 5); }; run_test("", hdr, rs, &["A"], &[]); } @@ -6340,6 +6344,8 @@ fn test_include_cpp_alone() { "}; let hexathorpe = Token![#](Span::call_site()); let rs = quote! { + #![feature(arbitrary_self_types)] + use autocxx::include_cpp; include_cpp! { #hexathorpe include "input.h" @@ -6363,6 +6369,7 @@ fn test_include_cpp_in_path() { "}; let hexathorpe = Token![#](Span::call_site()); let rs = quote! { + #![feature(arbitrary_self_types)] autocxx::include_cpp! { #hexathorpe include "input.h" safety!(unsafe_ffi) @@ -6417,7 +6424,7 @@ fn test_cint_vector() { "}; let rs = quote! { - assert_eq!(ffi::give_vec().as_ref().unwrap().as_slice(), &[1,2]); + assert_eq!(ffi::give_vec().as_slice(), &[1,2]); }; run_test("", hdr, rs, &["give_vec"], &[]); @@ -6434,7 +6441,7 @@ fn test_int_vector() { "}; let rs = quote! { - assert_eq!(ffi::give_vec().as_ref().unwrap().as_slice(), &[autocxx::c_int(1),autocxx::c_int(2)]); + assert_eq!(ffi::give_vec().as_cpp_ref().as_slice(), &[autocxx::c_int(1),autocxx::c_int(2)]); }; run_test("", hdr, rs, &["give_vec"], &[]); @@ -6684,6 +6691,7 @@ fn test_two_mods() { "}; let hexathorpe = Token![#](Span::call_site()); let rs = quote! { + #![feature(arbitrary_self_types)] use autocxx::prelude::*; include_cpp! { #hexathorpe include "input.h" @@ -6720,6 +6728,7 @@ fn test_manual_bridge() { "}; let hexathorpe = Token![#](Span::call_site()); let rs = quote! { + #![feature(arbitrary_self_types)] autocxx::include_cpp! { #hexathorpe include "input.h" safety!(unsafe_ffi) @@ -6758,6 +6767,7 @@ fn test_manual_bridge_mixed_types() { "}; let hexathorpe = Token![#](Span::call_site()); let rs = quote! { + #![feature(arbitrary_self_types)] use autocxx::prelude::*; autocxx::include_cpp! { #hexathorpe include "input.h" @@ -6775,7 +6785,7 @@ fn test_manual_bridge_mixed_types() { } fn main() { let a = ffi2::give_A(); - assert_eq!(ffi::take_A(&a), autocxx::c_int(5)); + assert_eq!(ffi::take_A(a.as_cpp_ref()), autocxx::c_int(5)); } }; do_run_test_manual("", hdr, rs, None, None).unwrap(); @@ -6798,6 +6808,7 @@ fn test_extern_cpp_type_cxx_bridge() { "}; let hexathorpe = Token![#](Span::call_site()); let rs = quote! { + #![feature(arbitrary_self_types)] use autocxx::prelude::*; include_cpp! { #hexathorpe include "input.h" @@ -6816,7 +6827,7 @@ fn test_extern_cpp_type_cxx_bridge() { } fn main() { let a = ffi::create_a(); - ffi::handle_a(&a); + ffi::handle_a(a.as_cpp_ref()); } }; do_run_test_manual("", hdr, rs, None, None).unwrap(); @@ -6839,6 +6850,7 @@ fn test_extern_cpp_type_different_name() { "}; let hexathorpe = Token![#](Span::call_site()); let rs = quote! { + #![feature(arbitrary_self_types)] use autocxx::prelude::*; include_cpp! { #hexathorpe include "input.h" @@ -6858,7 +6870,7 @@ fn test_extern_cpp_type_different_name() { pub use ffi2::A as DifferentA; fn main() { let a = ffi::create_a(); - ffi::handle_a(&a); + ffi::handle_a(a.as_cpp_ref()); } }; do_run_test_manual("", hdr, rs, None, None).unwrap(); @@ -6884,6 +6896,8 @@ fn test_extern_cpp_type_two_include_cpp() { "}; let hexathorpe = Token![#](Span::call_site()); let rs = quote! { + #![feature(arbitrary_self_types)] + use autocxx::prelude::*; pub mod base { autocxx::include_cpp! { #hexathorpe include "input.h" @@ -6908,8 +6922,8 @@ fn test_extern_cpp_type_two_include_cpp() { } fn main() { use autocxx::prelude::*; - let a = dependent::create_a(base::B::VARIANT).within_box(); - dependent::handle_a(&a); + let a = dependent::create_a(base::B::VARIANT).within_unique_ptr(); + dependent::handle_a(a.as_cpp_ref()); } }; do_run_test_manual("", hdr, rs, None, None).unwrap(); @@ -6932,6 +6946,8 @@ fn test_extern_cpp_type_namespace() { "}; let hexathorpe = Token![#](Span::call_site()); let rs = quote! { + #![feature(arbitrary_self_types)] + use autocxx::prelude::*; pub mod b { autocxx::include_cpp! { #hexathorpe include "input.h" @@ -6953,7 +6969,7 @@ fn test_extern_cpp_type_namespace() { } fn main() { use autocxx::prelude::*; - let _ = crate::a::A::new().within_unique_ptr().as_mut().unwrap().make_b(); + let _ = crate::a::A::new().within_unique_ptr().as_cpp_ref().const_cast().make_b(); } }; do_run_test_manual("", hdr, rs, None, None).unwrap(); @@ -6976,6 +6992,7 @@ fn test_extern_cpp_type_manual() { "}; let hexathorpe = Token![#](Span::call_site()); let rs = quote! { + #![feature(arbitrary_self_types)] autocxx::include_cpp! { #hexathorpe include "input.h" safety!(unsafe_ffi) @@ -7102,8 +7119,8 @@ fn test_rust_reference() { } "}; let rs = quote! { - let foo = RustType(3); - assert_eq!(ffi::take_rust_reference(&foo), 4); + let foo = CppPin::new(RustType(3)); + assert_eq!(ffi::take_rust_reference(foo.as_cpp_ref()), 4); }; run_test_ex( "", @@ -7132,8 +7149,8 @@ fn test_rust_reference_autodiscover() { } "}; let rs = quote! { - let foo = RustType(3); - let result = ffi::take_rust_reference(&foo); + let foo = CppPin::new(RustType(3)); + let result = ffi::take_rust_reference(foo.as_cpp_ref()); assert_eq!(result, 4); }; run_test_ex( @@ -7192,8 +7209,8 @@ fn test_extern_rust_method() { return foo.get(); }"}; let rs = quote! { - let a = RustType(74); - assert_eq!(ffi::examine(&a), 74); + let a = autocxx::CppPin::new(RustType(74)); + assert_eq!(ffi::examine(a.as_cpp_ref()), 74); }; run_test_ex( cxx, @@ -7222,6 +7239,7 @@ fn test_extern_rust_fn_callback() { "}; let hexathorpe = Token![#](Span::call_site()); let rs = quote! { + #![feature(arbitrary_self_types)] autocxx::include_cpp! { #hexathorpe include "input.h" safety!(unsafe_ffi) @@ -7255,8 +7273,8 @@ fn test_rust_reference_no_autodiscover() { } "}; let rs = quote! { - let foo = RustType(3); - let result = ffi::take_rust_reference(&foo); + let foo = CppPin::new(RustType(3)); + let result = ffi::take_rust_reference(foo.as_cpp_ref()); assert_eq!(result, 4); }; run_test_ex( @@ -7453,6 +7471,7 @@ fn test_box_via_extern_rust_no_include_cpp() { "", hdr, quote! { + #![feature(arbitrary_self_types)] #[autocxx::extern_rust::extern_rust_type] pub struct Foo { a: String, @@ -8189,6 +8208,7 @@ fn test_subclass_no_safety() { "}; let hexathorpe = Token![#](Span::call_site()); let unexpanded_rust = quote! { + #![feature(arbitrary_self_types)] use autocxx::prelude::*; include_cpp!( @@ -8347,7 +8367,7 @@ fn test_pv_subclass_allocation_not_self_owned() { assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated); assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated); assert!(!Lazy::force(&STATUS).lock().unwrap().a_called); - let obs_superclass = obs.as_ref().unwrap(); // &subclass + let obs_superclass = obs.as_cpp_ref(); // &subclass let obs_superclass = unsafe { core::mem::transmute::<&ffi::MyTestObserverCpp, &ffi::TestObserver>(obs_superclass) }; ffi::TriggerTestObserverA(obs_superclass); assert!(Lazy::force(&STATUS).lock().unwrap().a_called); @@ -8482,7 +8502,7 @@ fn test_pv_subclass_allocation_self_owned() { assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated); assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated); assert!(!Lazy::force(&STATUS).lock().unwrap().a_called); - let obs_superclass = obs.as_ref().unwrap(); // &subclass + let obs_superclass = obs.as_cpp_ref(); // &subclass let obs_superclass = unsafe { core::mem::transmute::<&ffi::MyTestObserverCpp, &ffi::TestObserver>(obs_superclass) }; ffi::TriggerTestObserverA(obs_superclass); @@ -8520,7 +8540,7 @@ fn test_pv_subclass_allocation_self_owned() { assert!(Lazy::force(&STATUS).lock().unwrap().cpp_allocated); assert!(Lazy::force(&STATUS).lock().unwrap().rust_allocated); assert!(!Lazy::force(&STATUS).lock().unwrap().a_called); - ffi::TriggerTestObserverA(unsafe { obs_superclass_ptr.as_ref().unwrap() }); + ffi::TriggerTestObserverA(unsafe { obs_superclass_ptr.as_cpp_ref() }); assert!(Lazy::force(&STATUS).lock().unwrap().a_called); assert!(!Lazy::force(&STATUS).lock().unwrap().rust_allocated); @@ -8667,7 +8687,7 @@ fn test_pv_subclass_calls() { let obs = MyTestObserver::new_rust_owned( MyTestObserver::default() ); - ffi::register_observer(obs.as_ref().borrow_mut().pin_mut()); + ffi::register_observer(obs.as_ref().borrow_mut().as_cpp_mut_ref()); assert_eq!(ffi::call_a(1), 2); assert!(Lazy::force(&STATUS).lock().unwrap().sub_a_called); *Lazy::force(&STATUS).lock().unwrap() = Default::default(); @@ -8955,7 +8975,7 @@ fn test_pv_subclass_types() { let obs = MyTestObserver::new_rust_owned( MyTestObserver::default() ); - ffi::register_observer(obs.as_ref().borrow_mut().pin_mut()); + ffi::register_observer(obs.as_ref().borrow_mut().as_cpp_mut_ref()); ffi::call_p(ffi::Pod { a: 3 }); ffi::call_s("hello"); ffi::call_n(ffi::make_non_pod("goodbye").within_unique_ptr()); @@ -9028,7 +9048,7 @@ fn test_pv_subclass_constructors() { let obs = MyTestObserver::new_rust_owned( MyTestObserver::default() ); - ffi::register_observer(obs.as_ref().borrow_mut().pin_mut()); + ffi::register_observer(obs.as_ref().borrow_mut().as_cpp_mut_ref()); ffi::do_a_thing(); }, quote! { @@ -9129,7 +9149,7 @@ fn test_non_pv_subclass_overloads() { let obs = MyTestObserver::new_rust_owned( MyTestObserver::default() ); - ffi::register_observer(obs.as_ref().borrow_mut().pin_mut()); + ffi::register_observer(obs.as_ref().borrow_mut().as_cpp_mut_ref()); ffi::do_a_thing(); }, quote! { @@ -9186,7 +9206,7 @@ fn test_pv_subclass_overrides() { let obs = MyTestObserver::new_rust_owned( MyTestObserver::default() ); - ffi::register_observer(obs.as_ref().borrow_mut().pin_mut()); + ffi::register_observer(obs.as_ref().borrow_mut().as_cpp_mut_ref()); ffi::do_a_thing(); }, quote! { @@ -9285,7 +9305,7 @@ fn test_constructor_moveit() { moveit! { let mut stack_obj = ffi::A::new(); } - stack_obj.as_mut().set(42); + stack_obj.set(42); assert_eq!(stack_obj.get(), 42); }; run_test("", hdr, rs, &["A"], &[]); @@ -9372,7 +9392,7 @@ fn test_implicit_constructor_moveit() { let mut stack_obj = ffi::A::new(); } stack_obj.as_mut().set(42); - assert_eq!(stack_obj.get(), 42); + assert_eq!(stack_obj.as_ref().get(), 42); }; run_test("", hdr, rs, &["A"], &[]); } @@ -9407,9 +9427,9 @@ fn test_pass_by_value_moveit() { // A has no move constructor so we can't consume it. let heap_obj = ffi::A::new().within_unique_ptr(); - ffi::take_a(heap_obj.as_ref().unwrap()); + ffi::take_a(heap_obj.as_cpp_ref()); ffi::take_a(&heap_obj); - ffi::take_a(autocxx::as_copy(heap_obj.as_ref().unwrap())); + ffi::take_a(autocxx::as_copy(heap_obj.as_cpp_ref())); ffi::take_a(heap_obj); // consume let heap_obj2 = ffi::A::new().within_box(); @@ -9448,7 +9468,7 @@ fn test_nonconst_reference_parameter() { "}; let rs = quote! { let mut heap_obj = ffi::A::new().within_unique_ptr(); - ffi::take_a(heap_obj.pin_mut()); + ffi::take_a(heap_obj.as_cpp_ref().const_cast()); }; run_test("", hdr, rs, &["NOP", "A", "take_a"], &[]); } @@ -9472,7 +9492,7 @@ fn test_nonconst_reference_method_parameter() { let rs = quote! { let mut a = ffi::A::new().within_unique_ptr(); let b = ffi::B::new().within_unique_ptr(); - b.take_a(a.pin_mut()); + b.as_cpp_ref().take_a(a.as_cpp_ref().const_cast()); }; run_test("", hdr, rs, &["NOP", "A", "B"], &[]); } @@ -9547,7 +9567,7 @@ fn test_copy_and_move_constructor_moveit() { moveit! { let mut stack_obj = ffi::A::new(); } - stack_obj.as_mut().set(42); + stack_obj.set(42); moveit! { let stack_obj2 = autocxx::moveit::new::copy(stack_obj.as_ref()); } @@ -9582,8 +9602,8 @@ fn test_uniqueptr_moveit() { let rs = quote! { use autocxx::moveit::Emplace; let mut up_obj = cxx::UniquePtr::emplace(ffi::A::new()); - up_obj.as_mut().unwrap().set(42); - assert_eq!(up_obj.get(), 42); + up_obj.as_cpp_ref().const_cast().set(42); + assert_eq!(up_obj.as_cpp_ref().get(), 42); }; run_test("", hdr, rs, &["A"], &[]); } @@ -9702,7 +9722,7 @@ fn test_pass_by_reference_to_value_param() { let a = ffi::A::new().within_unique_ptr(); ffi::take_a(a.as_ref().unwrap()); ffi::take_a(&a); // syntactic sugar - assert_eq!(ffi::report_on_a(&a), 0); // should have acted upon copies + assert_eq!(ffi::report_on_a(a.as_cpp_ref()), 0); // should have acted upon copies }; run_test("", hdr, rs, &["A", "take_a", "report_on_a"], &[]); } @@ -9863,7 +9883,7 @@ fn test_abstract_up() { "}; let rs = quote! { let a = ffi::get_a(); - a.foo(); + a.as_cpp_ref().foo(); }; run_test("", hdr, rs, &["A", "get_a"], &[]); } @@ -9885,6 +9905,8 @@ fn test_abstract_up_multiple_bridge() { "}; let hexathorpe = Token![#](Span::call_site()); let rs = quote! { + #![feature(arbitrary_self_types)] + use autocxx::prelude::*; autocxx::include_cpp! { #hexathorpe include "input.h" safety!(unsafe_ffi) @@ -9899,7 +9921,7 @@ fn test_abstract_up_multiple_bridge() { } fn main() { let a = ffi2::get_a(); - a.foo(); + a.as_cpp_ref().foo(); } }; do_run_test_manual("", hdr, rs, None, None).unwrap(); @@ -10116,8 +10138,8 @@ fn test_nested_class_methods() { "}; let rs = quote! { let a = ffi::A::new().within_unique_ptr(); - a.a(); - a.c(); + a.as_cpp_ref().a(); + a.as_cpp_ref().c(); }; run_test("", hdr, rs, &["A"], &[]); } @@ -10139,7 +10161,7 @@ fn test_call_superclass() { "}; let rs = quote! { let b = ffi::get_b(); - b.as_ref().unwrap().as_ref().foo(); + b.as_cpp_ref().foo(); }; run_test("", hdr, rs, &["A", "B", "get_b"], &[]); } @@ -10162,7 +10184,7 @@ fn test_pass_superclass() { "}; let rs = quote! { let b = ffi::get_b(); - ffi::take_a(b.as_ref().unwrap().as_ref()); + ffi::take_a(b.as_cpp_ref().as_ref()); }; run_test("", hdr, rs, &["A", "B", "get_b", "take_a"], &[]); } @@ -11395,7 +11417,7 @@ fn test_tricky_destructors() { let mut unique_t = <$t>::new().within_unique_ptr(); let mut destructor_flag = false; unsafe { - unique_t.pin_mut().set_flag(&mut destructor_flag); + unique_t.as_cpp_mut_ref().set_flag(&mut destructor_flag); } std::mem::drop(unique_t); assert!(destructor_flag, "Destructor did not run with make_unique for {}", quote::quote!{$t}); @@ -11405,7 +11427,7 @@ fn test_tricky_destructors() { } let mut destructor_flag = false; unsafe { - moveit_t.as_mut().set_flag(&mut destructor_flag); + moveit_t.as_cpp_mut_ref().set_flag(&mut destructor_flag); } std::mem::drop(moveit_t); assert!(destructor_flag, "Destructor did not run with moveit for {}", quote::quote!{$t}); @@ -12244,6 +12266,7 @@ fn test_issue_1229() { "}; let hexathorpe = Token![#](Span::call_site()); let rs = quote! { + #![feature(arbitrary_self_types)] use autocxx::WithinUniquePtr; autocxx::include_cpp! { diff --git a/parser/src/config.rs b/parser/src/config.rs index 2421e09a6..785ae042b 100644 --- a/parser/src/config.rs +++ b/parser/src/config.rs @@ -31,7 +31,6 @@ use quote::quote; #[derive(PartialEq, Eq, Clone, Debug, Hash)] pub enum UnsafePolicy { - AllFunctionsSafe, AllFunctionsUnsafe, ReferencesWrappedAllFunctionsSafe, } @@ -45,12 +44,12 @@ impl Default for UnsafePolicy { impl Parse for UnsafePolicy { fn parse(input: ParseStream) -> ParseResult { if input.parse::>()?.is_some() { - return Ok(UnsafePolicy::AllFunctionsSafe); + return Ok(UnsafePolicy::ReferencesWrappedAllFunctionsSafe); } let r = match input.parse::>()? { Some(id) => { if id == "unsafe_ffi" { - Ok(UnsafePolicy::AllFunctionsSafe) + Ok(UnsafePolicy::ReferencesWrappedAllFunctionsSafe) } else if id == "unsafe_references_wrapped" { Ok(UnsafePolicy::ReferencesWrappedAllFunctionsSafe) } else { @@ -74,9 +73,7 @@ impl Parse for UnsafePolicy { impl ToTokens for UnsafePolicy { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { - if *self == UnsafePolicy::AllFunctionsSafe { - tokens.extend(quote! { unsafe }) - } else if *self == UnsafePolicy::ReferencesWrappedAllFunctionsSafe { + if *self == UnsafePolicy::ReferencesWrappedAllFunctionsSafe { tokens.extend(quote! { unsafe_references_wrapped }) } } @@ -503,7 +500,7 @@ mod parse_tests { let us: UnsafePolicy = parse_quote! { unsafe }; - assert_eq!(us, UnsafePolicy::AllFunctionsSafe) + assert_eq!(us, UnsafePolicy::ReferencesWrappedAllFunctionsSafe) } #[test] @@ -511,7 +508,7 @@ mod parse_tests { let us: UnsafePolicy = parse_quote! { unsafe_ffi }; - assert_eq!(us, UnsafePolicy::AllFunctionsSafe) + assert_eq!(us, UnsafePolicy::ReferencesWrappedAllFunctionsSafe) } #[test] diff --git a/src/lib.rs b/src/lib.rs index b0eeec17a..eb5623b4d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ #![doc = include_str!("../README.md")] #![cfg_attr(nightly, feature(unsize))] #![cfg_attr(nightly, feature(dispatch_from_dyn))] +#![cfg_attr(nightly, feature(arbitrary_self_types))] // Copyright 2020 Google LLC // @@ -21,7 +22,9 @@ mod rvalue_param; pub mod subclass; mod value_param; -pub use reference_wrapper::{AsCppMutRef, AsCppRef, CppMutRef, CppPin, CppRef, CppUniquePtrPin}; +pub use reference_wrapper::{ + AsCppMutRef, AsCppRef, CppLtRef, CppMutLtRef, CppMutRef, CppPin, CppRef, CppUniquePtrPin, +}; #[cfg_attr(doc, aquamarine::aquamarine)] /// Include some C++ headers in your Rust project. @@ -270,7 +273,7 @@ macro_rules! concrete { /// 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_pointers`). However, it should +/// (`arbitrary_self_types`). However, it should /// eliminate all undefined behavior related to Rust's /// stricter aliasing rules than C++. #[macro_export] @@ -594,10 +597,7 @@ pub trait WithinBox { fn within_box(self) -> Pin>; /// 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. + /// C++ references to it. fn within_cpp_pin(self) -> CppPin; } diff --git a/src/reference_wrapper.rs b/src/reference_wrapper.rs index a8fa48755..4252100b1 100644 --- a/src/reference_wrapper.rs +++ b/src/reference_wrapper.rs @@ -8,8 +8,9 @@ use core::{marker::PhantomData, ops::Deref, pin::Pin}; +use std::ops::DerefMut; #[cfg(nightly)] -use std::{marker::Unsize, ops::DispatchFromDyn}; +use std::{marker::Unsize, ops::DispatchFromDyn, ops::Receiver}; use cxx::{memory::UniquePtrTarget, UniquePtr}; @@ -21,10 +22,6 @@ use cxx::{memory::UniquePtrTarget, UniquePtr}; /// 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 @@ -36,25 +33,15 @@ use cxx::{memory::UniquePtrTarget, UniquePtr}; /// # 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 +/// Currently, 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_pointers)]` 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. +/// and add `#![feature(arbitrary_self_types)]` to your crate. /// -/// 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. +/// # Lifetimes /// -/// 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. +/// A `CppRef` is not associated with any Rust lifetime. Normally, for +/// ergonomics, you actually may want a lifetime associated. +/// [`CppLtRef`] gives you this. /// /// # Field access /// @@ -68,14 +55,6 @@ use cxx::{memory::UniquePtrTarget, UniquePtr}; /// 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 @@ -114,15 +93,12 @@ use cxx::{memory::UniquePtrTarget, UniquePtr}; /// 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>, -} +pub struct CppRef(*const T); -impl<'a, T: ?Sized> CppRef<'a, T> { +impl CppRef { /// Retrieve the underlying C++ pointer. pub fn as_ptr(&self) -> *const T { - self.ptr + self.0 } /// Get a regular Rust reference out of this C++ reference. @@ -142,10 +118,7 @@ impl<'a, T: ?Sized> CppRef<'a, T> { /// Create a C++ reference from a raw pointer. pub fn from_ptr(ptr: *const T) -> Self { - Self { - ptr, - phantom: PhantomData, - } + Self(ptr) } /// Create a mutable version of this reference, roughly equivalent @@ -159,13 +132,56 @@ impl<'a, T: ?Sized> CppRef<'a, T> { /// 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, + pub fn const_cast(&self) -> CppMutRef { + CppMutRef(self.0 as *mut T) + } +} + +#[cfg(nightly)] +impl Receiver for CppRef { + type Target = T; +} + +impl Clone for CppRef { + fn clone(&self) -> Self { + Self(self.0) + } +} + +impl Copy for CppRef {} + +#[cfg(nightly)] +impl, U: ?Sized> DispatchFromDyn> for CppRef {} + +/// A [`CppRef`] with an associated lifetime. This can be used in place of +/// any `CppRef` due to a `Deref` implementation. +#[repr(transparent)] +pub struct CppLtRef<'a, T: ?Sized> { + ptr: CppRef, + phantom: PhantomData<&'a T>, +} + +impl Deref for CppLtRef<'_, T> { + type Target = CppRef; + fn deref(&self) -> &Self::Target { + // Safety: this type is transparent and contains a CppRef as + // its only non-zero field. + unsafe { std::mem::transmute(self) } + } +} + +impl Clone for CppLtRef<'_, T> { + fn clone(&self) -> Self { + Self { + ptr: self.ptr.clone(), phantom: self.phantom, } } +} + +impl Copy for CppLtRef<'_, T> {} +impl CppLtRef<'_, T> { /// Extend the lifetime of the returned reference beyond normal Rust /// borrow checker rules. /// @@ -177,49 +193,27 @@ impl<'a, T: ?Sized> CppRef<'a, T> { /// # 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` + /// for a long time, use this method. Store the resulting `CppRef` /// 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 { - PhantomReferent(self.ptr) + pub fn lifetime_cast(&self) -> CppRef { + CppRef(self.ptr.as_ptr()) } -} -impl Deref for CppRef<'_, 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); - impl C { - const V: core::convert::Infallible = panic!( - "You cannot directly obtain a Rust reference from a CppRef. Use CppRef::as_ref." - ); - } - match C::::V {} - } -} - -impl Clone for CppRef<'_, T> { - fn clone(&self) -> Self { + /// Create a C++ reference from a raw pointer. + pub fn from_ptr(ptr: *const T) -> Self { Self { - ptr: self.ptr, - phantom: self.phantom, + ptr: CppRef::from_ptr(ptr), + phantom: PhantomData, } } } -#[cfg(nightly)] -impl, U: ?Sized> DispatchFromDyn> 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 for regular Rust references. @@ -228,15 +222,12 @@ impl, U: ?Sized> DispatchFromDyn> for CppRef /// /// 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>, -} +pub struct CppMutRef(*mut T); -impl CppMutRef<'_, T> { +impl CppMutRef { /// Retrieve the underlying C++ pointer. pub fn as_mut_ptr(&self) -> *mut T { - self.ptr + self.0 } /// Get a regular Rust mutable reference out of this C++ reference. @@ -256,53 +247,60 @@ impl CppMutRef<'_, T> { /// 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 { - PhantomReferentMut(self.ptr) + Self(ptr) } } -impl Deref for CppMutRef<'_, T> { - type Target = *const T; +/// We implement `Deref` for `CppMutRef` so that any non-mutable +/// methods can be called on a `CppMutRef` instance. +impl Deref for CppMutRef { + type Target = CppRef; #[inline] fn deref(&self) -> &Self::Target { - // With `inline_const` we can simplify this to: - // const { panic!("you shouldn't deref CppRef!") } - struct C(T); - impl C { - const V: core::convert::Infallible = panic!("You cannot directly obtain a Rust reference from a CppMutRef. Use CppMutRef::as_mut."); - } - match C::::V {} + // Safety: `CppMutRef` and `CppRef` have the same + // layout. + unsafe { std::mem::transmute(self) } } } -impl Clone for CppMutRef<'_, T> { +impl Clone for CppMutRef { fn clone(&self) -> Self { - Self { - ptr: self.ptr, - phantom: self.phantom, - } + Self(self.0) + } +} + +impl Copy for CppMutRef {} + +impl From> for CppRef { + fn from(mutable: CppMutRef) -> Self { + Self(mutable.0) } } -impl<'a, T> From> for CppRef<'a, T> { - fn from(mutable: CppMutRef<'a, T>) -> Self { +#[repr(transparent)] +pub struct CppMutLtRef<'a, T: ?Sized> { + ptr: CppMutRef, + phantom: PhantomData<&'a mut T>, +} + +impl CppMutLtRef<'_, T> { + /// Extend the lifetime of the returned reference beyond normal Rust + /// borrow checker rules. See [`CppLtRef::lifetime_cast`]. + pub fn lifetime_cast(&mut self) -> CppMutRef { + CppMutRef(self.ptr.as_mut_ptr()) + } + + /// Create a C++ reference from a raw pointer. + pub fn from_ptr(ptr: *mut T) -> Self { Self { - ptr: mutable.ptr, - phantom: mutable.phantom, + ptr: CppMutRef::from_ptr(ptr), + phantom: PhantomData, } } } #[cfg(nightly)] -impl, U: ?Sized> DispatchFromDyn> for CppMutRef<'_, T> {} +impl, U: ?Sized> DispatchFromDyn> for CppMutRef {} /// Any type which can return a C++ reference to its contents. pub trait AsCppRef { @@ -316,9 +314,9 @@ pub trait AsCppMutRef: AsCppRef { fn as_cpp_mut_ref(&mut self) -> CppMutRef; } -impl AsCppRef for CppMutRef<'_, T> { +impl AsCppRef for CppMutRef { fn as_cpp_ref(&self) -> CppRef { - CppRef::from_ptr(self.ptr) + CppRef::from_ptr(self.0 as *const T) } } @@ -384,7 +382,9 @@ impl CppPinContents { /// /// See also [`CppUniquePtrPin`], which is equivalent for data which is in /// a [`cxx::UniquePtr`]. -pub struct CppPin(Box>); +// We also keep a `CppMutRef` to the contents for the sake of our `Deref` +// implementation. +pub struct CppPin(Box>, CppMutRef); impl CppPin { /// Imprison the Rust data within a `CppPin`. This eliminates any remaining @@ -395,7 +395,9 @@ impl CppPin { where T: Sized, { - Self(Box::new(CppPinContents(item))) + let mut contents = Box::new(CppPinContents(item)); + let ptr = contents.addr_of_mut(); + Self(contents, CppMutRef(ptr)) } /// Imprison the boxed Rust data within a `CppPin`. This eliminates any remaining @@ -412,8 +414,9 @@ impl CppPin { // to // Box> // is safe. - let contents = unsafe { std::mem::transmute::, Box>>(item) }; - Self(contents) + let mut contents = unsafe { std::mem::transmute::, Box>>(item) }; + let ptr = contents.addr_of_mut(); + Self(contents, CppMutRef(ptr)) } // Imprison the boxed Rust data within a `CppPin`. This eliminates any remaining @@ -493,6 +496,20 @@ impl AsCppMutRef for CppPin { } } +impl Deref for CppPin { + type Target = CppMutRef; + + fn deref(&self) -> &Self::Target { + &self.1 + } +} + +impl DerefMut for CppPin { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.1 + } +} + /// 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. @@ -500,14 +517,15 @@ impl AsCppMutRef for CppPin { /// 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(UniquePtr); +pub struct CppUniquePtrPin(UniquePtr, CppMutRef); impl CppUniquePtrPin { /// 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) -> Self { - Self(item) + let ptr = item.as_mut_ptr(); + Self(item, CppMutRef::from_ptr(ptr)) } /// Get an immutable pointer to the underlying object. @@ -527,46 +545,26 @@ impl AsCppRef for CppUniquePtrPin { impl AsCppMutRef for CppUniquePtrPin { fn as_cpp_mut_ref(&mut self) -> CppMutRef { - 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) + self.1.clone() } } -/// 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(*const T); +impl Deref for CppUniquePtrPin { + type Target = CppMutRef; -impl AsCppRef for PhantomReferent { - fn as_cpp_ref(&self) -> CppRef { - CppRef::from_ptr(self.0) + fn deref(&self) -> &Self::Target { + &self.1 } } -/// 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(*mut T); - -impl AsCppRef for PhantomReferentMut { +// It would be very nice to be able to impl Deref for UniquePtr +impl AsCppRef for cxx::UniquePtr { fn as_cpp_ref(&self) -> CppRef { - CppRef::from_ptr(self.0) - } -} - -impl AsCppMutRef for PhantomReferentMut { - fn as_cpp_mut_ref(&mut self) -> CppMutRef { - CppMutRef::from_ptr(self.0) + CppRef::from_ptr(self.as_ptr()) } } -#[cfg(all(feature = "arbitrary_self_types_pointers", test))] +#[cfg(all(feature = "arbitrary_self_types", test))] mod tests { use super::*; diff --git a/src/value_param.rs b/src/value_param.rs index 7386d19fb..bb837f11c 100644 --- a/src/value_param.rs +++ b/src/value_param.rs @@ -109,6 +109,8 @@ where } } +// TODO implement for CppPin and for CppRef + unsafe impl ValueParam for UniquePtr where T: UniquePtrTarget,