diff --git a/examples/src/ok_tests.rs b/examples/src/ok_tests.rs index 48a81b1..61ae346 100644 --- a/examples/src/ok_tests.rs +++ b/examples/src/ok_tests.rs @@ -179,6 +179,16 @@ fn try_new_recover_heads() { } } +#[test] +fn into_heads() { + let bar = BoxAndRefBuilder { + data: 12, + dref_builder: |data| data, + } + .build(); + assert!(bar.into_heads().data == 12); +} + #[test] fn box_and_mut_ref() { let mut bar = BoxAndMutRefBuilder { diff --git a/ouroboros_macro/src/generate/into_heads.rs b/ouroboros_macro/src/generate/into_heads.rs index 7b4b122..5784e46 100644 --- a/ouroboros_macro/src/generate/into_heads.rs +++ b/ouroboros_macro/src/generate/into_heads.rs @@ -3,8 +3,8 @@ use quote::quote; use crate::info_structures::{Options, StructInfo}; -/// Returns the Heads struct. -pub fn make_heads(info: &StructInfo, options: Options) -> TokenStream { +/// Returns the Heads struct and a function to convert the original struct into a Heads instance. +pub fn make_into_heads(info: &StructInfo, options: Options) -> (TokenStream, TokenStream) { let visibility = if options.do_pub_extras { info.vis.clone() } else { @@ -51,6 +51,31 @@ pub fn make_heads(info: &StructInfo, options: Options) -> TokenStream { #(#head_fields),* } }; + let documentation = concat!( + "This function drops all internally referencing fields and returns only the ", + "[head fields](https://docs.rs/ouroboros/latest/ouroboros/attr.self_referencing.html#definitions) of this struct." + ).to_owned(); - heads_struct_def + let documentation = if !options.do_no_doc { + quote! { + #[doc=#documentation] + } + } else { + quote! { #[doc(hidden)] } + }; + + let generic_args = info.generic_arguments(); + let into_heads_fn = quote! { + #documentation + #[allow(clippy::drop_ref)] + #[allow(clippy::drop_copy)] + #[allow(clippy::drop_non_drop)] + #visibility fn into_heads(self) -> Heads<#(#generic_args),*> { + #(#code)* + Heads { + #(#field_initializers),* + } + } + }; + (heads_struct_def, into_heads_fn) } diff --git a/ouroboros_macro/src/lib.rs b/ouroboros_macro/src/lib.rs index f531fb5..cd12419 100644 --- a/ouroboros_macro/src/lib.rs +++ b/ouroboros_macro/src/lib.rs @@ -9,7 +9,7 @@ mod utils; use crate::{ generate::{ constructor::create_builder_and_constructor, derives::create_derives, - into_heads::make_heads, struc::create_actual_struct_def, + into_heads::make_into_heads, struc::create_actual_struct_def, summon_checker::generate_checker_summoner, try_constructor::create_try_builder_and_constructor, type_asserts::make_type_asserts, with_all::make_with_all_function, with_each::make_with_functions, @@ -50,15 +50,12 @@ fn self_referencing_impl( create_try_builder_and_constructor(&info, options, BuilderType::Sync)?; let (async_try_builder_struct_name, async_try_builder_def, async_try_constructor_def) = create_try_builder_and_constructor(&info, options, BuilderType::Async)?; - let ( - async_send_try_builder_struct_name, - async_send_try_builder_def, - async_send_try_constructor_def, - ) = create_try_builder_and_constructor(&info, options, BuilderType::AsyncSend)?; + let (async_send_try_builder_struct_name, async_send_try_builder_def, async_send_try_constructor_def) = + create_try_builder_and_constructor(&info, options, BuilderType::AsyncSend)?; let with_defs = make_with_functions(&info, options)?; let (with_all_struct_defs, with_all_fn_defs) = make_with_all_function(&info, options)?; - let heads_struct_def = make_heads(&info, options); + let (heads_struct_def, into_heads_fn) = make_into_heads(&info, options); let impls = create_derives(&info)?; @@ -100,6 +97,7 @@ fn self_referencing_impl( #async_send_try_constructor_def #(#with_defs)* #with_all_fn_defs + #into_heads_fn } #type_asserts_def }