Skip to content

Commit

Permalink
Merge pull request #311 from dtolnay/result-box
Browse files Browse the repository at this point in the history
Fix return Result<Box<T>> from Rust to C++ [v2]
  • Loading branch information
dtolnay authored Sep 21, 2020
2 parents d22baba + 22602b4 commit 07c4832
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 36 deletions.
8 changes: 5 additions & 3 deletions gen/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -775,9 +775,11 @@ fn write_rust_function_shim_impl(
write!(out, "extern$");
}
write!(out, ")");
if let Some(ret) = &sig.ret {
if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
write!(out, ")");
if !indirect_return {
if let Some(ret) = &sig.ret {
if let Type::RustBox(_) | Type::UniquePtr(_) = ret {
write!(out, ")");
}
}
}
writeln!(out, ";");
Expand Down
66 changes: 33 additions & 33 deletions macro/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,42 +580,42 @@ fn expand_rust_function_shim_impl(
};
call.extend(quote! { (#(#vars),*) });

let mut expr = sig
.ret
.as_ref()
.and_then(|ret| match ret {
Type::Ident(ident) if ident == RustString => {
Some(quote!(::cxx::private::RustString::from(#call)))
}
Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw(#call))),
Type::RustVec(vec) => {
if vec.inner == RustString {
Some(quote!(::cxx::private::RustVec::from_vec_string(#call)))
} else {
Some(quote!(::cxx::private::RustVec::from(#call)))
}
let conversion = sig.ret.as_ref().and_then(|ret| match ret {
Type::Ident(ident) if ident == RustString => Some(quote!(::cxx::private::RustString::from)),
Type::RustBox(_) => Some(quote!(::std::boxed::Box::into_raw)),
Type::RustVec(vec) => {
if vec.inner == RustString {
Some(quote!(::cxx::private::RustVec::from_vec_string))
} else {
Some(quote!(::cxx::private::RustVec::from))
}
Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw(#call))),
Type::Ref(ty) => match &ty.inner {
Type::Ident(ident) if ident == RustString => match ty.mutability {
None => Some(quote!(::cxx::private::RustString::from_ref(#call))),
Some(_) => Some(quote!(::cxx::private::RustString::from_mut(#call))),
},
Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
None => Some(quote!(::cxx::private::RustVec::from_ref_vec_string(#call))),
Some(_) => Some(quote!(::cxx::private::RustVec::from_mut_vec_string(#call))),
},
Type::RustVec(_) => match ty.mutability {
None => Some(quote!(::cxx::private::RustVec::from_ref(#call))),
Some(_) => Some(quote!(::cxx::private::RustVec::from_mut(#call))),
},
_ => None,
}
Type::UniquePtr(_) => Some(quote!(::cxx::UniquePtr::into_raw)),
Type::Ref(ty) => match &ty.inner {
Type::Ident(ident) if ident == RustString => match ty.mutability {
None => Some(quote!(::cxx::private::RustString::from_ref)),
Some(_) => Some(quote!(::cxx::private::RustString::from_mut)),
},
Type::RustVec(vec) if vec.inner == RustString => match ty.mutability {
None => Some(quote!(::cxx::private::RustVec::from_ref_vec_string)),
Some(_) => Some(quote!(::cxx::private::RustVec::from_mut_vec_string)),
},
Type::RustVec(_) => match ty.mutability {
None => Some(quote!(::cxx::private::RustVec::from_ref)),
Some(_) => Some(quote!(::cxx::private::RustVec::from_mut)),
},
Type::Str(_) => Some(quote!(::cxx::private::RustStr::from(#call))),
Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustSliceU8::from(#call))),
_ => None,
})
.unwrap_or(call);
},
Type::Str(_) => Some(quote!(::cxx::private::RustStr::from)),
Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustSliceU8::from)),
_ => None,
});

let mut expr = match conversion {
None => call,
Some(conversion) if !sig.throws => quote!(#conversion(#call)),
Some(conversion) => quote!(::std::result::Result::map(#call, #conversion)),
};

let mut outparam = None;
let indirect_return = indirect_return(sig, types);
Expand Down
5 changes: 5 additions & 0 deletions tests/ffi/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ pub mod ffi {

fn r_try_return_void() -> Result<()>;
fn r_try_return_primitive() -> Result<usize>;
fn r_try_return_box() -> Result<Box<R>>;
fn r_fail_return_primitive() -> Result<usize>;

fn r_return_r2(n: usize) -> Box<R2>;
Expand Down Expand Up @@ -334,6 +335,10 @@ fn r_try_return_primitive() -> Result<usize, Error> {
Ok(2020)
}

fn r_try_return_box() -> Result<Box<R>, Error> {
Ok(Box::new(2020))
}

fn r_fail_return_primitive() -> Result<usize, Error> {
Err(Error)
}
Expand Down

0 comments on commit 07c4832

Please sign in to comment.