From 99d33511d7e00f98e48248cb54c476304757e963 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Sun, 9 May 2021 02:46:11 -0500 Subject: [PATCH 1/9] Add support for optional references --- gen/src/write.rs | 8 ++++++-- syntax/impls.rs | 13 ++++++++++++- syntax/mod.rs | 2 ++ syntax/parse.rs | 18 +++++++++++++++++- syntax/tokens.rs | 9 +++++++++ 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/gen/src/write.rs b/gen/src/write.rs index c6d59d8b9..3971e5754 100644 --- a/gen/src/write.rs +++ b/gen/src/write.rs @@ -769,7 +769,7 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { write!(out, "return "); } match &efn.ret { - Some(Type::Ref(_)) => write!(out, "&"), + Some(Type::Ref(ty)) if !ty.option => write!(out, "&"), Some(Type::Str(_)) if !indirect_return => { out.builtin.rust_str_repr = true; write!(out, "::rust::impl<::rust::Str>::repr("); @@ -1231,7 +1231,11 @@ fn write_type(out: &mut OutFile, ty: &Type) { } Type::Ref(r) => { write_pointee_type(out, &r.inner, r.mutable); - write!(out, " &"); + if r.option { + write!(out, " *") + } else { + write!(out, " &"); + } } Type::Ptr(p) => { write_pointee_type(out, &p.inner, p.mutable); diff --git a/syntax/impls.rs b/syntax/impls.rs index 06d68dc22..a99d61b74 100644 --- a/syntax/impls.rs +++ b/syntax/impls.rs @@ -152,23 +152,31 @@ impl PartialEq for Ref { fn eq(&self, other: &Self) -> bool { let Ref { pinned, + option, ampersand: _, lifetime, mutable, inner, pin_tokens: _, + option_tokens: _, mutability: _, } = self; let Ref { pinned: pinned2, + option: option2, ampersand: _, lifetime: lifetime2, mutable: mutable2, inner: inner2, pin_tokens: _, + option_tokens: _, mutability: _, } = other; - pinned == pinned2 && lifetime == lifetime2 && mutable == mutable2 && inner == inner2 + pinned == pinned2 + && option == option2 + && lifetime == lifetime2 + && mutable == mutable2 + && inner == inner2 } } @@ -176,14 +184,17 @@ impl Hash for Ref { fn hash(&self, state: &mut H) { let Ref { pinned, + option, ampersand: _, lifetime, mutable, inner, pin_tokens: _, + option_tokens: _, mutability: _, } = self; pinned.hash(state); + option.hash(state); lifetime.hash(state); mutable.hash(state); inner.hash(state); diff --git a/syntax/mod.rs b/syntax/mod.rs index 1d9863455..f5514ca4c 100644 --- a/syntax/mod.rs +++ b/syntax/mod.rs @@ -231,11 +231,13 @@ pub struct Ty1 { pub struct Ref { pub pinned: bool, + pub option: bool, pub ampersand: Token![&], pub lifetime: Option, pub mutable: bool, pub inner: Type, pub pin_tokens: Option<(kw::Pin, Token![<], Token![>])>, + pub option_tokens: Option<(kw::Option, Token![<], Token![>])>, pub mutability: Option, } diff --git a/syntax/parse.rs b/syntax/parse.rs index 32d36eb34..e3ab6cf8b 100644 --- a/syntax/parse.rs +++ b/syntax/parse.rs @@ -1,8 +1,8 @@ -use crate::syntax::attrs::OtherAttrs; use crate::syntax::discriminant::DiscriminantSet; use crate::syntax::file::{Item, ItemForeignMod}; use crate::syntax::report::Errors; use crate::syntax::Atom::*; +use crate::syntax::OtherAttrs; use crate::syntax::{ attrs, error, Api, Array, Derive, Doc, Enum, EnumRepr, ExternFn, ExternType, ForeignName, Impl, Include, IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Ptr, Receiver, Ref, @@ -22,6 +22,7 @@ use syn::{ }; pub mod kw { + syn::custom_keyword!(Option); syn::custom_keyword!(Pin); syn::custom_keyword!(Result); } @@ -1080,7 +1081,9 @@ fn parse_type_reference(ty: &TypeReference) -> Result { let inner = parse_type(&ty.elem)?; let pinned = false; + let option = false; let pin_tokens = None; + let option_tokens = None; Ok(match &inner { Type::Ident(ident) if ident.rust == "str" => { @@ -1093,11 +1096,13 @@ fn parse_type_reference(ty: &TypeReference) -> Result { _ => Type::Ref, }(Box::new(Ref { pinned, + option, ampersand, lifetime, mutable, inner, pin_tokens, + option_tokens, mutability, }))) } @@ -1198,6 +1203,17 @@ fn parse_type_path(ty: &TypePath) -> Result { return Ok(Type::Ref(inner)); } } + } else if ident == "Option" && generic.args.len() == 1 { + if let GenericArgument::Type(arg) = &generic.args[0] { + let inner = parse_type(arg)?; + let option_token = kw::Option(ident.span()); + if let Type::Ref(mut inner) = inner { + inner.option = true; + inner.option_tokens = + Some((option_token, generic.lt_token, generic.gt_token)); + return Ok(Type::Ref(inner)); + } + } } else { let mut lifetimes = Punctuated::new(); let mut only_lifetimes = true; diff --git a/syntax/tokens.rs b/syntax/tokens.rs index 33f20fa3c..0d4aeebbd 100644 --- a/syntax/tokens.rs +++ b/syntax/tokens.rs @@ -81,13 +81,19 @@ impl ToTokens for Ref { fn to_tokens(&self, tokens: &mut TokenStream) { let Ref { pinned: _, + option: _, ampersand, lifetime, mutable: _, inner, pin_tokens, + option_tokens, mutability, } = self; + if let Some((option, langle, _rangle)) = option_tokens { + tokens.extend(quote_spanned!(option.span=> ::std::option::Option)); + langle.to_tokens(tokens); + } if let Some((pin, langle, _rangle)) = pin_tokens { tokens.extend(quote_spanned!(pin.span=> ::std::pin::Pin)); langle.to_tokens(tokens); @@ -99,6 +105,9 @@ impl ToTokens for Ref { if let Some((_pin, _langle, rangle)) = pin_tokens { rangle.to_tokens(tokens); } + if let Some((_option, _langle, rangle)) = option_tokens { + rangle.to_tokens(tokens); + } } } From a8e1a73c5a9d0a873d5ae4bdf9310a80722ec85e Mon Sep 17 00:00:00 2001 From: CAD97 Date: Sun, 9 May 2021 12:54:58 -0500 Subject: [PATCH 2/9] Test use of optional ref --- macro/src/expand.rs | 11 ++++++++--- tests/ffi/lib.rs | 2 ++ tests/ffi/tests.cc | 10 ++++++++++ tests/ffi/tests.h | 2 ++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/macro/src/expand.rs b/macro/src/expand.rs index bc3f000d6..0dc018b31 100644 --- a/macro/src/expand.rs +++ b/macro/src/expand.rs @@ -531,11 +531,16 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { false => quote!(#var), true => quote_spanned!(span=> ::std::pin::Pin::into_inner_unchecked(#var)), }; - match ty.mutable { + let to_ptr = match ty.mutable { false => { - quote_spanned!(span=> #var as *const #inner as *const ::std::ffi::c_void) + quote_spanned!(span=> |var| var as *const #inner as *const ::std::ffi::c_void) } - true => quote_spanned!(span=> #var as *mut #inner as *mut ::std::ffi::c_void), + true => quote_spanned!(span=> |var| var as *mut #inner as *mut ::std::ffi::c_void), + }; + match (ty.option, ty.mutable) { + (false, _) => quote_spanned!(span=> (#to_ptr)(#var)), + (true, false) => quote_spanned!(span=> #var.map_or(::std::ptr::null(), #to_ptr)), + (true, true) => quote_spanned!(span=> #var.map_or(::std::ptr::null_mut(), #to_ptr)), } } _ => quote!(#var), diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs index 25b4ccdc8..bc9f6fb6f 100644 --- a/tests/ffi/lib.rs +++ b/tests/ffi/lib.rs @@ -99,6 +99,7 @@ pub mod ffi { fn c_return_shared_ptr() -> SharedPtr; fn c_return_ref(shared: &Shared) -> &usize; fn c_return_mut(shared: &mut Shared) -> &mut usize; + fn c_return_opt(shared: &Shared) -> Option<&usize>; fn c_return_str(shared: &Shared) -> &str; fn c_return_slice_char(shared: &Shared) -> &[c_char]; fn c_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8]; @@ -130,6 +131,7 @@ pub mod ffi { fn c_take_box(r: Box); fn c_take_ref_r(r: &R); fn c_take_ref_c(c: &C); + fn c_take_opt_r(r: Option<&R>); fn c_take_str(s: &str); fn c_take_slice_char(s: &[c_char]); fn c_take_slice_shared(s: &[Shared]); diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc index ff215ca00..b890926e8 100644 --- a/tests/ffi/tests.cc +++ b/tests/ffi/tests.cc @@ -94,6 +94,8 @@ const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared) { size_t &c_return_mut(Shared &shared) { return shared.z; } +const size_t *c_return_opt(const Shared &shared) { return &shared.z; } + rust::Str c_return_str(const Shared &shared) { (void)shared; return "2020"; @@ -269,6 +271,14 @@ void c_take_ref_c(const C &c) { } } +void c_take_opt_r(const R *r) { + if (r) { + c_take_ref_r(*r); + } else { + cxx_test_suite_set_correct(); + } +} + void c_take_ref_ns_c(const ::H::H &h) { if (h.h == "hello") { cxx_test_suite_set_correct(); diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h index b624d3933..e108bf923 100644 --- a/tests/ffi/tests.h +++ b/tests/ffi/tests.h @@ -96,6 +96,7 @@ const size_t &c_return_ref(const Shared &shared); const size_t &c_return_ns_ref(const ::A::AShared &shared); const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared); size_t &c_return_mut(Shared &shared); +const size_t *c_return_opt(const Shared &shared); rust::Str c_return_str(const Shared &shared); rust::Slice c_return_slice_char(const Shared &shared); rust::Slice c_return_mutsliceu8(rust::Slice slice); @@ -129,6 +130,7 @@ void c_take_box(rust::Box r); void c_take_unique_ptr(std::unique_ptr c); void c_take_ref_r(const R &r); void c_take_ref_c(const C &c); +void c_take_opt_r(const R *r); void c_take_ref_ns_c(const ::H::H &h); void c_take_str(rust::Str s); void c_take_slice_char(rust::Slice s); From 5ea1d74cb249268b445687cbc32d386e53314e19 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Sun, 9 May 2021 13:09:21 -0500 Subject: [PATCH 3/9] Fix clippy::redundant-closure-call in emitted code --- macro/src/expand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macro/src/expand.rs b/macro/src/expand.rs index 0dc018b31..9b585eeb8 100644 --- a/macro/src/expand.rs +++ b/macro/src/expand.rs @@ -538,7 +538,7 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { true => quote_spanned!(span=> |var| var as *mut #inner as *mut ::std::ffi::c_void), }; match (ty.option, ty.mutable) { - (false, _) => quote_spanned!(span=> (#to_ptr)(#var)), + (false, _) => quote_spanned!(span=> #[allow(clippy::redundant_closure_call)] (#to_ptr)(#var)), (true, false) => quote_spanned!(span=> #var.map_or(::std::ptr::null(), #to_ptr)), (true, true) => quote_spanned!(span=> #var.map_or(::std::ptr::null_mut(), #to_ptr)), } From 61db41dfdb236a48ed11fa583841cb8fff0095ff Mon Sep 17 00:00:00 2001 From: CAD97 Date: Sun, 9 May 2021 13:26:53 -0500 Subject: [PATCH 4/9] Add tests for opt ref mut --- tests/ffi/lib.rs | 6 ++++-- tests/ffi/tests.cc | 14 ++++++++++++-- tests/ffi/tests.h | 6 ++++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs index bc9f6fb6f..4c717f9c0 100644 --- a/tests/ffi/lib.rs +++ b/tests/ffi/lib.rs @@ -99,7 +99,8 @@ pub mod ffi { fn c_return_shared_ptr() -> SharedPtr; fn c_return_ref(shared: &Shared) -> &usize; fn c_return_mut(shared: &mut Shared) -> &mut usize; - fn c_return_opt(shared: &Shared) -> Option<&usize>; + fn c_return_opt_ref(shared: &Shared) -> Option<&usize>; + fn c_return_opt_mut(shared: &mut Shared) -> Option<&mut usize>; fn c_return_str(shared: &Shared) -> &str; fn c_return_slice_char(shared: &Shared) -> &[c_char]; fn c_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8]; @@ -131,7 +132,8 @@ pub mod ffi { fn c_take_box(r: Box); fn c_take_ref_r(r: &R); fn c_take_ref_c(c: &C); - fn c_take_opt_r(r: Option<&R>); + fn c_take_opt_ref_r(r: Option<&R>); + fn c_take_opt_mut_r(r: Option<&mut R>); fn c_take_str(s: &str); fn c_take_slice_char(s: &[c_char]); fn c_take_slice_shared(s: &[Shared]); diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc index b890926e8..0b881699d 100644 --- a/tests/ffi/tests.cc +++ b/tests/ffi/tests.cc @@ -94,7 +94,9 @@ const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared) { size_t &c_return_mut(Shared &shared) { return shared.z; } -const size_t *c_return_opt(const Shared &shared) { return &shared.z; } +const size_t *c_return_opt_ref(const Shared &shared) { return &shared.z; } + +size_t *c_return_opt_mut(Shared &shared) { return &shared.z; } rust::Str c_return_str(const Shared &shared) { (void)shared; @@ -271,7 +273,15 @@ void c_take_ref_c(const C &c) { } } -void c_take_opt_r(const R *r) { +void c_take_opt_ref_r(const R *r) { + if (r) { + c_take_ref_r(*r); + } else { + cxx_test_suite_set_correct(); + } +} + +void c_take_opt_mut_r(R *r) { if (r) { c_take_ref_r(*r); } else { diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h index e108bf923..fba80b074 100644 --- a/tests/ffi/tests.h +++ b/tests/ffi/tests.h @@ -96,7 +96,8 @@ const size_t &c_return_ref(const Shared &shared); const size_t &c_return_ns_ref(const ::A::AShared &shared); const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared); size_t &c_return_mut(Shared &shared); -const size_t *c_return_opt(const Shared &shared); +const size_t *c_return_opt_ref(const Shared &shared); +size_t *c_return_opt_mut(Shared &shared); rust::Str c_return_str(const Shared &shared); rust::Slice c_return_slice_char(const Shared &shared); rust::Slice c_return_mutsliceu8(rust::Slice slice); @@ -130,7 +131,8 @@ void c_take_box(rust::Box r); void c_take_unique_ptr(std::unique_ptr c); void c_take_ref_r(const R &r); void c_take_ref_c(const C &c); -void c_take_opt_r(const R *r); +void c_take_opt_ref_r(const R *r); +void c_take_opt_mut_r(R *r); void c_take_ref_ns_c(const ::H::H &h); void c_take_str(rust::Str s); void c_take_slice_char(rust::Slice s); From 3c05a6bdf56dcb3d35d82c53b2d254a82536426c Mon Sep 17 00:00:00 2001 From: CAD97 Date: Fri, 14 May 2021 01:14:34 -0500 Subject: [PATCH 5/9] Add more optional reference tests --- tests/ffi/lib.rs | 2 ++ tests/ffi/module.rs | 4 ++++ tests/ffi/tests.cc | 24 ++++++++++++++++++++++++ tests/ffi/tests.h | 6 ++++++ 4 files changed, 36 insertions(+) diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs index 4c717f9c0..561edb99c 100644 --- a/tests/ffi/lib.rs +++ b/tests/ffi/lib.rs @@ -134,6 +134,8 @@ pub mod ffi { fn c_take_ref_c(c: &C); fn c_take_opt_ref_r(r: Option<&R>); fn c_take_opt_mut_r(r: Option<&mut R>); + fn c_take_opt_ref_c(r: Option<&C>); + fn c_take_opt_mut_c(r: Option>); fn c_take_str(s: &str); fn c_take_slice_char(s: &[c_char]); fn c_take_slice_shared(s: &[Shared]); diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs index 21a86206d..f3cd5ecc7 100644 --- a/tests/ffi/module.rs +++ b/tests/ffi/module.rs @@ -35,6 +35,10 @@ pub mod ffi2 { fn c_take_trivial_mut_ref(d: &mut D); fn c_take_trivial_pin_ref(d: Pin<&D>); fn c_take_trivial_pin_mut_ref(d: Pin<&mut D>); + fn c_take_trivial_opt_ref(d: Option<&D>); + fn c_take_trivial_opt_mut_ref(d: Option<&mut D>); + fn c_take_trivial_opt_pin_ref(d: Option>); + fn c_take_trivial_opt_pin_mut_ref(d: Option>); fn c_take_trivial_ref_method(self: &D); fn c_take_trivial_mut_ref_method(self: &mut D); fn c_take_trivial(d: D); diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc index 0b881699d..da485c0cd 100644 --- a/tests/ffi/tests.cc +++ b/tests/ffi/tests.cc @@ -289,6 +289,22 @@ void c_take_opt_mut_r(R *r) { } } +void c_take_opt_ref_c(const C *c) { + if (c) { + c_take_ref_c(*c); + } else { + cxx_test_suite_set_correct(); + } +} + +void c_take_opt_mut_c(C *c) { + if (c) { + c_take_ref_c(*c); + } else { + cxx_test_suite_set_correct(); + } +} + void c_take_ref_ns_c(const ::H::H &h) { if (h.h == "hello") { cxx_test_suite_set_correct(); @@ -640,6 +656,14 @@ void c_take_trivial_pin_ref(const D &d) { (void)d; } void c_take_trivial_pin_mut_ref(D &d) { (void)d; } +void c_take_trivial_opt_ref(const D *d) { (void)d; } + +void c_take_trivial_opt_mut_ref(D *d) { (void)d; } + +void c_take_trivial_opt_pin_ref(const D *d) { (void)d; } + +void c_take_trivial_opt_pin_mut_ref(D *d) { (void)d; } + void D::c_take_trivial_ref_method() const { if (d == 30) { cxx_test_suite_set_correct(); diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h index fba80b074..efd83d635 100644 --- a/tests/ffi/tests.h +++ b/tests/ffi/tests.h @@ -133,6 +133,8 @@ void c_take_ref_r(const R &r); void c_take_ref_c(const C &c); void c_take_opt_ref_r(const R *r); void c_take_opt_mut_r(R *r); +void c_take_opt_ref_c(const C *c); +void c_take_opt_mut_c(C *c); void c_take_ref_ns_c(const ::H::H &h); void c_take_str(rust::Str s); void c_take_slice_char(rust::Slice s); @@ -193,6 +195,10 @@ void c_take_trivial_ref(const D &d); void c_take_trivial_mut_ref(D &d); void c_take_trivial_pin_ref(const D &d); void c_take_trivial_pin_mut_ref(D &d); +void c_take_trivial_opt_ref(const D *d); +void c_take_trivial_opt_mut_ref(D *d); +void c_take_trivial_opt_pin_ref(const D *d); +void c_take_trivial_opt_pin_mut_ref(D *d); void c_take_trivial(D d); void c_take_trivial_ns_ptr(std::unique_ptr<::G::G> g); From ee51314c93ba5449bc76b8e04387ab9719fea0a8 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Fri, 14 May 2021 01:48:50 -0500 Subject: [PATCH 6/9] Fix Option> argument handling --- macro/src/expand.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/macro/src/expand.rs b/macro/src/expand.rs index 9b585eeb8..eb55d629b 100644 --- a/macro/src/expand.rs +++ b/macro/src/expand.rs @@ -527,16 +527,15 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { true => quote_spanned!(span=> ::cxx::private::RustVec::from_mut(#var)), }, inner if types.is_considered_improper_ctype(inner) => { - let var = match ty.pinned { - false => quote!(#var), - true => quote_spanned!(span=> ::std::pin::Pin::into_inner_unchecked(#var)), + let unpin = match ty.pinned { + false => quote!(), + true => quote_spanned!(span=> ::std::pin::Pin::into_inner_unchecked), }; - let to_ptr = match ty.mutable { - false => { - quote_spanned!(span=> |var| var as *const #inner as *const ::std::ffi::c_void) - } - true => quote_spanned!(span=> |var| var as *mut #inner as *mut ::std::ffi::c_void), + let raw_mutability = match ty.mutable { + false => quote_spanned!(span=> const), + true => quote_spanned!(span=> mut), }; + let to_ptr = quote_spanned!(span=> |var| #unpin(var) as *#raw_mutability #inner as *#raw_mutability ::std::ffi::c_void); match (ty.option, ty.mutable) { (false, _) => quote_spanned!(span=> #[allow(clippy::redundant_closure_call)] (#to_ptr)(#var)), (true, false) => quote_spanned!(span=> #var.map_or(::std::ptr::null(), #to_ptr)), From 957e0b9542ef6d7e1fc9158c6945ddfa5d46559a Mon Sep 17 00:00:00 2001 From: CAD97 Date: Fri, 14 May 2021 02:07:48 -0500 Subject: [PATCH 7/9] Add more optional reference tests --- tests/ffi/module.rs | 1 + tests/ffi/tests.cc | 2 ++ tests/ffi/tests.h | 1 + 3 files changed, 4 insertions(+) diff --git a/tests/ffi/module.rs b/tests/ffi/module.rs index f3cd5ecc7..67203854b 100644 --- a/tests/ffi/module.rs +++ b/tests/ffi/module.rs @@ -60,6 +60,7 @@ pub mod ffi2 { fn c_return_ns_opaque_ptr() -> UniquePtr; fn c_return_ns_unique_ptr() -> UniquePtr; fn c_take_ref_ns_c(h: &H); + fn c_roundtrip_opaque_opt_mut_pin_ref(e: Option>) -> Option>; #[namespace = "other"] fn ns_c_take_trivial(d: D); diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc index da485c0cd..1da8f9bbb 100644 --- a/tests/ffi/tests.cc +++ b/tests/ffi/tests.cc @@ -311,6 +311,8 @@ void c_take_ref_ns_c(const ::H::H &h) { } } +E *c_roundtrip_opaque_opt_mut_pin_ref(E *e) { return e; } + void c_take_str(rust::Str s) { if (std::string(s) == "2020") { cxx_test_suite_set_correct(); diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h index efd83d635..47cf81f0c 100644 --- a/tests/ffi/tests.h +++ b/tests/ffi/tests.h @@ -136,6 +136,7 @@ void c_take_opt_mut_r(R *r); void c_take_opt_ref_c(const C *c); void c_take_opt_mut_c(C *c); void c_take_ref_ns_c(const ::H::H &h); +E *c_roundtrip_opaque_opt_mut_pin_ref(E *e); void c_take_str(rust::Str s); void c_take_slice_char(rust::Slice s); void c_take_slice_shared(rust::Slice s); From 2d4bc0cc8bd9591a5668e2f5d18234fa15761aea Mon Sep 17 00:00:00 2001 From: CAD97 Date: Fri, 14 May 2021 02:08:12 -0500 Subject: [PATCH 8/9] Fix Option> return handling --- macro/src/expand.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/macro/src/expand.rs b/macro/src/expand.rs index eb55d629b..966c2c7eb 100644 --- a/macro/src/expand.rs +++ b/macro/src/expand.rs @@ -659,12 +659,24 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream { }, inner if types.is_considered_improper_ctype(inner) => { let mutability = ty.mutability; - let deref_mut = quote_spanned!(span=> &#mutability *#call.cast()); - match ty.pinned { - false => deref_mut, + let call = quote_spanned!(span=> let __ptr = #call); + let unpinned = quote_spanned!(span=> &#mutability *__ptr.cast()); + let maybe_pinned = match ty.pinned { + false => unpinned, true => { - quote_spanned!(span=> ::std::pin::Pin::new_unchecked(#deref_mut)) + quote_spanned!(span=> ::std::pin::Pin::new_unchecked(#unpinned)) } + }; + match ty.option { + false => quote_spanned!(span=> #call; #maybe_pinned), + true => quote_spanned! {span=> + #call; + if __ptr.is_null() { + ::std::option::Option::None + } else { + ::std::option::Option::Some(#maybe_pinned) + } + }, } } _ => call, From be37b9d5fff3929ca328861e3c31179fa90f16c9 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Fri, 14 May 2021 02:24:29 -0500 Subject: [PATCH 9/9] Add ui test for Option> --- tests/ui/option_option.rs | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/ui/option_option.rs diff --git a/tests/ui/option_option.rs b/tests/ui/option_option.rs new file mode 100644 index 000000000..4632f0265 --- /dev/null +++ b/tests/ui/option_option.rs @@ -0,0 +1,8 @@ +#[cxx::bridge] +mod ffi { + extern "C++" { + unsafe fn f(_: Option>); + } +} + +fn main() {}