1mod codegen;
6
7mod field_checking;
8
9mod patterns;
10
11use darling::ast::NestedMeta;
12use proc_macro::TokenStream;
13use proc_macro2::TokenStream as TokenStream2;
14use quote::quote;
15use syn::{
16 Generics, Ident, Result, Token, braced,
17 parse::{Parse, ParseStream},
18 parse_macro_input,
19 punctuated::Punctuated,
20};
21
22use darling::FromMeta;
23
24struct AdtCompose {
25 uses: Vec<UseDeclaration>,
26 items: Vec<AdtItem>,
27}
28
29impl Parse for AdtCompose {
30 fn parse(input: ParseStream) -> Result<Self> {
31 let mut uses = Vec::new();
32 let mut items = Vec::new();
33
34 while input.peek(Token![use]) {
36 uses.push(input.parse::<UseDeclaration>()?);
37 if input.peek(Token![;]) {
38 input.parse::<Token![;]>()?;
39 }
40 }
41
42 while !input.is_empty() {
44 items.push(input.parse::<AdtItem>()?);
45 if input.peek(Token![;]) {
46 input.parse::<Token![;]>()?;
47 }
48 }
49
50 Ok(AdtCompose { uses, items })
51 }
52}
53
54enum AdtItem {
55 EnumDeclaration(EnumDeclaration),
56 PatternType(PatternTypeDeclaration),
57 SubtypeImpl(SubtypeImplDeclaration),
58 TypeAlias(TypeAlias),
59}
60
61impl Parse for AdtItem {
62 fn parse(input: ParseStream) -> Result<Self> {
63 if input.peek(Token![enum]) {
64 Ok(AdtItem::EnumDeclaration(EnumDeclaration::parse_with_attrs(
65 input,
66 Vec::new(),
67 Vec::new(),
68 )?))
69 } else if input.peek(Token![type]) {
70 let fork = input.fork();
72 if fork.parse::<Token![type]>().is_ok()
73 && fork.parse::<Ident>().is_ok()
74 && fork.parse::<Token![=]>().is_ok()
75 && fork.parse::<Ident>().is_ok()
76 && fork.peek(syn::Ident)
77 {
78 Ok(AdtItem::PatternType(input.parse()?))
80 } else {
81 Ok(AdtItem::TypeAlias(input.parse()?))
83 }
84 } else if input.peek(Token![impl]) {
85 Ok(AdtItem::SubtypeImpl(input.parse()?))
86 } else if input.peek(Token![#]) {
87 let attrs = syn::Attribute::parse_outer(input)?;
89
90 if input.peek(Token![impl]) {
91 Ok(AdtItem::SubtypeImpl(SubtypeImplDeclaration::parse_with_attrs(input, attrs)?))
96 } else if input.peek(Token![enum]) {
97 let (derives, other_attrs) = extract_derives(attrs)?;
98 Ok(AdtItem::EnumDeclaration(EnumDeclaration::parse_with_attrs(
99 input,
100 derives,
101 other_attrs,
102 )?))
103 } else {
104 Err(input.error("Expected 'enum' or 'impl' after attributes"))
105 }
106 } else {
107 Err(input.error("Expected 'enum', 'type', or 'impl' declaration"))
108 }
109 }
110}
111
112enum CompositionPart {
113 TypeRef(Ident, Option<syn::AngleBracketedGenericArguments>), BoxedTypeRef(Ident), InlineVariants { variants: Vec<Variant> }, }
117
118struct EnumBody(Vec<CompositionPart>);
119
120impl EnumBody {
121 fn parse_composition_parts(input: ParseStream, parts: &mut Vec<CompositionPart>) -> Result<()> {
122 loop {
123 if input.peek(syn::token::Brace) {
124 let variants_content;
126 braced!(variants_content in input);
127 let variants = variants_content.parse_terminated(Variant::parse, Token![,])?.into_iter().collect();
128 parts.push(CompositionPart::InlineVariants { variants });
129 } else if input.peek(Ident) && input.peek2(Token![<]) {
130 let ident: Ident = input.parse()?;
132 if ident == "Box" {
133 input.parse::<Token![<]>()?;
134 let type_name: Ident = input.parse()?;
135 input.parse::<Token![>]>()?;
136 parts.push(CompositionPart::BoxedTypeRef(type_name));
137 } else {
138 let generics: syn::AngleBracketedGenericArguments = input.parse()?;
140 parts.push(CompositionPart::TypeRef(ident, Some(generics)));
141 }
142 } else if input.peek(Ident) {
143 let type_name: Ident = input.parse()?;
145 parts.push(CompositionPart::TypeRef(type_name, None));
146 } else {
147 return Err(input.error("Expected type reference or inline variants"));
148 }
149
150 if input.peek(Token![|]) {
152 input.parse::<Token![|]>()?;
153 } else {
154 break;
155 }
156 }
157 Ok(())
158 }
159}
160
161impl Parse for EnumBody {
162 fn parse(input: ParseStream) -> Result<Self> {
163 if input.peek(syn::token::Brace) {
165 let content;
167 braced!(content in input);
168
169 if content.is_empty() {
170 return Err(content.error("Empty enum body"));
171 }
172
173 let mut variants = Vec::new();
175 while !content.is_empty() {
176 variants.push(content.parse::<Variant>()?);
177
178 if content.peek(Token![,]) {
179 content.parse::<Token![,]>()?;
180 } else if content.peek(Token![|]) {
181 return Err(content.error(
182 "Union syntax (|) is not allowed inside braces. To compose types, use: enum MyEnum = TypeA | TypeB | { variants }",
183 ));
184 } else if !content.is_empty() {
185 return Err(content.error("Expected ',' between variants"));
186 }
187 }
188 Ok(EnumBody(vec![CompositionPart::InlineVariants { variants }]))
189 } else {
190 let mut parts = Vec::new();
192 EnumBody::parse_composition_parts(input, &mut parts)?;
193 Ok(EnumBody(parts))
194 }
195 }
196}
197
198struct EnumDeclaration {
199 pub attrs: Vec<syn::Attribute>,
200 pub derives: Vec<syn::Path>,
201 pub name: Ident,
202 pub generics: Option<Generics>,
203 pub pattern_param: Option<(Ident, Ident)>, pub parts: EnumBody,
205}
206
207impl EnumDeclaration {
208 pub fn full_generics(&self) -> TokenStream2 {
210 match (&self.generics, &self.pattern_param) {
211 (Some(generics), Some((param_name, trait_name))) => {
212 let params = &generics.params;
213 quote! { <#params, #param_name: #trait_name> }
214 }
215 (Some(generics), None) => quote! { #generics },
216 (None, Some((param_name, trait_name))) => quote! { <#param_name: #trait_name> },
217 (None, None) => quote! {},
218 }
219 }
220
221 pub fn enum_type(&self) -> TokenStream2 {
223 let enum_name = &self.name;
224 if let Some((param_name, _)) = &self.pattern_param {
225 quote! { #enum_name<#param_name> }
226 } else {
227 let generics = &self.generics;
228 quote! { #enum_name #generics }
229 }
230 }
231}
232
233impl EnumDeclaration {
234 fn parse_with_attrs(input: ParseStream, derives: Vec<syn::Path>, attrs: Vec<syn::Attribute>) -> Result<Self> {
235 input.parse::<Token![enum]>()?;
237
238 let name: Ident = input.parse()?;
239
240 let generics = if input.peek(Token![<]) {
241 Some(input.parse::<Generics>()?)
242 } else {
243 None
244 };
245
246 let pattern_param = if input.peek(syn::Ident) && input.peek2(Token![<]) {
248 let is_kw: Ident = input.parse()?;
250 if is_kw != "is" {
251 return Err(syn::Error::new_spanned(is_kw, "Expected 'is' keyword"));
252 }
253
254 input.parse::<Token![<]>()?;
256 let param_name: Ident = input.parse()?;
257 input.parse::<Token![:]>()?;
258 let trait_name: Ident = input.parse()?;
259 input.parse::<Token![>]>()?;
260
261 Some((param_name, trait_name))
262 } else {
263 None
264 };
265
266 input.parse::<Token![=]>()?;
267
268 let parts = input.parse::<EnumBody>()?;
270
271 Ok(EnumDeclaration {
272 attrs,
273 derives,
274 name,
275 generics,
276 pattern_param,
277 parts,
278 })
279 }
280}
281
282impl Parse for EnumDeclaration {
283 fn parse(input: ParseStream) -> Result<Self> {
284 Self::parse_with_attrs(input, Vec::new(), Vec::new())
285 }
286}
287
288#[derive(Clone, Default)]
289struct FieldAttributes {
290 pub attrs: Vec<syn::Attribute>,
291 pub unsafe_transmute_check_iter: Option<String>,
293}
294
295struct PatternTypeDeclaration {
297 pub name: Ident,
298 pub base_type: Ident,
299 pub pattern: VariantPattern,
300}
301
302impl syn::parse::Parse for PatternTypeDeclaration {
303 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
304 input.parse::<Token![type]>()?;
305 let name: Ident = input.parse()?;
306 input.parse::<Token![=]>()?;
307 let base_type: Ident = input.parse()?;
308
309 let pattern = VariantPattern::parse_is_pattern(input)?;
310
311 Ok(Self { name, base_type, pattern })
312 }
313}
314
315#[derive(Debug, PartialEq)]
316enum SubtypeAttribute {
317 SubtypingRelation(SubtypingRelation),
318}
319
320struct SubtypeImplDeclaration {
321 subtype: Ident,
322 supertype: Ident,
323 attributes: Vec<SubtypeAttribute>,
324}
325
326impl SubtypeImplDeclaration {
327 fn parse_with_attrs(input: ParseStream, attrs: Vec<syn::Attribute>) -> Result<Self> {
328 let mut attributes = Vec::new();
329
330 for attr in attrs {
331 if attr.path().is_ident("derive") {
332 let nested = attr.parse_args_with(|input: ParseStream| {
334 let punctuated: Punctuated<NestedMeta, Token![,]> = Punctuated::parse_terminated(input)?;
335 Ok(punctuated)
336 })?;
337
338 for meta in nested {
339 if let NestedMeta::Meta(meta) = meta
340 && meta.path().is_ident("SubtypingRelation")
341 {
342 let subtyping_rel = SubtypingRelation::from_meta(&meta).map_err(|e| syn::Error::new_spanned(&meta, e.to_string()))?;
344 attributes.push(SubtypeAttribute::SubtypingRelation(subtyping_rel));
345 }
346 }
347 }
348 }
349
350 input.parse::<Token![impl]>()?;
351 let subtype: Ident = input.parse()?;
352 input.parse::<Token![:]>()?;
353 let supertype: Ident = input.parse()?;
354
355 Ok(SubtypeImplDeclaration {
356 subtype,
357 supertype,
358 attributes,
359 })
360 }
361}
362
363impl Parse for SubtypeImplDeclaration {
364 fn parse(input: ParseStream) -> Result<Self> {
365 let attrs = syn::Attribute::parse_outer(input)?;
366 Self::parse_with_attrs(input, attrs)
367 }
368}
369
370#[derive(Debug, FromMeta, PartialEq)]
376struct SubtypingRelation {
377 pub upcast: syn::Ident,
378 pub downcast: syn::Ident,
379}
380
381struct TypeAlias {
382 name: Ident,
383 ty: syn::Type,
384}
385
386impl Parse for TypeAlias {
387 fn parse(input: ParseStream) -> Result<Self> {
388 input.parse::<Token![type]>()?;
389 let name: Ident = input.parse()?;
390 input.parse::<Token![=]>()?;
391 let ty: syn::Type = input.parse()?;
392
393 Ok(TypeAlias { name, ty })
394 }
395}
396
397struct UseDeclaration {
398 path: syn::Path,
399}
400
401impl Parse for UseDeclaration {
402 fn parse(input: ParseStream) -> Result<Self> {
403 input.parse::<Token![use]>()?;
404 let path = input.parse::<syn::Path>()?;
405 Ok(UseDeclaration { path })
406 }
407}
408
409#[derive(Clone)]
410struct Variant {
411 pub attrs: Vec<syn::Attribute>,
412 pub name: Ident,
413 pub fields: Option<VariantFields>,
414}
415
416impl Parse for Variant {
417 fn parse(input: ParseStream) -> Result<Self> {
418 let attrs = syn::Attribute::parse_outer(input)?;
420
421 let name: Ident = input.parse()?;
422
423 let fields = if input.peek(syn::token::Brace) {
424 let content;
425 braced!(content in input);
426 let mut named_fields = Vec::new();
427
428 while !content.is_empty() {
429 let field_outer_attrs = syn::Attribute::parse_outer(&content)?;
431 let mut field_attrs = FieldAttributes {
432 attrs: field_outer_attrs.clone(),
433 ..Default::default()
434 };
435
436 for attr in &field_outer_attrs {
437 if attr.path().is_ident("unsafe_transmute_check") {
438 attr.parse_nested_meta(|meta| {
440 if meta.path.is_ident("iter") {
441 meta.input.parse::<Token![=]>()?;
442 let iter_expr: syn::LitStr = meta.input.parse()?;
443 field_attrs.unsafe_transmute_check_iter = Some(iter_expr.value());
444 }
445 Ok(())
446 })?;
447 }
448 }
449
450 let field_name: Ident = content.parse()?;
451 content.parse::<Token![:]>()?;
452 let field_type: syn::Type = content.parse()?;
453 named_fields.push((field_name, field_type, field_attrs));
454
455 if content.peek(Token![,]) {
456 content.parse::<Token![,]>()?;
457 }
458 }
459
460 Some(VariantFields::Named(named_fields))
461 } else if input.peek(syn::token::Paren) {
462 let content;
463 syn::parenthesized!(content in input);
464 let types = content.parse_terminated(syn::Type::parse, Token![,])?;
465 Some(VariantFields::Unnamed(types.into_iter().collect()))
466 } else {
467 None
468 };
469
470 Ok(Variant { attrs, name, fields })
471 }
472}
473
474#[derive(Clone)]
475enum VariantFields {
476 Named(Vec<(Ident, syn::Type, FieldAttributes)>),
477 Unnamed(Vec<syn::Type>),
478}
479
480#[derive(Debug)]
482enum VariantPattern {
483 Wildcard,
484 Variants(Vec<Ident>),
485}
486
487impl VariantPattern {
488 fn parse_variant_with_pattern(input: syn::parse::ParseStream) -> syn::Result<Ident> {
489 let variant: Ident = input.parse()?;
490
491 if input.peek(syn::token::Paren) {
493 let parens;
494 syn::parenthesized!(parens in input);
495 if parens.peek(Token![_]) {
497 parens.parse::<Token![_]>()?;
498 } else if !parens.is_empty() {
499 return Err(parens.error("Complex patterns are not supported. Only wildcard patterns (_) are allowed. Complex patterns like ranges, guards, and nested patterns will require native pattern types support in Rust."));
500 }
501 }
502
503 if input.peek(syn::token::Brace) {
505 let braces;
506 syn::braced!(braces in input);
507
508 if braces.peek(Token![..]) {
510 braces.parse::<Token![..]>()?;
511 if !braces.is_empty() {
512 return Err(braces.error("Only wildcard pattern { .. } is supported for struct variants"));
513 }
514 } else {
515 return Err(braces.error("Field patterns are not supported. Only wildcard pattern { .. } is allowed for struct variants. Field patterns will require native pattern types support in Rust."));
516 }
517 }
518
519 if input.peek(syn::Ident) && input.peek2(syn::Ident) {
521 let lookahead = input.lookahead1();
522 if lookahead.peek(syn::Ident) {
523 let fork = input.fork();
525 if let Ok(ident) = fork.parse::<syn::Ident>()
526 && ident == "if"
527 {
528 return Err(
529 input.error("Guard patterns with 'if' are not supported. Guards will require native pattern types support in Rust.")
530 );
531 }
532 }
533 }
534
535 Ok(variant)
536 }
537
538 pub fn parse_is_pattern(input: syn::parse::ParseStream) -> syn::Result<Self> {
539 let is_ident: Ident = input.parse()?;
541 if is_ident != "is" {
542 return Err(input.error("Expected 'is' keyword"));
543 }
544
545 if input.peek(Token![_]) {
547 input.parse::<Token![_]>()?;
548 return Ok(VariantPattern::Wildcard);
549 }
550
551 let mut variants = Vec::new();
553
554 let first_variant = Self::parse_variant_with_pattern(input)?;
556 variants.push(first_variant);
557
558 while input.peek(Token![|]) {
560 input.parse::<Token![|]>()?;
561 let variant = Self::parse_variant_with_pattern(input)?;
562 variants.push(variant);
563 }
564
565 Ok(VariantPattern::Variants(variants))
566 }
567}
568
569fn expand_pattern_wishcast(input: &AdtCompose) -> TokenStream2 {
570 let mut output = TokenStream2::new();
571
572 for use_decl in &input.uses {
574 let path = &use_decl.path;
575 output.extend(quote! {
576 use #path;
577 });
578 }
579
580 let mut enum_decls = Vec::new();
582 let mut pattern_types = Vec::new();
583 let mut subtype_impls = Vec::new();
584 let mut type_aliases = Vec::new();
585
586 for item in &input.items {
587 match item {
588 AdtItem::EnumDeclaration(e) => enum_decls.push(e),
589 AdtItem::PatternType(p) => pattern_types.push(p),
590 AdtItem::SubtypeImpl(s) => subtype_impls.push(s),
591 AdtItem::TypeAlias(t) => type_aliases.push(t),
592 }
593 }
594
595 let enum_map: std::collections::HashMap<String, &EnumDeclaration> = enum_decls.iter().map(|decl| (decl.name.to_string(), *decl)).collect();
597
598 if pattern_types.is_empty() {
600 for enum_decl in &enum_decls {
601 if enum_decl.pattern_param.is_some() {
602 let enum_name = &enum_decl.name;
603 return quote! {
604 compile_error!(concat!(
605 "Enum `", stringify!(#enum_name), "` declares pattern support with `is <P: ...>` but no pattern types are defined. ",
606 "Either: 1) Add pattern type declarations like `type FlexValue = ", stringify!(#enum_name), " is _;`, or ",
607 "2) Remove the `is <P: ...>` declaration if you don't need pattern-based strictness."
608 ));
609 };
610 }
611 }
612 }
613
614 for pattern_type in &pattern_types {
616 let base_type_name = pattern_type.base_type.to_string();
617 if let Some(enum_decl) = enum_map.get(&base_type_name) {
618 if enum_decl.pattern_param.is_none() {
619 return quote! {
620 compile_error!(concat!(
621 "Cannot create pattern type for enum `",
622 stringify!(#base_type_name),
623 "`. You must declare the enum with pattern support: `enum ",
624 stringify!(#base_type_name),
625 " is <P: PatternTrait> { ... }`"
626 ));
627 };
628 }
629 } else {
630 return quote! {
631 compile_error!(concat!("Unknown base type: ", stringify!(#base_type_name)));
632 };
633 }
634 }
635
636 for enum_decl in &enum_decls {
638 let enum_name = &enum_decl.name;
639
640 let enum_pattern_types: Vec<&PatternTypeDeclaration> = pattern_types.iter().filter(|pt| pt.base_type == *enum_name).copied().collect();
642
643 let mut enum_variants = Vec::new();
645 let mut variant_names = std::collections::HashSet::new();
646 let mut has_type_composition = false;
647
648 for part in &enum_decl.parts.0 {
649 match part {
650 CompositionPart::InlineVariants { variants } => {
651 for variant in variants {
652 variant_names.insert(variant.name.to_string());
653 enum_variants.push(variant.clone()); }
655 }
656 CompositionPart::TypeRef(type_name, generics) => {
657 has_type_composition = true;
658 variant_names.insert(type_name.to_string());
659 enum_variants.push(Variant {
660 attrs: Vec::new(),
661 name: type_name.clone(),
662 fields: Some(VariantFields::Unnamed(vec![syn::parse_quote! { #type_name #generics }])),
663 });
664 }
665 CompositionPart::BoxedTypeRef(type_name) => {
666 has_type_composition = true;
667 variant_names.insert(type_name.to_string());
668 enum_variants.push(Variant {
669 attrs: Vec::new(),
670 name: type_name.clone(),
671 fields: Some(VariantFields::Unnamed(vec![syn::parse_quote! { Box<#type_name> }])),
672 });
673 }
674 }
675 }
676
677 let conditional_variants = patterns::identify_conditional_variants(&enum_pattern_types, &variant_names);
678 let has_composition = !conditional_variants.is_empty() || has_type_composition;
679
680 if !enum_pattern_types.is_empty() && conditional_variants.is_empty() {
682 if enum_pattern_types.len() == 1 {
684 let single_pattern = &enum_pattern_types[0];
685 let pattern_name = &single_pattern.name;
686 return quote! {
687 compile_error!(concat!(
688 "Enum `", stringify!(#enum_name), "` has only one pattern type `", stringify!(#pattern_name), "`. ",
689 "Since there are no conditional variants, you don't need pattern support. ",
690 "Remove `is <P: PatternFields>` from the enum declaration and use a simple type alias instead: ",
691 "`type ", stringify!(#pattern_name), " = ", stringify!(#enum_name), ";`"
692 ));
693 };
694 } else {
695 return quote! {
696 compile_error!(concat!(
697 "No conditional variants found for enum `", stringify!(#enum_name), "`. ",
698 "All variants are included in all pattern types, making them identical. ",
699 "Either: 1) Add variants that are excluded from some pattern types, ",
700 "2) Use a single type alias instead of multiple identical ones, or ",
701 "3) Remove `is <P: PatternFields>` if you don't need strictness patterns."
702 ));
703 };
704 }
705 }
706
707 let (variants, type_transformer): (Vec<_>, Box<dyn Fn(&syn::Type) -> TokenStream2>) = if !conditional_variants.is_empty() {
709 let mut modified_variants = Vec::new();
711 let pattern_param_name = enum_decl.pattern_param.as_ref().map(|(param_name, _)| param_name).unwrap();
712
713 for variant in &enum_variants {
714 let variant_name = &variant.name;
715 let variant_name_str = variant_name.to_string();
716
717 let is_enum_variant = variant.fields.is_none() && enum_map.contains_key(&variant_name_str);
719 let is_type_ref_variant = matches!(
720 &variant.fields,
721 Some(VariantFields::Unnamed(types)) if types.len() == 1 && enum_map.contains_key(&variant_name_str)
722 );
723
724 if is_enum_variant || is_type_ref_variant {
725 let referenced_enum_name = &variant_name;
727
728 if conditional_variants.contains(&variant_name_str) {
729 let never_field_name = syn::Ident::new(&format!("{variant_name_str}Allowed"), variant_name.span());
731
732 let original_field_type = if let Some(VariantFields::Unnamed(types)) = &variant.fields {
734 types[0].clone()
735 } else {
736 syn::parse_quote! { #referenced_enum_name }
737 };
738
739 modified_variants.push(Variant {
740 attrs: variant.attrs.clone(),
741 name: variant_name.clone(),
742 fields: Some(VariantFields::Unnamed(vec![
743 original_field_type,
744 syn::parse_quote! { #pattern_param_name::#never_field_name },
745 ])),
746 });
747 } else {
748 let original_field_type = if let Some(VariantFields::Unnamed(types)) = &variant.fields {
750 types[0].clone()
751 } else {
752 syn::parse_quote! { #referenced_enum_name }
753 };
754
755 modified_variants.push(Variant {
756 attrs: variant.attrs.clone(),
757 name: variant_name.clone(),
758 fields: Some(VariantFields::Unnamed(vec![original_field_type])),
759 });
760 }
761 } else if conditional_variants.contains(&variant_name_str) {
762 let never_field_name = syn::Ident::new(&format!("{variant_name_str}Allowed"), variant_name.span());
764 let mut new_variant = variant.clone();
765
766 match &mut new_variant.fields {
767 Some(VariantFields::Named(fields)) => {
768 fields.push((
769 syn::Ident::new("_never", variant_name.span()),
770 syn::parse_quote! { #pattern_param_name::#never_field_name },
771 FieldAttributes::default(),
772 ));
773 }
774 Some(VariantFields::Unnamed(_)) => {
775 }
777 None => {
778 new_variant.fields = Some(VariantFields::Named(vec![(
779 syn::Ident::new("_never", variant_name.span()),
780 syn::parse_quote! { #pattern_param_name::#never_field_name },
781 FieldAttributes::default(),
782 )]));
783 }
784 }
785 modified_variants.push(new_variant);
786 } else {
787 modified_variants.push(variant.clone());
789 }
790 }
791
792 let pattern_param_name_clone = pattern_param_name.clone();
793 (
794 modified_variants,
795 Box::new(move |ty| codegen::fix_self_references(ty, enum_name, &pattern_param_name_clone)),
796 )
797 } else {
798 if has_composition {
800 (enum_variants.clone(), Box::new(|ty| quote! { #ty }))
801 } else {
802 (
803 enum_variants.clone(),
804 Box::new(|ty| codegen::fix_concrete_references(ty, &enum_map)),
805 )
806 }
807 };
808
809 let expanded_variants: Vec<_> = variants
811 .iter()
812 .map(|v| codegen::expand_variant_with(v, |ty| type_transformer(ty)))
813 .collect();
814
815 let full_generics = enum_decl.full_generics();
816
817 let derive_attr = if enum_decl.derives.is_empty() {
818 quote! { #[derive(Debug, Clone)] }
819 } else {
820 let paths = &enum_decl.derives;
821 quote! { #[derive(#(#paths),*)] }
822 };
823
824 let enum_attrs = &enum_decl.attrs;
825
826 output.extend(quote! {
827 #derive_attr
828 #(#enum_attrs)*
829 #[repr(C)]
830 pub enum #enum_name #full_generics {
831 #(#expanded_variants),*
832 }
833 });
834
835 if has_composition {
836 codegen::generate_from_traits(
837 &mut output,
838 enum_decl,
839 if conditional_variants.is_empty() {
840 None
841 } else {
842 Some(&conditional_variants)
843 },
844 );
845 }
846
847 if !conditional_variants.is_empty() {
849 let (_, strictness_trait_name) = enum_decl
851 .pattern_param
852 .as_ref()
853 .expect("conditional_variants requires pattern_param");
854
855 output.extend(patterns::generate_strictness_system(
857 enum_name,
858 strictness_trait_name,
859 &enum_pattern_types,
860 &conditional_variants,
861 ));
862
863 generate_subtype_conversions(
865 &mut output,
866 enum_decl,
867 &enum_variants,
868 &conditional_variants,
869 &subtype_impls,
870 &enum_pattern_types,
871 );
872
873 generate_subtyping_tests(&mut output, &enum_variants, &conditional_variants, &subtype_impls, &enum_map);
875 }
876 }
877
878 for alias in &type_aliases {
880 let name = &alias.name;
881 let ty = &alias.ty;
882 output.extend(quote! {
883 pub type #name = #ty;
884 });
885 }
886
887 output
888}
889
890fn extract_derives(attrs: Vec<syn::Attribute>) -> Result<(Vec<syn::Path>, Vec<syn::Attribute>)> {
892 let mut derives = Vec::new();
893 let mut other_attrs = Vec::new();
894 for attr in attrs {
895 if attr.path().is_ident("derive") {
896 attr.parse_nested_meta(|meta| {
897 derives.push(meta.path);
898 Ok(())
899 })?;
900 } else {
901 other_attrs.push(attr);
902 }
903 }
904 Ok((derives, other_attrs))
905}
906
907fn generate_subtype_conversions(
908 output: &mut TokenStream2,
909 enum_decl: &EnumDeclaration,
910 enum_variants: &[Variant],
911 conditional_variants: &std::collections::HashSet<String>,
912 subtype_impls: &[&SubtypeImplDeclaration],
913 pattern_types: &[&PatternTypeDeclaration],
914) {
915 let enum_name = &enum_decl.name;
916 let pattern_allowed_variants: std::collections::HashMap<String, Option<std::collections::HashSet<String>>> = pattern_types
917 .iter()
918 .map(|pt| {
919 let allowed = match &pt.pattern {
920 VariantPattern::Wildcard => None, VariantPattern::Variants(variants) => Some(variants.iter().map(|v| v.to_string()).collect()),
922 };
923 (pt.name.to_string(), allowed)
924 })
925 .collect();
926
927 let generate_variant_checks =
930 |supertype: &Ident, check_ident: &Ident, allowed_variants: Option<&std::collections::HashSet<String>>| -> Vec<TokenStream2> {
931 enum_variants
932 .iter()
933 .map(|variant| {
934 let variant_name = &variant.name;
935 let variant_name_str = variant_name.to_string();
936
937 let is_rejected = conditional_variants.contains(&variant_name_str)
939 && allowed_variants.is_some_and(|allowed| !allowed.contains(&variant_name_str));
940
941 if is_rejected {
942 quote! {
943 #supertype::#variant_name { .. } => Err(()),
944 }
945 } else {
946 let is_conditional = conditional_variants.contains(&variant_name_str);
949 match &variant.fields {
950 None => {
951 if is_conditional {
953 quote! {
954 #supertype::#variant_name { .. } => Ok(()),
955 }
956 } else {
957 quote! {
958 #supertype::#variant_name => Ok(()),
959 }
960 }
961 }
962 Some(VariantFields::Named(fields)) => {
963 let field_checks_with_names: Vec<_> = fields
964 .iter()
965 .filter_map(|(field_name, field_type, field_attrs)| {
966 field_checking::generate_field_check(field_name, field_type, field_attrs, check_ident, enum_name)
967 .map(|check| (field_name, check))
968 })
969 .collect();
970
971 if field_checks_with_names.is_empty() {
972 quote! {
973 #supertype::#variant_name { .. } => Ok(()),
974 }
975 } else {
976 let field_names: Vec<_> = field_checks_with_names.iter().map(|(name, _)| name).collect();
977 let field_checks: Vec<_> = field_checks_with_names.iter().map(|(_, check)| check).collect();
978 quote! {
979 #supertype::#variant_name { #(#field_names),*, .. } => {
980 #(#field_checks)*
981 Ok(())
982 },
983 }
984 }
985 }
986 Some(VariantFields::Unnamed(types)) => {
987 let field_names: Vec<_> = (0..types.len())
988 .map(|i| syn::Ident::new(&format!("field_{i}"), variant_name.span()))
989 .collect();
990 let field_checks: Vec<_> = types
991 .iter()
992 .enumerate()
993 .filter_map(|(i, field_type)| {
994 let field_name = &field_names[i];
995 let default_attrs = FieldAttributes::default();
996 field_checking::generate_field_check(field_name, field_type, &default_attrs, check_ident, enum_name)
997 })
998 .collect();
999
1000 if field_checks.is_empty() {
1001 quote! {
1003 #supertype::#variant_name(..) => Ok(()),
1004 }
1005 } else {
1006 quote! {
1007 #supertype::#variant_name(#(#field_names),*) => {
1008 #(#field_checks)*
1009 Ok(())
1010 },
1011 }
1012 }
1013 }
1014 }
1015 }
1016 })
1017 .collect()
1018 };
1019
1020 for subtype_impl in subtype_impls {
1022 for attr in &subtype_impl.attributes {
1023 let SubtypeAttribute::SubtypingRelation(rel) = attr;
1024 let subtype = &subtype_impl.subtype;
1025 let supertype = &subtype_impl.supertype;
1026
1027 let upcast_ident = rel.upcast.clone();
1029 let upcast_ref_ident = syn::Ident::new(&format!("{}_ref", rel.upcast), subtype.span());
1030 let downcast_ident = rel.downcast.clone();
1033 let downcast_ref_ident = syn::Ident::new(&format!("{}_ref", rel.downcast), supertype.span());
1034 let downcast_mut_ident = syn::Ident::new(&format!("{}_mut", rel.downcast), supertype.span());
1035 let check_ident = syn::Ident::new(
1036 &format!("check_{}", rel.downcast.to_string().trim_start_matches("try_")),
1037 supertype.span(),
1038 );
1039
1040 output.extend(quote! {
1042 impl #subtype {
1043 pub fn #upcast_ident(self) -> #supertype {
1044 unsafe { std::mem::transmute(self) }
1045 }
1046
1047 pub fn #upcast_ref_ident(&self) -> &#supertype {
1048 unsafe { std::mem::transmute(self) }
1049 }
1050
1051 }
1056 });
1057
1058 let subtype_allowed = pattern_allowed_variants.get(&subtype.to_string()).and_then(|opt| opt.as_ref());
1060 let variant_checks = generate_variant_checks(supertype, &check_ident, subtype_allowed);
1061
1062 output.extend(quote! {
1063 impl #supertype {
1064 pub fn #check_ident(&self) -> Result<(), ()> {
1065 match self {
1066 #(#variant_checks)*
1067 }
1068 }
1069
1070 pub fn #downcast_ident(self) -> Result<#subtype, Self> {
1071 match self.#check_ident() {
1072 Ok(()) => unsafe { Ok(std::mem::transmute(self)) },
1073 Err(()) => Err(self),
1074 }
1075 }
1076
1077 pub fn #downcast_ref_ident(&self) -> Result<&#subtype, ()> {
1078 match self.#check_ident() {
1079 Ok(()) => unsafe { Ok(std::mem::transmute(self)) },
1080 Err(()) => Err(()),
1081 }
1082 }
1083
1084 pub fn #downcast_mut_ident(&mut self) -> Result<&mut #subtype, ()> {
1085 match self.#check_ident() {
1086 Ok(()) => unsafe { Ok(std::mem::transmute(self)) },
1087 Err(()) => Err(()),
1088 }
1089 }
1090 }
1091 });
1092 }
1093 }
1094}
1095
1096fn generate_subtyping_tests(
1098 output: &mut TokenStream2,
1099 enum_variants: &[Variant],
1100 conditional_variants: &std::collections::HashSet<String>,
1101 subtype_impls: &[&SubtypeImplDeclaration],
1102 enum_map: &std::collections::HashMap<String, &EnumDeclaration>,
1103) {
1104 for subtype_impl in subtype_impls {
1105 for attr in &subtype_impl.attributes {
1106 let SubtypeAttribute::SubtypingRelation(rel) = attr;
1107 let subtype = &subtype_impl.subtype;
1108 let supertype = &subtype_impl.supertype;
1109
1110 let upcast_ident = &rel.upcast;
1112 let upcast_ref_ident = syn::Ident::new(&format!("{}_ref", rel.upcast), subtype.span());
1113 let downcast_ident = &rel.downcast;
1114
1115 let test_fn_name = syn::Ident::new(
1117 &format!(
1118 "test_subtyping_{}_{}",
1119 subtype.to_string().to_lowercase(),
1120 supertype.to_string().to_lowercase()
1121 ),
1122 subtype.span(),
1123 );
1124
1125 'variant_loop: for variant in enum_variants.iter().filter(|v| !conditional_variants.contains(&v.name.to_string())) {
1127 let variant_name = &variant.name;
1128
1129 let test_constructor = match &variant.fields {
1131 None => quote! { #subtype::#variant_name },
1132 Some(VariantFields::Named(fields)) => {
1133 let mut field_inits = Vec::new();
1134 for (name, ty, _attrs) in fields {
1135 match generate_test_value_for_type(ty, enum_map) {
1136 Ok(test_value) => {
1137 field_inits.push(quote! { #name: #test_value });
1138 }
1139 Err(_) => {
1140 continue 'variant_loop;
1142 }
1143 }
1144 }
1145 quote! { #subtype::#variant_name { #(#field_inits),* } }
1146 }
1147 Some(VariantFields::Unnamed(types)) => {
1148 if types.len() == 1 {
1150 let ty = &types[0];
1152 match generate_test_value_for_type(ty, enum_map) {
1153 Ok(test_value) => {
1154 quote! { #subtype::#variant_name(#test_value) }
1155 }
1156 Err(_) => {
1157 continue 'variant_loop;
1159 }
1160 }
1161 } else {
1162 let mut test_values = Vec::new();
1164 for ty in types {
1165 match generate_test_value_for_type(ty, enum_map) {
1166 Ok(test_value) => {
1167 test_values.push(test_value);
1168 }
1169 Err(_) => {
1170 continue 'variant_loop;
1172 }
1173 }
1174 }
1175 quote! { #subtype::#variant_name(#(#test_values),*) }
1176 }
1177 }
1178 };
1179
1180 let match_pattern = match &variant.fields {
1182 None => quote! { #supertype::#variant_name },
1183 Some(VariantFields::Named(_)) => quote! { #supertype::#variant_name { .. } },
1184 Some(VariantFields::Unnamed(_)) => quote! { #supertype::#variant_name(..) },
1185 };
1186
1187 output.extend(quote! {
1188 #[cfg(test)]
1189 #[test]
1190 fn #test_fn_name() {
1191 use std::mem::discriminant;
1192
1193 let strict = #test_constructor;
1195 let flex = strict.#upcast_ident();
1196
1197 let strict_disc = discriminant(&#test_constructor);
1199 let flex_disc = discriminant(&flex);
1200
1201 let strict_raw: usize = unsafe { *(&strict_disc as *const _ as *const usize) };
1203 let flex_raw: usize = unsafe { *(&flex_disc as *const _ as *const usize) };
1204
1205 assert_eq!(strict_raw, flex_raw, "Raw discriminants should match between {} and {}", stringify!(#subtype), stringify!(#supertype));
1207
1208 let mut strict_for_ref = #test_constructor;
1210
1211 let flex_ref: &#supertype = strict_for_ref.#upcast_ref_ident();
1213 assert!(matches!(flex_ref, #match_pattern), "Reference conversion failed");
1214
1215
1216 let strict_ptr = &strict_for_ref as *const _ as usize;
1218 let flex_ptr = strict_for_ref.#upcast_ref_ident() as *const _ as usize;
1219 assert_eq!(strict_ptr, flex_ptr, "Reference conversion changed pointer");
1220
1221 let upcast_value = #test_constructor.#upcast_ident();
1223 match upcast_value.#downcast_ident() {
1224 Ok(downcast) => {
1225 let downcast_disc = discriminant(&downcast);
1227 let original_disc = discriminant(&#test_constructor);
1228 assert_eq!(downcast_disc, original_disc, "Round-trip conversion corrupted discriminant");
1229 }
1230 Err(_) => panic!("Valid variant should round-trip successfully"),
1231 }
1232 }
1233 });
1234
1235 break 'variant_loop;
1237 }
1238 }
1239 }
1240}
1241
1242fn generate_test_value_for_type(
1244 ty: &syn::Type,
1245 enum_map: &std::collections::HashMap<String, &EnumDeclaration>,
1246) -> std::result::Result<TokenStream2, String> {
1247 let type_str = quote! { #ty }.to_string();
1249
1250 if type_str.contains("String") {
1251 Ok(quote! { "test".to_string() })
1252 } else if type_str.contains("Box<") {
1253 if let syn::Type::Path(type_path) = ty
1255 && let Some(segment) = type_path.path.segments.last()
1256 && segment.ident == "Box"
1257 && let syn::PathArguments::AngleBracketed(args) = &segment.arguments
1258 && let Some(syn::GenericArgument::Type(inner_ty)) = args.args.first()
1259 {
1260 let inner_value = generate_test_value_for_type(inner_ty, enum_map)?;
1261 return Ok(quote! { Box::new(#inner_value) });
1262 }
1263 Err(format!("Could not parse Box type: {type_str}"))
1264 } else if type_str.contains("Vec<") {
1265 Ok(quote! { vec![] })
1266 } else if type_str.contains("i32") || type_str.contains("i64") {
1267 Ok(quote! { 42 })
1268 } else if type_str.contains("usize") {
1269 Ok(quote! { 0 })
1270 } else if type_str.contains("bool") {
1271 Ok(quote! { true })
1272 } else if let syn::Type::Path(type_path) = ty {
1273 if let Some(segment) = type_path.path.segments.last() {
1275 let type_name = segment.ident.to_string();
1276 if let Some(enum_decl) = enum_map.get(&type_name) {
1277 if let Some(simple_variant) = enum_decl.parts.0.iter().find_map(|part| match part {
1279 crate::CompositionPart::InlineVariants { variants } => variants.iter().find(|v| v.fields.is_none()),
1280 _ => None,
1281 }) {
1282 let variant_name = &simple_variant.name;
1283 let type_ident = syn::Ident::new(&type_name, variant_name.span());
1284 Ok(quote! { #type_ident::#variant_name })
1285 } else {
1286 Err(format!("No unit variant found in enum {type_name}"))
1287 }
1288 } else {
1289 Err(format!("Unknown type: {type_name}"))
1290 }
1291 } else {
1292 Err(format!("Complex path type not supported: {type_str}"))
1293 }
1294 } else {
1295 Err(format!("Unsupported type for test generation: {type_str}"))
1296 }
1297}
1298
1299#[proc_macro]
1300pub fn pattern_wishcast(tokens: TokenStream) -> TokenStream {
1301 let input = parse_macro_input!(tokens as AdtCompose);
1302 let expanded = expand_pattern_wishcast(&input);
1303 TokenStream::from(expanded)
1304}