diff --git a/Cargo.toml b/Cargo.toml index 6792426..3ac7e74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,3 +3,4 @@ members = [ "metastruct", "metastruct_macro", ] +resolver = "2" diff --git a/metastruct_macro/src/mapping.rs b/metastruct_macro/src/mapping.rs index b167a2d..c07db3f 100644 --- a/metastruct_macro/src/mapping.rs +++ b/metastruct_macro/src/mapping.rs @@ -29,13 +29,13 @@ pub(crate) fn generate_mapping_macro( quote! { ref } }; - let mapping_function_types = selected_field_types + let mapping_function_input_types = selected_field_types .iter() .map(|field_type| { if mapping_opts.mutable { - quote! { &mut dyn FnMut(usize, &'_ mut #field_type) -> _ } + quote! { mut #field_type } } else { - quote! { &mut dyn FnMut(usize, &'_ #field_type) -> _ } + quote! { #field_type } } }) .collect::>(); @@ -54,7 +54,7 @@ pub(crate) fn generate_mapping_macro( quote! { #[macro_export] macro_rules! #macro_name { - ($v:expr, $f:expr) => { + (&$lifetime:tt _, $v:expr, $f:expr) => { match $v { #type_name { #( @@ -64,13 +64,16 @@ pub(crate) fn generate_mapping_macro( } => { let mut __metastruct_i: usize = 0; #( - let __metastruct_f: #mapping_function_types = &mut $f; + let __metastruct_f: &mut dyn FnMut(usize, &$lifetime #mapping_function_input_types) -> _ = &mut $f; #function_call_exprs; __metastruct_i += 1; )* } } - } + }; + ($v:expr, $f:expr) => { + #macro_name!(&'_ _, $v, $f) + }; } } .into() diff --git a/metastruct_macro/tests/lifetime.rs b/metastruct_macro/tests/lifetime.rs new file mode 100644 index 0000000..90769f9 --- /dev/null +++ b/metastruct_macro/tests/lifetime.rs @@ -0,0 +1,20 @@ +use metastruct_macro::metastruct; + +#[metastruct(mappings(map_foo_fields()))] +struct Foo { + x: u64, + y: u16, + z: u32, +} + +fn sum<'a>(total: &'a mut u64, foo: &'a Foo) { + map_foo_fields!(&'a _, foo, |_, field| *total += *field as u64); +} + +#[test] +fn reference_with_lifetime() { + let foo = Foo { x: 1, y: 2, z: 3 }; + let mut total = 0; + sum(&mut total, &foo); + assert_eq!(total, 6); +}