use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::{spanned::Spanned, ImplItemFn};
use super::ImplFns;
pub(crate) fn rewrite_moving_constructor(
output: &mut ImplFns,
mut f: ImplItemFn,
ident: &syn::Ident,
) -> Result<(), TokenStream> {
let inner_ident = format_ident!("Inner{}", ident);
let expr = match f.block.stmts.last_mut() {
Some(syn::Stmt::Expr(expr, _)) => expr,
Some(stmt) => return Err(quote::quote_spanned! { stmt.span() =>
compile_error!("[E0006, placing] invalid constructor body: functions marked `#[placing]` have to end with a struct expression"),
}.into()),
None => return Err(quote::quote_spanned! { f.block.span() =>
compile_error!("[E0005, placing] empty constructor body: functions marked `#[placing]` cannot be empty"),
}.into()),
};
match expr {
syn::Expr::Struct(strukt) => {
let fields = strukt.fields.clone();
*strukt = syn::parse2(quote! {
#ident {
inner: ::core::mem::MaybeUninit::new(#inner_ident { #fields })
}
}).unwrap();
}
expr => return Err(quote::quote_spanned! { expr.span() =>
compile_error!("[E0006, placing] invalid constructor body: functions marked `#[placing]` have to end with a struct expression"),
}.into()),
};
output.non_emplacing_constructors.push(f.into());
Ok(())
}