Skip to content

Commit

Permalink
Fix dyn Fn special casing
Browse files Browse the repository at this point in the history
  • Loading branch information
HKalbasi committed Oct 9, 2023
1 parent 7c9b4dd commit 9e43156
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 24 deletions.
37 changes: 36 additions & 1 deletion examples/memory_management/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// Rust values are available in the `::rust` namespace from their absolute path
// in Rust
template <typename T> using Vec = rust::std::vec::Vec<T>;
// template <typename T> using Option = rust::std::option::Option<T>;
template <typename T> using Option = rust::std::option::Option<T>;
template <typename T> using BoxDyn = rust::Box<rust::Dyn<T>>;
template <typename T> using RmDyn = rust::RefMut<rust::Dyn<T>>;
using rust::crate::consume_and_panic;
Expand Down Expand Up @@ -122,4 +122,39 @@ int main() {
std::cout << "Checkpoint 34" << std::endl;
}
std::cout << "Checkpoint 35" << std::endl;
{
auto p1 = Option<PrintOnDrop>::Some(
PrintOnDrop(rust::Str::from_char_star("option_A")));
std::cout << "Checkpoint 36" << std::endl;
auto p2 = Option<PrintOnDrop>::Some(
PrintOnDrop(rust::Str::from_char_star("option_B")));
std::cout << "Checkpoint 37" << std::endl;
p2.take();
std::cout << "Checkpoint 38" << std::endl;
p2.take();
std::cout << "Checkpoint 39" << std::endl;
}
std::cout << "Checkpoint 40" << std::endl;
{
const char *elems[3] = {"elem1", "elem2", "elem3"};
int i = 0;
auto iter = rust::std::iter::from_fn(
::rust::Box<::rust::Dyn<::rust::Fn<::rust::std::option::Option<
::rust::crate::PrintOnDrop>>>>::make_box([&] {
if (i == 3) {
return Option<PrintOnDrop>::None();
}
return Option<PrintOnDrop>::Some(
PrintOnDrop(rust::Str::from_char_star(elems[i++])));
}));
std::cout << "Checkpoint 41" << std::endl;
iter.for_each(
::rust::Box<
::rust::Dyn<::rust::Fn<::rust::crate::PrintOnDrop, rust::Unit>>>::
make_box([](PrintOnDrop p) -> rust::Unit {
std::cout << "Checkpoint 42" << std::endl;
return {};
}));
}
std::cout << "Checkpoint 43" << std::endl;
}
29 changes: 29 additions & 0 deletions examples/memory_management/main.zng
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ type str {
wellknown_traits(?Sized);
}

type Box<dyn Fn() -> ::std::option::Option<crate::PrintOnDrop>> {
#layout(size = 16, align = 8);
}

type Box<dyn Fn(crate::PrintOnDrop)> {
#layout(size = 16, align = 8);
}

mod crate {
type PrintOnDropPair {
#layout(size = 32, align = 8);
Expand Down Expand Up @@ -60,6 +68,27 @@ mod ::std {

fn unwrap(self) -> &crate::PrintOnDrop;
}

type Option<crate::PrintOnDrop> {
#layout(size = 16, align = 8);

constructor Some(crate::PrintOnDrop);
constructor None;

fn take(&mut self) -> Option<crate::PrintOnDrop>;
}
}

mod iter {
type FromFn<Box<dyn Fn() -> ::std::option::Option<crate::PrintOnDrop>>> {
#layout(size = 16, align = 8);

fn for_each<Box<dyn Fn(crate::PrintOnDrop)>>(self, Box<dyn Fn(crate::PrintOnDrop)>);
}

fn from_fn<crate::PrintOnDrop, Box<dyn Fn() -> ::std::option::Option<crate::PrintOnDrop>>>(
Box<dyn Fn() -> ::std::option::Option<crate::PrintOnDrop>>
) -> FromFn<Box<dyn Fn() -> ::std::option::Option<crate::PrintOnDrop>>>;
}

mod vec {
Expand Down
13 changes: 13 additions & 0 deletions examples/memory_management/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,17 @@ Checkpoint 33
Checkpoint 34
PrintOnDrop(dbg_A) has been dropped
Checkpoint 35
Checkpoint 36
Checkpoint 37
PrintOnDrop(option_B) has been dropped
Checkpoint 38
Checkpoint 39
PrintOnDrop(option_A) has been dropped
Checkpoint 40
Checkpoint 41
PrintOnDrop(iter_elem) has been dropped
PrintOnDrop(iter_elem) has been dropped
PrintOnDrop(iter_elem) has been dropped
Checkpoint 42
Checkpoint 43
PrintOnDrop(C) has been dropped
42 changes: 22 additions & 20 deletions zngur-generator/src/cpp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ impl CppPath {
}

fn need_header(&self) -> bool {
self.0.first().map(|x| x.as_str()) == Some("rust") && self.0 != ["rust", "Unit"]
self.0.first().map(|x| x.as_str()) == Some("rust")
&& self.0 != ["rust", "Unit"]
&& self.0 != ["rust", "Ref"]
&& self.0 != ["rust", "RefMut"]
}

pub(crate) fn from_rust_path(path: &[String]) -> CppPath {
Expand Down Expand Up @@ -107,13 +110,7 @@ impl CppType {
}
self.path.emit_in_namespace(state, |state| {
if !self.generic_args.is_empty() {
writeln!(
state,
"template<{}>",
(0..self.generic_args.len())
.map(|n| format!("typename T{n}"))
.join(", ")
)?;
writeln!(state, "template<typename ...T>")?;
}
writeln!(state, "struct {};", self.path.name())
})
Expand Down Expand Up @@ -345,16 +342,16 @@ impl CppTraitDefinition {
sig:
CppFnSig {
rust_link_name,
inputs: _,
inputs,
output: _,
},
} => {
// TODO: too special
writeln!(
state,
"void {rust_link_name}(uint8_t *data, void destructor(uint8_t *),
void call(uint8_t *, uint8_t *, uint8_t *),
uint8_t *o);"
void call(uint8_t *, {} uint8_t *),
uint8_t *o);",
(0..inputs.len()).map(|_| "uint8_t *, ").join(" ")
)?;
}
CppTraitDefinition::Normal {
Expand Down Expand Up @@ -1086,18 +1083,24 @@ namespace rust {{
}
match self.from_trait.as_ref().and_then(|k| traits.get(k)) {
Some(CppTraitDefinition::Fn { sig }) => {
// TODO: too special
let as_std_function = format!(
"::std::function<{}({})>",
sig.output,
sig.inputs.iter().join(", ")
);
let ii_args = sig
let ii_names = sig
.inputs
.iter()
.enumerate()
.map(|(n, x)| format!("::rust::__zngur_internal_move_from_rust<{x}>(i{n})"))
.join(", ");
let uint8_t_ix = sig
.inputs
.iter()
.enumerate()
.map(|(n, x)| format!("{x} ii{n} = *reinterpret_cast<{x} *>(i{n});"))
.join("\n");
.map(|(n, _)| format!("uint8_t* i{n},"))
.join(" ");
let out_ty = &sig.output;
writeln!(
state,
r#"
Expand All @@ -1108,11 +1111,10 @@ auto data = new {as_std_function}(f);
{link_name}(
reinterpret_cast<uint8_t*>(data),
[](uint8_t *d) {{ delete reinterpret_cast<{as_std_function}*>(d); }},
[](uint8_t *d, uint8_t *i0, uint8_t *o) {{
int32_t *oo = reinterpret_cast<int32_t *>(o);
{ii_args}
[](uint8_t *d, {uint8_t_ix} uint8_t *o) {{
auto dd = reinterpret_cast<{as_std_function} *>(d);
*oo = (*dd)(ii0);
{out_ty} oo = (*dd)({ii_names});
::rust::__zngur_internal_move_to_rust<{out_ty}>(o, oo);
}},
::rust::__zngur_internal_data_ptr(o));
return o;
Expand Down
16 changes: 13 additions & 3 deletions zngur-generator/src/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,16 +442,26 @@ pub extern "C" fn {mangled_name}(
pub extern "C" fn {mangled_name}(
data: *mut u8,
destructor: extern "C" fn(*mut u8),
call: extern "C" fn(data: *mut u8, i1: *mut u8, o: *mut u8),
call: extern "C" fn(data: *mut u8, {} o: *mut u8),
o: *mut u8,
) {{
let this = unsafe {{ ZngurCppOpaqueOwnedObject::new(data, destructor) }};
let r: Box<dyn {trait_str}> = Box::new(move |i0| unsafe {{
let r: Box<dyn {trait_str}> = Box::new(move |{}| unsafe {{
_ = &this;
let data = this.ptr();
"#,
inputs
.iter()
.enumerate()
.map(|(n, _)| format!("i{n}: *mut u8, "))
.join(" "),
inputs
.iter()
.enumerate()
.map(|(n, ty)| format!("i{n}: {ty}"))
.join(", "),
);
self.call_cpp_function("call(data, ", 1);
self.call_cpp_function("call(data, ", inputs.len());
wln!(
self,
r#"
Expand Down

0 comments on commit 9e43156

Please sign in to comment.