Skip to main content

plusplus_macros/
lib.rs

1use proc_macro_crate::{FoundCrate, crate_name};
2use proc_macro2::{Span, TokenStream};
3use quote::{format_ident, quote};
4use syn::parse::{Parse, ParseStream};
5use syn::spanned::Spanned;
6use syn::token::Brace;
7use syn::{
8    AngleBracketedGenericArguments, AttrStyle, CapturedParam, Error, GenericArgument, GenericParam,
9    Lifetime, LifetimeParam, MacroDelimiter, Meta, Path, PathArguments, ReturnType, Signature,
10    Token, TypeParamBound, parse2,
11};
12use syn::{
13    Attribute, Field, FnArg, Ident, ImplItemFn, Pat, Type, Visibility, braced, parse_macro_input,
14    parse_quote,
15};
16
17mod kw {
18    syn::custom_keyword!(class);
19}
20
21#[derive(Debug, Clone)]
22struct OverrideItem {
23    _override_token: Token![override],
24    override_class: Type,
25    _brace_token: Brace,
26    items: Vec<ImplItemFn>,
27}
28
29fn correct_priv_vis(vis: Visibility) -> Visibility {
30    match vis {
31        Visibility::Public(p) => Visibility::Public(p),
32        Visibility::Restricted(mut restricted) => {
33            if restricted.path.segments.get(0) != Some(&parse_quote!(crate)) {
34                restricted.path.segments.insert(0, parse_quote!(super));
35            }
36            Visibility::Restricted(restricted)
37        }
38        Visibility::Inherited => {
39            parse_quote!(pub(super))
40        }
41    }
42}
43
44impl Parse for OverrideItem {
45    fn parse(input: ParseStream) -> syn::Result<Self> {
46        let content;
47        let override_token = input.parse()?;
48        let override_class = input.parse()?;
49        let brace_token = braced!(content in input);
50        let mut items = Vec::new();
51        while !content.is_empty() {
52            let mut item: ImplItemFn = content.parse()?;
53            item.vis = correct_priv_vis(item.vis);
54            items.push(item);
55        }
56
57        Ok(OverrideItem {
58            _override_token: override_token,
59            override_class,
60            _brace_token: brace_token,
61            items,
62        })
63    }
64}
65
66#[derive(Debug, Clone)]
67enum ClassItem {
68    Field {
69        field: Field,
70        _semi_token: Token![;],
71    },
72    ImplItemFn(ImplItemFn),
73    OverrideItem(OverrideItem),
74}
75
76impl Parse for ClassItem {
77    fn parse(input: ParseStream) -> syn::Result<Self> {
78        let lookahead = input.lookahead1();
79        if lookahead.peek(Token![override]) {
80            return Ok(ClassItem::OverrideItem(OverrideItem::parse(input)?));
81        }
82
83        let begin = input.fork();
84        let _attrs = input.call(Attribute::parse_outer)?;
85        let _vis: Visibility = begin.parse()?;
86        let lookahead = begin.lookahead1();
87        if lookahead.peek(Token![fn])
88            || lookahead.peek(Token![unsafe])
89            || lookahead.peek(Token![async])
90        {
91            return Ok(ClassItem::ImplItemFn(ImplItemFn::parse(input)?));
92        }
93
94        let mut field = Field::parse_named(input)?;
95        field.vis = correct_priv_vis(field.vis);
96        let semi_token = input.parse()?;
97        Ok(ClassItem::Field {
98            field,
99            _semi_token: semi_token,
100        })
101    }
102}
103
104#[derive(Debug, Clone)]
105struct SuperclassInput {
106    _colon_token: Token![:],
107    ty: Type,
108}
109
110impl Parse for SuperclassInput {
111    fn parse(input: ParseStream) -> syn::Result<Self> {
112        Ok(SuperclassInput {
113            _colon_token: input.parse()?,
114            ty: input.parse()?,
115        })
116    }
117}
118
119#[derive(Debug, Clone)]
120struct ClassInput {
121    attrs: Vec<Attribute>,
122    vis: Visibility,
123    _class_token: kw::class,
124    ident: Ident,
125    superclass: Option<SuperclassInput>,
126    _brace_token: Brace,
127    items: Vec<ClassItem>,
128}
129
130impl Parse for ClassInput {
131    fn parse(input: ParseStream) -> syn::Result<Self> {
132        let attrs = input.call(Attribute::parse_outer)?;
133        let content;
134        let vis = input.parse()?;
135        let class_token = input.parse()?;
136        let ident = input.parse()?;
137
138        let lookahead = input.lookahead1();
139        let superclass = if lookahead.peek(Token![:]) {
140            Some(input.parse()?)
141        } else {
142            None
143        };
144
145        let brace_token = braced!(content in input);
146        let mut items = Vec::new();
147        while !content.is_empty() {
148            items.push(content.parse()?);
149        }
150        Ok(ClassInput {
151            attrs,
152            vis,
153            _class_token: class_token,
154            ident,
155            superclass,
156            _brace_token: brace_token,
157            items,
158        })
159    }
160}
161
162#[derive(Debug, Clone)]
163struct CrateAlias {
164    _crate_token: Token![crate],
165    _as_token: Token![as],
166    ident: Ident,
167    _semi_token: Token![;],
168}
169
170impl Parse for CrateAlias {
171    fn parse(input: ParseStream) -> syn::Result<Self> {
172        Ok(CrateAlias {
173            _crate_token: input.parse()?,
174            _as_token: input.parse()?,
175            ident: input.parse()?,
176            _semi_token: input.parse()?,
177        })
178    }
179}
180
181struct ClassInputs {
182    crate_alias: Option<CrateAlias>,
183    inputs: Vec<ClassInput>,
184}
185
186impl Parse for ClassInputs {
187    fn parse(input: ParseStream) -> syn::Result<Self> {
188        let lookahead = input.lookahead1();
189        let crate_alias = if lookahead.peek(Token![crate]) {
190            Some(input.parse()?)
191        } else {
192            None
193        };
194
195        let mut inputs = Vec::new();
196        while !input.is_empty() {
197            inputs.push(input.parse()?);
198        }
199
200        Ok(ClassInputs {
201            crate_alias,
202            inputs,
203        })
204    }
205}
206
207fn plusplus() -> proc_macro2::TokenStream {
208    let found_crate = crate_name("plusplus").expect("plusplus is present in `Cargo.toml`");
209    match found_crate {
210        FoundCrate::Itself => quote!(crate),
211        FoundCrate::Name(name) => {
212            let ident = Ident::new(&name, Span::call_site());
213            quote!( #ident )
214        }
215    }
216}
217
218fn cast_class_ptr(
219    plusplus: &proc_macro2::TokenStream,
220    from: &Type,
221    to: &Type,
222    expr: impl Into<proc_macro2::TokenStream>,
223) -> proc_macro2::TokenStream {
224    let expr = expr.into();
225    quote! {{
226        let t: &#from = #expr;
227        let self_size = std::mem::size_of_val(t);
228        let target_size = std::mem::size_of::<#to<#plusplus::InConstruction>>();
229        assert!(self_size >= target_size);
230        let array_size = self_size - target_size;
231        let target_ptr = std::ptr::slice_from_raw_parts(t as *const #from as *const u8, array_size);
232        let target_ref = &*(target_ptr as *const #to);
233        assert_eq!(self_size, std::mem::size_of_val(target_ref));
234        target_ref
235    }}
236}
237
238fn cast_class_ptr_mut(
239    plusplus: &TokenStream,
240    from: &Type,
241    to: &Type,
242    expr: impl Into<TokenStream>,
243) -> TokenStream {
244    let expr = expr.into();
245    quote! {{
246        let t: &mut #from = #expr;
247        let self_size = std::mem::size_of_val(t);
248        let target_size = std::mem::size_of::<#to<#plusplus::InConstruction>>();
249        assert!(self_size >= target_size);
250        let array_size = self_size - target_size;
251        let target_ptr = std::ptr::slice_from_raw_parts_mut(t as *mut #from as *mut u8, array_size);
252        let target_ref = &mut *(target_ptr as *mut #to);
253        assert_eq!(self_size, std::mem::size_of_val(target_ref));
254        target_ref
255    }}
256}
257
258fn set_arg_blank_lifetime(arg: &mut FnArg, lifetime: &Lifetime, lifetime_set: &mut bool) {
259    match arg {
260        FnArg::Receiver(rx) => {
261            if let Some((_, lt)) = &mut rx.reference {
262                maybe_set_lifetime_opt(lt, lifetime, lifetime_set);
263            }
264        }
265        FnArg::Typed(ty) => {
266            set_blank_type_lifetimes(&mut ty.ty, lifetime, lifetime_set);
267        }
268    }
269}
270
271fn set_blank_type_lifetimes(ty: &mut Type, lifetime: &Lifetime, lifetime_set: &mut bool) {
272    match ty {
273        Type::Array(arr) => set_blank_type_lifetimes(&mut arr.elem, lifetime, lifetime_set),
274        Type::BareFn(_) => {}
275        Type::Group(group) => set_blank_type_lifetimes(&mut group.elem, lifetime, lifetime_set),
276        Type::ImplTrait(_) => {} // technically we should implement this but it doesn't come up in our use
277        Type::Infer(_) => {}
278        Type::Macro(_) => {}
279        Type::Never(_) => {}
280        Type::Paren(paren) => set_blank_type_lifetimes(&mut paren.elem, lifetime, lifetime_set),
281        Type::Path(path) => {
282            if let Some(qself) = &mut path.qself {
283                set_blank_type_lifetimes(&mut qself.ty, lifetime, lifetime_set);
284            }
285            set_blank_path_lifetimes(&mut path.path, lifetime, lifetime_set);
286        }
287        Type::Ptr(ptr) => set_blank_type_lifetimes(&mut ptr.elem, lifetime, lifetime_set),
288        Type::Reference(refer) => {
289            maybe_set_lifetime_opt(&mut refer.lifetime, lifetime, lifetime_set);
290            set_blank_type_lifetimes(&mut refer.elem, lifetime, lifetime_set)
291        }
292        Type::Slice(slice) => set_blank_type_lifetimes(&mut slice.elem, lifetime, lifetime_set),
293        Type::TraitObject(obj) => {
294            set_blank_type_param_bounds(&mut obj.bounds, lifetime, lifetime_set)
295        }
296        Type::Tuple(tup) => {
297            for ty in &mut tup.elems {
298                set_blank_type_lifetimes(ty, lifetime, lifetime_set);
299            }
300        }
301        Type::Verbatim(_) => {}
302        _ => (),
303    }
304}
305
306fn set_blank_path_lifetimes(path: &mut Path, lifetime: &Lifetime, lifetime_set: &mut bool) {
307    for path_args in path.segments.iter_mut().map(|seg| &mut seg.arguments) {
308        match path_args {
309            PathArguments::None => {}
310            PathArguments::AngleBracketed(angle_args) => {
311                set_blank_angle_bracket_lifetimes(angle_args, lifetime, lifetime_set)
312            }
313            PathArguments::Parenthesized(paren_args) => {
314                for ty in &mut paren_args.inputs {
315                    set_blank_type_lifetimes(ty, lifetime, lifetime_set);
316                }
317                if let ReturnType::Type(_, ty) = &mut paren_args.output {
318                    set_blank_type_lifetimes(ty, lifetime, lifetime_set);
319                }
320            }
321        }
322    }
323}
324
325fn set_blank_angle_bracket_lifetimes(
326    angle: &mut AngleBracketedGenericArguments,
327    lifetime: &Lifetime,
328    lifetime_set: &mut bool,
329) {
330    for arg in &mut angle.args {
331        set_blank_generic_lifetimes(arg, lifetime, lifetime_set);
332    }
333}
334
335fn maybe_set_lifetime(set: &mut Lifetime, to: &Lifetime, lifetime_set: &mut bool) {
336    if set.ident == format_ident!("_") {
337        *set = to.clone();
338        *lifetime_set = true;
339    }
340}
341fn maybe_set_lifetime_opt(set: &mut Option<Lifetime>, to: &Lifetime, lifetime_set: &mut bool) {
342    match set {
343        Some(lt) => maybe_set_lifetime(lt, to, lifetime_set),
344        None => {
345            *set = Some(to.clone());
346            *lifetime_set = true;
347        }
348    }
349}
350
351fn set_blank_type_param_bounds<'a>(
352    bounds: impl IntoIterator<Item = &'a mut TypeParamBound>,
353    lifetime: &Lifetime,
354    lifetime_set: &mut bool,
355) {
356    for bound in bounds {
357        match bound {
358            TypeParamBound::Trait(trait_bound) => {
359                set_blank_path_lifetimes(&mut trait_bound.path, lifetime, lifetime_set)
360            }
361            TypeParamBound::Lifetime(lt) => maybe_set_lifetime(lt, lifetime, lifetime_set),
362            TypeParamBound::PreciseCapture(cap) => {
363                for p in &mut cap.params {
364                    match p {
365                        CapturedParam::Lifetime(lt) => {
366                            maybe_set_lifetime(lt, lifetime, lifetime_set)
367                        }
368                        CapturedParam::Ident(_) => {}
369                        _ => (),
370                    }
371                }
372            }
373            TypeParamBound::Verbatim(_) => {}
374            _ => (),
375        }
376    }
377}
378fn set_blank_generic_lifetimes(
379    arg: &mut GenericArgument,
380    lifetime: &Lifetime,
381    lifetime_set: &mut bool,
382) {
383    match arg {
384        GenericArgument::Lifetime(lt) => maybe_set_lifetime(lt, lifetime, lifetime_set),
385        GenericArgument::Type(ty) => set_blank_type_lifetimes(ty, lifetime, lifetime_set),
386        GenericArgument::Const(_) => {}
387        GenericArgument::AssocType(ty) => {
388            if let Some(args) = &mut ty.generics {
389                set_blank_angle_bracket_lifetimes(args, lifetime, lifetime_set);
390            }
391            set_blank_type_lifetimes(&mut ty.ty, lifetime, lifetime_set);
392        }
393        GenericArgument::AssocConst(_) => {}
394        GenericArgument::Constraint(constraint) => {
395            if let Some(args) = &mut constraint.generics {
396                set_blank_angle_bracket_lifetimes(args, lifetime, lifetime_set);
397            }
398
399            set_blank_type_param_bounds(&mut constraint.bounds, lifetime, lifetime_set);
400        }
401        _ => (),
402    }
403}
404
405#[derive(Debug, Clone)]
406struct FuncInfo {
407    func: ImplItemFn,
408    name: Ident,
409    vtbl_name: Ident,
410    lifetime_bounds: Option<TokenStream>,
411    vtbl_sig: TokenStream,
412    args: Vec<Box<Pat>>,
413    mut_self: bool,
414}
415
416fn get_func_sig(class_name: &Type, f: &ImplItemFn) -> FuncInfo {
417    let func_name = &f.sig.ident;
418    let is_async = f.sig.asyncness.is_some();
419
420    let mut inputs = f.sig.inputs.clone();
421    let mut mut_self = false;
422    if let Some(FnArg::Receiver(rx)) = &f.sig.inputs.get(0) {
423        let receiver = &mut inputs[0];
424        if let Some((_, rx_lifetime)) = &rx.reference {
425            if rx.mutability.is_some() {
426                *receiver = FnArg::Typed(parse_quote!(this: & #rx_lifetime mut #class_name));
427            } else {
428                *receiver = FnArg::Typed(parse_quote!(this: & #rx_lifetime #class_name));
429            }
430        }
431        mut_self = rx.mutability.is_some();
432    };
433
434    let mut lifetimes: Vec<LifetimeParam> = Vec::new();
435    let future_fallback_lt: Lifetime = parse_quote!('rpp_future);
436    let mut using_future_lifetime = false;
437    let mut vtbl_inputs = inputs.clone();
438    // eprintln!("inputs = {:#?}", vtbl_inputs);
439    if is_async {
440        for arg in &mut vtbl_inputs {
441            set_arg_blank_lifetime(arg, &future_fallback_lt, &mut using_future_lifetime);
442        }
443        if using_future_lifetime {
444            lifetimes.push(parse_quote!(#future_fallback_lt));
445        }
446    }
447    for generic in &f.sig.generics.params {
448        match generic {
449            GenericParam::Lifetime(lt) => {
450                let mut lt = lt.clone();
451                if using_future_lifetime {
452                    lt.bounds.push(future_fallback_lt.clone());
453                }
454                lifetimes.push(lt)
455                // if using_future_lifetime {
456                //     lifetimes.push(parse_quote!(#lt: #future_fallback_lt));
457                // } else {
458                //     lifetimes.push(parse_quote!(#lt));
459                // }
460            }
461            GenericParam::Type(_) => {}
462            GenericParam::Const(_) => {}
463        }
464    }
465
466    let lifetime_bounds = if lifetimes.len() > 0 {
467        Some(quote!(<#(#lifetimes),*>))
468    } else {
469        None
470    };
471
472    let mut output = f.sig.output.clone();
473    if is_async {
474        let future_output = match output {
475            ReturnType::Default => quote!(()),
476            ReturnType::Type(_, ty) => quote!(#ty),
477        };
478        let future_lifetimes = if using_future_lifetime {
479            future_fallback_lt
480        } else {
481            assert!(lifetimes.len() > 0);
482            lifetimes[0].lifetime.clone()
483        };
484        output = parse_quote!(-> std::pin::Pin<Box<dyn #future_lifetimes + Future<Output=#future_output>>>);
485    }
486    let vtbl_name = format_ident!("fn_{func_name}");
487    let vtbl_sig = quote! {
488        (#vtbl_inputs) #output
489    };
490
491    let func_args = inputs
492        .into_iter()
493        .skip(1)
494        .map(|arg| match arg {
495            FnArg::Receiver(_) => unreachable!(),
496            FnArg::Typed(arg) => arg.pat,
497        })
498        .collect::<Vec<_>>();
499
500    FuncInfo {
501        func: f.clone(),
502        name: func_name.clone(),
503        vtbl_name,
504        lifetime_bounds,
505        vtbl_sig,
506        args: func_args,
507        mut_self,
508    }
509}
510
511#[derive(Debug, Clone, Copy)]
512struct Derives {
513    clone: bool,
514}
515
516impl Derives {
517    fn from_attributes(attrs: impl Iterator<Item = Attribute>) -> syn::Result<Derives> {
518        let mut clone = false;
519        for attr in attrs {
520            if let AttrStyle::Inner(_) = attr.style {
521                return Err(Error::new(
522                    attr.span(),
523                    "did not expect inner attribute in class macro",
524                ));
525            }
526
527            let derive_tokens = match attr.meta {
528                Meta::List(list) if list.path == parse_quote!(derive) => {
529                    if !matches!(list.delimiter, MacroDelimiter::Paren(_)) {
530                        return Err(Error::new(
531                            list.delimiter.span().open(),
532                            "derive attribute must have parenthesis",
533                        ));
534                    }
535                    list.tokens
536                }
537                _ => return Err(Error::new(attr.span(), "unsupported attribute on class")),
538            };
539
540            let derive_path: Path = parse2(derive_tokens)?;
541            if derive_path == parse_quote!(Clone) {
542                if clone {
543                    return Err(Error::new(
544                        derive_path.span(),
545                        "Clone derive already specified",
546                    ));
547                }
548                clone = true;
549            }
550        }
551
552        Ok(Derives { clone })
553    }
554
555    fn has_any_derives(&self) -> bool {
556        self.clone
557    }
558}
559
560struct ClassData {
561    plusplus: TokenStream,
562    class_name: Ident,
563    class_type: Type,
564    class_mod_name: Ident,
565    vtbl_ident: Ident,
566    class_vis: Visibility,
567    fields: Vec<Field>,
568    constructors: Vec<FuncInfo>,
569    member_funcs: Vec<FuncInfo>,
570    overrides: Vec<OverrideItem>,
571    override_funcs: Vec<FuncInfo>,
572    superclass_type: Option<Type>,
573    mod_superclass_type: Option<Type>,
574    derives: Derives,
575}
576
577impl ClassData {
578    fn from_input(input: ClassInput, crate_alias: Option<&CrateAlias>) -> syn::Result<ClassData> {
579        let ClassInput {
580            attrs,
581            vis: class_vis,
582            _class_token: _,
583            ident: class_name,
584            superclass,
585            _brace_token: _,
586            items: class_items,
587        } = input;
588
589        let mut fields = Vec::new();
590        let mut constructors = Vec::new();
591        let mut member_funcs = Vec::new();
592        let mut overrides = Vec::new();
593        let mut override_funcs = Vec::new();
594
595        let class_type: Type = parse_quote!(#class_name);
596
597        for item in class_items {
598            match item {
599                ClassItem::Field { field, .. } => fields.push(field),
600                ClassItem::ImplItemFn(func) => {
601                    if let Some(FnArg::Receiver(_)) = func.sig.inputs.get(0) {
602                        member_funcs.push(get_func_sig(&class_type, &func))
603                    } else {
604                        constructors.push(get_func_sig(&class_type, &func));
605                    }
606                }
607                ClassItem::OverrideItem(override_item) => {
608                    override_funcs.extend(
609                        override_item
610                            .items
611                            .iter()
612                            .map(|f| get_func_sig(&class_type, &f)),
613                    );
614                    overrides.push(override_item);
615                }
616            }
617        }
618
619        let class_mod_name =
620            format_ident!("plusplus__class_{}", class_name.to_string().to_lowercase());
621
622        let plusplus = if let Some(alias) = crate_alias {
623            let alias = &alias.ident;
624            quote!(#alias)
625        } else {
626            plusplus()
627        };
628
629        let superclass_type = superclass.map(|sc| sc.ty);
630        let mod_superclass_type = match superclass_type.clone() {
631            Some(Type::Path(mut type_path)) => {
632                if type_path.path.segments.get(0) != Some(&parse_quote!(crate)) {
633                    type_path.path.segments.insert(0, parse_quote!(super));
634                }
635                Some(Type::Path(type_path))
636            }
637            ty => ty,
638        };
639
640        let derives = Derives::from_attributes(attrs.into_iter())?;
641
642        Ok(ClassData {
643            plusplus,
644            vtbl_ident: format_ident!("{}Vtbl", class_name),
645            class_vis,
646            class_name,
647            class_type,
648            class_mod_name,
649            fields,
650            constructors,
651            member_funcs,
652            overrides,
653            override_funcs,
654            superclass_type,
655            mod_superclass_type,
656            derives,
657        })
658    }
659
660    fn has_superclass(&self) -> bool {
661        self.superclass_type.is_some()
662    }
663
664    fn gen_mod_vtbl_struct(&self) -> TokenStream {
665        // create vtbl
666        let vtbl_ident = &self.vtbl_ident;
667        let class_name = &self.class_name;
668        let plusplus = &self.plusplus;
669
670        let mut vtbl_func_names = Vec::new();
671        let mut vtbl_sigs = Vec::new();
672        let mut my_func_names = Vec::new();
673        let mut async_func_impls = Vec::new();
674        let mut func_setters = Vec::new();
675        let mut vtbl_fors = Vec::new();
676        let mut vtbl_unsafes = Vec::new();
677
678        for f in self.member_funcs.iter() {
679            let FuncInfo {
680                func:
681                    ImplItemFn {
682                        sig:
683                            Signature {
684                                asyncness,
685                                unsafety,
686                                ..
687                            },
688                        ..
689                    },
690                name: func_name,
691                vtbl_name: vtbl_func_name,
692                lifetime_bounds,
693                vtbl_sig,
694                args,
695                mut_self: _,
696            } = f;
697            let my_func_name = format_ident!("my_{func_name}");
698            let vtbl_for = lifetime_bounds.as_ref().map(|bounds| quote!(for #bounds));
699            vtbl_fors.push(vtbl_for.clone());
700            vtbl_unsafes.push(unsafety);
701
702            if asyncness.is_some() {
703                async_func_impls.push(quote!{
704                    // fn #my_func_name #func_sig {
705                    let #my_func_name: #vtbl_for #unsafety fn #vtbl_sig = |this, #(#args)*| #unsafety {
706                        Box::pin(#class_name::#my_func_name(this, #(#args)*))
707                    };
708                });
709                func_setters.push(quote! {
710                    #vtbl_func_name: #my_func_name,
711                })
712            } else {
713                func_setters.push(quote! {
714                     #vtbl_func_name: #class_name::#my_func_name,
715                })
716            }
717
718            my_func_names.push(my_func_name);
719            vtbl_func_names.push(vtbl_func_name);
720            vtbl_sigs.push(vtbl_sig);
721        }
722
723        let vtbl_drop_field: Option<_>;
724        let vtbl_drop_func: Option<_>;
725        let vtbl_drop_set: Option<_>;
726        if !self.has_superclass() {
727            vtbl_drop_field = Some(quote! {
728                pub manually_drop: unsafe fn(*mut #class_name),
729            });
730            vtbl_drop_func = Some(quote! {
731                unsafe fn manually_drop(this: *mut #class_name) {
732                    unsafe{ std::ptr::drop_in_place(this) }
733                }
734            });
735            vtbl_drop_set = Some(quote! {
736                manually_drop,
737            });
738        } else {
739            vtbl_drop_field = None;
740            vtbl_drop_func = None;
741            vtbl_drop_set = None;
742        };
743
744        let mut vtbl_trait_fields = None;
745        let mut vtbl_trait_impls = None;
746        let mut vtbl_trait_setters = None;
747        if self.derives.has_any_derives() && !self.has_superclass() {
748            let Derives { clone } = self.derives;
749            let clone_field = clone.then(|| {
750                quote! {
751                    class_clone: fn(&#class_name) -> #plusplus::ClassBox<#class_name>,
752                }
753            });
754            let clone_impl = clone.then(|| {
755                quote! {
756                    fn class_clone(this: &#class_name) -> #plusplus::ClassBox<#class_name> {
757                        use #plusplus::{Class, ClassInConstruction};
758                        let in_construction = unsafe{ this.as_in_construction() };
759                        in_construction.clone().finish()
760                    }
761                }
762            });
763            let clone_set = clone.then(|| {
764                quote! {
765                    class_clone,
766                }
767            });
768            vtbl_trait_fields = Some(quote! {
769                #clone_field
770            });
771            vtbl_trait_impls = Some(quote! {
772                #clone_impl
773            });
774            vtbl_trait_setters = Some(quote! {
775                #clone_set
776            })
777        };
778
779        quote! {
780            #[doc(hidden)]
781            #[derive(Clone, Copy)]
782            pub struct #vtbl_ident {
783                #vtbl_drop_field
784                #vtbl_trait_fields
785                #(pub #vtbl_func_names: #vtbl_fors #vtbl_unsafes fn #vtbl_sigs,)*
786            }
787
788            impl #vtbl_ident {
789                const BASE: Self = {
790                    #vtbl_drop_func
791                    #vtbl_trait_impls
792                    #(#async_func_impls)*
793
794                    Self {
795                        #vtbl_drop_set
796                        #vtbl_trait_setters
797                        #(#func_setters)*
798                    }
799                };
800            }
801        }
802    }
803
804    fn gen_fn_set_vtbls(&self) -> TokenStream {
805        let plusplus = &self.plusplus;
806        let class_name = &self.class_name;
807
808        let set_vtbls = self.overrides.iter().map(|ovr| {
809            let ovr_class = &ovr.override_class;
810            let ovr_class = match ovr_class.clone() {
811                Type::Path(mut type_path) => {
812                    type_path.path.segments.insert(0, parse_quote!(super));
813                    Type::Path(type_path)
814                }
815                ty => ty,
816            };
817
818            let mut ol_func_names = Vec::new();
819            let mut ol_func_sigs = Vec::new();
820            let mut ol_func_self_call_impls = Vec::new();
821            let mut ol_lifetime_bounds = Vec::new();
822            for f in &ovr.items {
823                let FuncInfo {
824                    func:
825                        ImplItemFn {
826                            sig:
827                                Signature {
828                                    asyncness,
829                                    unsafety,
830                                    ..
831                                },
832                            ..
833                        },
834                    name: func_name,
835                    vtbl_name,
836                    lifetime_bounds,
837                    vtbl_sig: func_sig,
838                    args: func_args,
839                    mut_self,
840                } = get_func_sig(&ovr_class, f);
841                ol_func_names.push(vtbl_name);
842                ol_func_sigs.push(func_sig);
843                ol_lifetime_bounds.push(lifetime_bounds);
844
845                let func_name = format_ident!("my_{}", func_name);
846                let make_this = if mut_self {
847                    quote! {
848                        let this: &mut #class_name = unsafe{ #class_name::from_root_class_mut(this.root_class_mut()) };
849                    }
850                } else {
851                    quote! {
852                        let this: &#class_name = unsafe{ #class_name::from_root_class_ref(this.root_class()) };
853                    }
854                };
855                let self_call = if asyncness.is_some() {
856                    quote! {
857                        #make_this
858                        #unsafety { Box::pin(this.#func_name(#(#func_args,)*)) }
859                    }
860                } else {
861                    quote! {
862                        #make_this
863                        #unsafety { this.#func_name(#(#func_args,)*) }
864                    }
865                };
866                ol_func_self_call_impls.push(self_call);
867            }
868
869            quote! {{
870                let this: &mut #ovr_class = &mut *(unsafe{ self.to_constructed() });
871                #(
872                    fn #ol_func_names #ol_lifetime_bounds #ol_func_sigs {
873                        #ol_func_self_call_impls
874                    }
875                    unsafe{ this.plusplus__vtbl_mut().#ol_func_names = #ol_func_names };
876                )*
877            }}
878        });
879
880        let root_type: Type = parse_quote!(<#class_name as #plusplus::Class>::RootClass);
881        let root_type = &root_type;
882
883        let set_subclass = self.has_superclass().then(|| quote!{
884            use #plusplus::Class as _;
885            unsafe{ self.superclass.plusplus__set_subclass(<#class_name as #plusplus::Class>::TYPE_ID) };
886
887            {
888                unsafe fn manually_drop(this: *mut #root_type) {
889                    let this = unsafe{ #class_name::from_root_class_mut(&mut *this) };
890                    unsafe{ std::ptr::drop_in_place(this) };
891                }
892                let root_vtbl = unsafe{ <#class_name as #plusplus::Class>::root_class_mut(self.to_constructed()).plusplus__vtbl_mut() };
893                root_vtbl.manually_drop = manually_drop;
894            }
895        });
896
897        let mut set_trait_vtbls = None;
898        if !self.has_superclass() {
899            let mut derive_trait_bounds = None;
900            let mut derive_trait_impls = None;
901            if self.derives.has_any_derives() {
902                let Derives { clone } = self.derives;
903                let clone_trait_bound = clone.then(|| quote!(Clone));
904                let clone_impl = clone.then(|| quote!{
905                    let class_clone = |this: &#class_name| -> #plusplus::ClassBox<#class_name> {
906                        use #plusplus::{Class as _, ClassBox, ClassInConstruction};
907                        let child_class = unsafe{ Class::from_root_class_ref(this).as_in_construction() };
908                        let cloned = child_class.clone().finish();
909                        unsafe{ ClassBox::from_raw(ClassBox::leak(cloned).root_class_mut()) }
910                    };
911                    self.vtbl.class_clone = class_clone;
912                });
913                derive_trait_bounds =
914                    Some(quote! {where Class::InConstruction: #clone_trait_bound});
915                derive_trait_impls = Some(quote! {
916                    #clone_impl
917                });
918            }
919
920            set_trait_vtbls = Some(quote! {
921                #[doc(hidden)]
922                pub fn plusplus__set_trait_vtbls<Class: ?Sized + #plusplus::Class<RootClass=#class_name>>(&mut self)
923                #derive_trait_bounds
924                {
925                    #derive_trait_impls
926                }
927            });
928        }
929
930        quote! {
931            fn plusplus__set_vtbls(&mut self) {
932                #set_subclass
933                #(#set_vtbls)*
934            }
935
936            #set_trait_vtbls
937        }
938    }
939
940    fn gen_mod_class_struct(&self) -> TokenStream {
941        let plusplus = &self.plusplus;
942
943        let superclass_field = self.mod_superclass_type.as_ref().map(|sc_type| {
944            quote! {
945                superclass: #sc_type<#plusplus::InConstruction>,
946            }
947        });
948        let superclass_field = superclass_field.as_ref();
949        let superclass_bound = self.mod_superclass_type.as_ref().map(|sc_ident| {
950            quote! {
951                where #sc_ident: #plusplus::Class
952            }
953        });
954
955        let class_struct_vis = correct_priv_vis(self.class_vis.clone());
956        let vtbl_ident = &self.vtbl_ident;
957        let class_name = &self.class_name;
958        let fields = &self.fields;
959        let init_superclass_field = superclass_field.map(|f| quote!(pub #f));
960        let init_fields = self.fields.iter().cloned().map(|f| Field {
961            vis: Visibility::Public(parse_quote!(pub)),
962            ..f
963        });
964
965        let derives = self.derives.has_any_derives().then(|| {
966            let Derives { clone } = self.derives;
967            let clone = clone.then(|| quote!(Clone,));
968            quote!(#[derive(#clone)])
969        });
970
971        quote! {
972            #[repr(C)]
973            #derives
974            #class_struct_vis struct #class_name<C: ?Sized + #plusplus::ClassMemory = #plusplus::Constructed>
975                #superclass_bound
976            {
977                #superclass_field
978                vtbl: #vtbl_ident,
979                // we store a reference to a type ID instead of a type ID as a size optimization;
980                // an Option<TypeId> is 24 bytes, while an Option<&TypeId> is 8 bytes
981                subclass_id: Option<&'static std::any::TypeId>,
982                #(#fields,)*
983                memory: C,
984            }
985
986            pub struct PlusPlus__InitClass {
987                #init_superclass_field
988                #(#init_fields,)*
989            }
990        }
991    }
992
993    fn gen_mod_trait_impls(&self) -> TokenStream {
994        let plusplus = &self.plusplus;
995        let class_name = &self.class_name;
996
997        let Derives { clone } = self.derives;
998
999        let clone_impl = clone.then(|| {
1000            if self.has_superclass() {
1001                quote! {
1002                    impl #plusplus::ClassClone for #class_name {
1003                        fn class_clone(&self) -> #plusplus::ClassBox<Self> {
1004                            use #plusplus::{ClassBox, Class, ClassClone};
1005                            let root_ref: &mut _ = ClassBox::leak(self.root_class().class_clone());
1006                            let self_ref = unsafe{ Self::from_root_class_mut(root_ref) };
1007                            unsafe{ ClassBox::from_raw(self_ref) }
1008                        }
1009                    }
1010                }
1011            } else {
1012                quote! {
1013                    impl #plusplus::ClassClone for #class_name {
1014                        fn class_clone(&self) -> #plusplus::ClassBox<Self> {
1015                            (self.vtbl.class_clone)(self)
1016                        }
1017                    }
1018                }
1019            }
1020        });
1021
1022        quote! {
1023            #clone_impl
1024        }
1025    }
1026
1027    fn gen_superclass_casters(&self) -> Option<TokenStream> {
1028        let Some(sc_type) = self.superclass_type.as_ref() else {
1029            return None;
1030        };
1031        let class_name = &self.class_name;
1032
1033        let deref_upcast = cast_class_ptr(&self.plusplus, &self.class_type, sc_type, quote! {self});
1034        let deref_upcast_mut =
1035            cast_class_ptr_mut(&self.plusplus, &self.class_type, sc_type, quote! {self});
1036        let ref_downcast = cast_class_ptr(&self.plusplus, sc_type, &self.class_type, quote! {self});
1037        let ref_downcast_mut =
1038            cast_class_ptr_mut(&self.plusplus, sc_type, &self.class_type, quote! {self});
1039
1040        let plusplus = &self.plusplus;
1041        Some(quote! {
1042            impl std::ops::Deref for #class_name {
1043                type Target = #sc_type;
1044
1045                fn deref(&self) -> &Self::Target {
1046                    unsafe { #deref_upcast }
1047                }
1048            }
1049
1050            impl std::ops::DerefMut for #class_name {
1051                fn deref_mut(&mut self) -> &mut Self::Target {
1052                    unsafe { #deref_upcast_mut }
1053                }
1054            }
1055
1056            impl<'a> #plusplus::Downcast<#class_name> for &'a #sc_type {
1057                type Wrapped = &'a #class_name;
1058                fn downcast(self) -> Result<&'a #class_name, Self> {
1059                    use #plusplus::Class;
1060                    let subclass_type_id = <#class_name as #plusplus::Class>::TYPE_ID;
1061                    if self.subclass_id() == Some(subclass_type_id) {
1062                        Ok(unsafe{ #ref_downcast })
1063                    } else {
1064                        Err(self)
1065                    }
1066                }
1067            }
1068
1069            impl<'a> #plusplus::Downcast<#class_name> for &'a mut #sc_type {
1070                type Wrapped = &'a mut #class_name;
1071                fn downcast(self) -> Result<&'a mut #class_name, Self> {
1072                    use #plusplus::Class;
1073                    let subclass_type_id = <#class_name as #plusplus::Class>::TYPE_ID;
1074                    if self.subclass_id() == Some(subclass_type_id) {
1075                        Ok(unsafe{ #ref_downcast_mut })
1076                    } else {
1077                        Err(self)
1078                    }
1079                }
1080            }
1081        })
1082    }
1083
1084    fn gen_mod_impl_class_trait(&self) -> TokenStream {
1085        let plusplus = &self.plusplus;
1086        let class_name = &self.class_name;
1087        let root_class = self
1088            .mod_superclass_type
1089            .as_ref()
1090            .map(|sc_ident| quote! { <#sc_ident as #plusplus::Class>::RootClass })
1091            .unwrap_or_else(|| quote! { #class_name });
1092
1093        let from_root_class_ref = cast_class_ptr(
1094            plusplus,
1095            &parse_quote!(#root_class),
1096            &parse_quote!(#class_name),
1097            quote!(root),
1098        );
1099        let from_root_class_mut = cast_class_ptr_mut(
1100            plusplus,
1101            &parse_quote!(#root_class),
1102            &parse_quote!(#class_name),
1103            quote!(root),
1104        );
1105
1106
1107        quote! {
1108            unsafe impl #plusplus::Class for #class_name {
1109                const TYPE_ID: &'static std::any::TypeId = &std::any::TypeId::of::<#class_name>();
1110
1111                type RootClass = #root_class;
1112                type InConstruction = #class_name<#plusplus::InConstruction>;
1113
1114                fn subclass_id(&self) -> Option<&'static std::any::TypeId> {
1115                    self.subclass_id
1116                }
1117
1118                fn root_class(&self) -> &Self::RootClass {
1119                    self
1120                }
1121
1122                fn root_class_mut(&mut self) -> &mut Self::RootClass {
1123                    self
1124                }
1125
1126                unsafe fn manually_drop(slot: &mut std::mem::ManuallyDrop<Self>) {
1127                    let as_root_class = slot.root_class_mut();
1128                    let manual_drop_fn = unsafe{ as_root_class.plusplus__vtbl_mut().manually_drop };
1129                    unsafe{ manual_drop_fn(as_root_class); }
1130                }
1131                unsafe fn as_in_construction(&self) -> &#class_name<#plusplus::InConstruction> {
1132                    unsafe{ &*(self as *const Self as *const #class_name<#plusplus::InConstruction>) }
1133                }
1134                unsafe fn as_in_construction_mut(&mut self) -> &mut #class_name<#plusplus::InConstruction> {
1135                    unsafe{ &mut *(self as *mut Self as *mut #class_name<#plusplus::InConstruction>) }
1136                }
1137                unsafe fn from_root_class_ref(root: &Self::RootClass) -> &Self {
1138                    unsafe{ #from_root_class_ref }
1139                }
1140                unsafe fn from_root_class_mut(root: &mut Self::RootClass) -> &mut Self {
1141                    unsafe{ #from_root_class_mut }
1142                }
1143            }
1144
1145            impl #plusplus::ClassInConstruction for #class_name<#plusplus::InConstruction> {
1146                type Class = #class_name;
1147
1148                /// Finish constructing this by moving it to the heap placing it in a `ClassBox`.
1149                ///
1150                /// Downcasting, upcasting, and deref coersions will work properly after calling this!
1151                fn finish(self) -> #plusplus::ClassBox<#class_name> {
1152                    let boxed = Box::new(self);
1153                    let leaked = Box::leak(boxed);
1154                    let constructed = unsafe{ leaked.to_constructed() };
1155                    unsafe{ #plusplus::ClassBox::from_raw(constructed) }
1156                }
1157            }
1158        }
1159    }
1160
1161    fn gen_mod_class_impl(&self) -> TokenStream {
1162        let class_name = &self.class_name;
1163        let vtbl_ident = &self.vtbl_ident;
1164
1165        let mut call_vtbl_impls = Vec::new();
1166        for f in self.member_funcs.iter() {
1167            let FuncInfo {
1168                func: ImplItemFn { vis, sig, .. },
1169                name: _,
1170                vtbl_name,
1171                lifetime_bounds: _,
1172                vtbl_sig: _,
1173                args: func_args,
1174                mut_self: _,
1175            } = f;
1176
1177            let vis = correct_priv_vis(vis.clone());
1178            let do_await = sig.asyncness.is_some().then(|| quote!(.await));
1179            let call_vtbl = quote! {
1180                #vis #sig {
1181                    (self.vtbl.#vtbl_name)(self, #(#func_args,)*) #do_await
1182                }
1183            };
1184            call_vtbl_impls.push(call_vtbl);
1185        }
1186
1187        let mut my_func_impls = Vec::new();
1188        let mut super_func_impls = Vec::new();
1189
1190        for (f, is_override) in self
1191            .member_funcs
1192            .iter()
1193            .cloned()
1194            .map(|f| (f, false))
1195            .chain(self.override_funcs.iter().cloned().map(|f| (f, true)))
1196        {
1197            let FuncInfo {
1198                func:
1199                    ImplItemFn {
1200                        attrs: _,
1201                        vis,
1202                        defaultness: _,
1203                        sig,
1204                        block,
1205                    },
1206                name: func_name,
1207                vtbl_name: _,
1208                lifetime_bounds: _,
1209                vtbl_sig: _,
1210                args: func_args,
1211                mut_self,
1212            } = f;
1213
1214            let my_impl_name = format_ident!("my_{}", func_name);
1215            let mut my_impl_sig = sig.clone();
1216            my_impl_sig.ident = my_impl_name.clone();
1217            my_func_impls.push(quote! {
1218                #vis #my_impl_sig {
1219                    #block
1220                }
1221            });
1222
1223            if is_override {
1224                let super_impl_name = format_ident!("super_{}", func_name);
1225                let mut super_impl_sig = sig.clone();
1226                super_impl_sig.ident = super_impl_name.clone();
1227                let get_super = if mut_self {
1228                    quote! {
1229                        self.plusplus__super_mut()
1230                    }
1231                } else {
1232                    quote! {
1233                        self.plusplus__super_ref()
1234                    }
1235                };
1236                let super_impl_block = if sig.asyncness.is_some() {
1237                    quote! { #get_super.#my_impl_name(#(#func_args,)*).await }
1238                } else {
1239                    quote! { #get_super.#my_impl_name(#(#func_args,)*) }
1240                };
1241
1242                super_func_impls.push(quote! {
1243                    #vis #super_impl_sig {
1244                        #super_impl_block
1245                    }
1246                });
1247            }
1248        }
1249
1250        let superclass_getters = self.mod_superclass_type.as_ref().map(|sc_ident| {
1251            quote! {
1252                fn plusplus__super_ref(&self) -> &#sc_ident {
1253                    self
1254                }
1255
1256                fn plusplus__super_mut(&mut self) -> &mut #sc_ident {
1257                    self
1258                }
1259            }
1260        });
1261
1262        quote! {
1263            impl #class_name {
1264                #(#call_vtbl_impls)*
1265                #(#super_func_impls)*
1266
1267                #superclass_getters
1268
1269                #[doc(hidden)]
1270                pub unsafe fn plusplus__vtbl_mut(&mut self) -> &mut #vtbl_ident {
1271                    &mut self.vtbl
1272                }
1273            }
1274        }
1275    }
1276
1277    fn gen_mod_in_construction_class_impl(&self) -> TokenStream {
1278        let plusplus = &self.plusplus;
1279        let class_name = &self.class_name;
1280        let vtbl_ident = &self.vtbl_ident;
1281
1282        let set_vtbl_func = self.gen_fn_set_vtbls();
1283
1284        let superclass_field = self
1285            .has_superclass()
1286            .then(|| quote! {superclass: init.superclass,});
1287        let fields = self.fields.iter().map(|f| &f.ident).collect::<Vec<_>>();
1288
1289        quote! {
1290            impl #class_name<#plusplus::InConstruction> {
1291                #set_vtbl_func
1292
1293                pub(super) fn plusplus__new_from_init(init: PlusPlus__InitClass) -> Self {
1294                    use #plusplus::Class;
1295                    let mut this = Self {
1296                        vtbl: #vtbl_ident::BASE,
1297                        memory: #plusplus::InConstruction::default(),
1298                        subclass_id: None,
1299                        #superclass_field
1300                        #(#fields: init.#fields,)*
1301                    };
1302
1303                    this.plusplus__set_vtbls();
1304                    unsafe{ this.to_constructed().root_class_mut().as_in_construction_mut() }.plusplus__set_trait_vtbls::<#class_name>();
1305
1306                    this
1307                }
1308
1309                #[doc(hidden)]
1310                pub unsafe fn plusplus__set_subclass(&mut self, subclass_id: &'static std::any::TypeId) {
1311                    self.subclass_id = Some(subclass_id);
1312                }
1313
1314                /// Unsafe because caller must guarantee that vtbl doesn't contain any
1315                /// subclass methods
1316                pub unsafe fn to_constructed(&mut self) -> &mut #class_name {
1317                    unsafe{ &mut *(std::ptr::slice_from_raw_parts_mut::<u8>(self as *mut _ as *mut u8, 0) as *mut #class_name) }
1318                }
1319            }
1320        }
1321    }
1322
1323    fn gen_init_class_macro(&self) -> TokenStream {
1324        let plusplus = &self.plusplus;
1325        let class_name = &self.class_name;
1326        let class_mod_name = &self.class_mod_name;
1327
1328        quote! {
1329            macro_rules! init_class {
1330                ($($tt:tt)*) => {{
1331                    #class_name::<#plusplus::InConstruction>::plusplus__new_from_init(#class_mod_name::PlusPlus__InitClass {
1332                        $($tt)*
1333                    })
1334                }}
1335            }
1336        }
1337    }
1338
1339    fn gen_class_impl(&self) -> TokenStream {
1340        let class_name = &self.class_name;
1341        let mut my_func_impls = Vec::new();
1342        for f in self
1343            .member_funcs
1344            .iter()
1345            .cloned()
1346            .chain(self.override_funcs.iter().cloned())
1347        {
1348            let FuncInfo {
1349                func:
1350                    ImplItemFn {
1351                        attrs: _,
1352                        vis,
1353                        defaultness: _,
1354                        sig,
1355                        block,
1356                    },
1357                name: func_name,
1358                vtbl_name: _,
1359                lifetime_bounds: _,
1360                vtbl_sig: _,
1361                args: _,
1362                mut_self: _,
1363            } = f;
1364
1365            let my_impl_name = format_ident!("my_{}", func_name);
1366            let mut my_impl_sig = sig.clone();
1367            my_impl_sig.ident = my_impl_name.clone();
1368            my_func_impls.push(quote! {
1369                #vis #my_impl_sig {
1370                    #block
1371                }
1372            });
1373        }
1374
1375        let init_class_macro = self.gen_init_class_macro();
1376        let mut constructor_impls = Vec::new();
1377        for c in self.constructors.iter() {
1378            let ImplItemFn {
1379                attrs,
1380                vis,
1381                defaultness,
1382                sig,
1383                block,
1384            } = &c.func;
1385
1386            let vis = correct_priv_vis(vis.clone());
1387            constructor_impls.push(quote! {
1388                #(#attrs)* #vis #defaultness #sig {
1389                    #init_class_macro
1390                    #block
1391                }
1392            });
1393        }
1394
1395        quote! {
1396            impl #class_name {
1397                #(#constructor_impls)*
1398                #(#my_func_impls)*
1399            }
1400        }
1401    }
1402
1403    fn gen_class(&self) -> TokenStream {
1404        let class_vis = &self.class_vis;
1405        let class_name = &self.class_name;
1406        let class_mod_name = &self.class_mod_name;
1407        let mod_vtbl_struct = self.gen_mod_vtbl_struct();
1408        let mod_class_struct = self.gen_mod_class_struct();
1409        let mod_impl_class_trait = self.gen_mod_impl_class_trait();
1410        let mod_trait_impls = self.gen_mod_trait_impls();
1411        let superclass_cast = self.gen_superclass_casters();
1412        let mod_class_impl = self.gen_mod_class_impl();
1413        let mod_in_construction_class_impl = self.gen_mod_in_construction_class_impl();
1414        let class_impl = self.gen_class_impl();
1415
1416        quote! {
1417            #class_vis use #class_mod_name::#class_name;
1418            mod #class_mod_name {
1419                use super::*;
1420                #mod_vtbl_struct
1421                #mod_class_struct
1422
1423                #mod_class_impl
1424
1425                #mod_impl_class_trait
1426
1427                #mod_in_construction_class_impl
1428
1429                #mod_trait_impls
1430            }
1431
1432            #class_impl
1433
1434            #superclass_cast
1435        }
1436    }
1437}
1438
1439fn do_class(inputs: ClassInputs) -> syn::Result<TokenStream> {
1440    let class_data = inputs
1441        .inputs
1442        .into_iter()
1443        .map(|input| Ok(ClassData::from_input(input, inputs.crate_alias.as_ref())?.gen_class()))
1444        .collect::<Result<Vec<_>, syn::Error>>()?;
1445
1446    Ok(quote! {
1447        #(#class_data)*
1448    })
1449}
1450
1451/// The whole point.
1452#[proc_macro]
1453pub fn class(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
1454    let inputs = parse_macro_input!(tokens as ClassInputs);
1455    do_class(inputs)
1456        .unwrap_or_else(syn::Error::into_compile_error)
1457        .into()
1458}