Skip to main content

pattern_wishcast_macros/
lib.rs

1// SPDX-FileCopyrightText: 2025 LunNova
2//
3// SPDX-License-Identifier: MIT
4
5mod 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		// Parse use declarations first
35		while input.peek(Token![use]) {
36			uses.push(input.parse::<UseDeclaration>()?);
37			if input.peek(Token![;]) {
38				input.parse::<Token![;]>()?;
39			}
40		}
41
42		// Parse items
43		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			// Disambiguate between pattern types and simple type aliases
71			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				// This looks like a pattern type (type X = Y is ...)
79				Ok(AdtItem::PatternType(input.parse()?))
80			} else {
81				// This is a simple type alias (type X = Y<T>)
82				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			// Parse outer attributes first
88			let attrs = syn::Attribute::parse_outer(input)?;
89
90			if input.peek(Token![impl]) {
91				// Re-inject attributes for SubtypeImplDeclaration parsing
92				// SubtypeImplDeclaration expects to parse its own attributes, so we need
93				// to handle this differently - it already handles #[derive(SubtypingRelation(...))]
94				// For now, extract derives and pass them, but SubtypeImpl has its own attr handling
95				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>), // External enum like CoreAtoms or Container<T>
114	BoxedTypeRef(Ident),                                         // Box<TypedTermComplex>
115	InlineVariants { variants: Vec<Variant> },                   // { ... }
116}
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				// Inline variants: { ... }
125				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				// Generic type reference like Container<T> or Box<Type>
131				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					// Generic type reference - preserve the generics
139					let generics: syn::AngleBracketedGenericArguments = input.parse()?;
140					parts.push(CompositionPart::TypeRef(ident, Some(generics)));
141				}
142			} else if input.peek(Ident) {
143				// Simple type reference
144				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			// Check for continuation with |
151			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		// Handle both braced and direct union syntax
164		if input.peek(syn::token::Brace) {
165			// New syntax: = { ... }
166			let content;
167			braced!(content in input);
168
169			if content.is_empty() {
170				return Err(content.error("Empty enum body"));
171			}
172
173			// Inside braces, we only allow simple variants, not union syntax
174			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			// Direct syntax: = TypeRef | TypeRef | { ... }
191			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)>, // (param_name, trait_name) for "is <P: PatternFields>"
204	pub parts: EnumBody,
205}
206
207impl EnumDeclaration {
208	/// Build the complete generics list combining regular generics with optional pattern parameter
209	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	/// Build the enum type with appropriate generic parameters
222	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		// 'enum' keyword is now mandatory
236		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		// Check for "is <P: Trait>" pattern parameter
247		let pattern_param = if input.peek(syn::Ident) && input.peek2(Token![<]) {
248			// Parse "is" keyword
249			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			// Parse <P: Trait>
255			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		// Parse composition - can be simple variants or union syntax
269		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	/// Safety-critical iteration expression for pattern checking
292	pub unsafe_transmute_check_iter: Option<String>,
293}
294
295/// Cleaner pattern type declaration
296struct 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				// Parse the meta list inside derive(...)
333				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						// Use darling to parse the SubtypingRelation
343						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/// Parse #[derive(SubtypingRelation(upcast=to_flex, downcast=try_to_strict))]
371// <generated by cargo-derive-doc>
372// Macro expansions:
373//   impl ::darling::FromMeta for SubtypingRelation
374// </generated by cargo-derive-doc>
375#[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		// Parse variant-level attributes (including doc comments)
419		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				// Parse field attributes (including doc comments)
430				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						// Parse the attribute content
439						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/// Parse pattern types more cleanly
481#[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		// Handle pattern like (_) after variant name
492		if input.peek(syn::token::Paren) {
493			let parens;
494			syn::parenthesized!(parens in input);
495			// Only support wildcard patterns for now
496			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		// Handle struct variant wildcard like { .. }
504		if input.peek(syn::token::Brace) {
505			let braces;
506			syn::braced!(braces in input);
507
508			// Check for .. wildcard
509			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		// Check for guard patterns with 'if'
520		if input.peek(syn::Ident) && input.peek2(syn::Ident) {
521			let lookahead = input.lookahead1();
522			if lookahead.peek(syn::Ident) {
523				// Try to parse an identifier to see if it's "if"
524				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		// Look for "is"
540		let is_ident: Ident = input.parse()?;
541		if is_ident != "is" {
542			return Err(input.error("Expected 'is' keyword"));
543		}
544
545		// Check for wildcard
546		if input.peek(Token![_]) {
547			input.parse::<Token![_]>()?;
548			return Ok(VariantPattern::Wildcard);
549		}
550
551		// Parse variant list directly (no outer braces required)
552		let mut variants = Vec::new();
553
554		// Parse first variant
555		let first_variant = Self::parse_variant_with_pattern(input)?;
556		variants.push(first_variant);
557
558		// Continue parsing additional variants separated by |
559		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	// Generate use statements
573	for use_decl in &input.uses {
574		let path = &use_decl.path;
575		output.extend(quote! {
576			use #path;
577		});
578	}
579
580	// Separate items by type for processing
581	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	// Create a map of enum names to their declarations for cross-referencing
596	let enum_map: std::collections::HashMap<String, &EnumDeclaration> = enum_decls.iter().map(|decl| (decl.name.to_string(), *decl)).collect();
597
598	// Check if any enum declares pattern support but has no pattern types
599	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	// Validate that pattern types only reference enums with pattern parameters
615	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	// Process each enum individually
637	for enum_decl in &enum_decls {
638		let enum_name = &enum_decl.name;
639
640		// Find pattern types for this enum directly
641		let enum_pattern_types: Vec<&PatternTypeDeclaration> = pattern_types.iter().filter(|pt| pt.base_type == *enum_name).copied().collect();
642
643		// Build variants and analyze composition in one efficient pass
644		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()); // Still need owned for later modification
654					}
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		// Validate pattern enums that declare support but have no conditional variants
681		if !enum_pattern_types.is_empty() && conditional_variants.is_empty() {
682			// Generate appropriate error messages
683			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		// Generate enum with variant transformation based on pattern analysis
708		let (variants, type_transformer): (Vec<_>, Box<dyn Fn(&syn::Type) -> TokenStream2>) = if !conditional_variants.is_empty() {
709			// Pattern enum: apply pattern transformation to variants
710			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				// Check if this is an enum-as-variant (either unit variant or TypeRef/BoxedTypeRef)
718				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					// Enum-as-variant (either unit or type reference)
726					let referenced_enum_name = &variant_name;
727
728					if conditional_variants.contains(&variant_name_str) {
729						// Conditional enum-as-variant as tuple (value, trait_assoc_type)
730						let never_field_name = syn::Ident::new(&format!("{variant_name_str}Allowed"), variant_name.span());
731
732						// Preserve original field type for type references (including Box<T>)
733						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						// Regular enum-as-variant - preserve original field type
749						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					// Conditional variant with _never field
763					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							// Skip tuple variants with conditionals for now
776						}
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					// Regular variant
788					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			// Simple enum: choose strategy based on composition
799			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		// Transform variants using the appropriate strategy
810		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		// Only do pattern-specific generation if we have conditional variants
848		if !conditional_variants.is_empty() {
849			// pattern_param is guaranteed Some when conditional_variants is non-empty
850			let (_, strictness_trait_name) = enum_decl
851				.pattern_param
852				.as_ref()
853				.expect("conditional_variants requires pattern_param");
854
855			// Generate strictness system
856			output.extend(patterns::generate_strictness_system(
857				enum_name,
858				strictness_trait_name,
859				&enum_pattern_types,
860				&conditional_variants,
861			));
862
863			// Generate conversion methods
864			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 automatic tests for subtyping relationships
874			generate_subtyping_tests(&mut output, &enum_variants, &conditional_variants, &subtype_impls, &enum_map);
875		}
876	}
877
878	// Generate simple type aliases
879	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
890/// Extract derive macro paths from attributes, returning (derives, other_attrs)
891fn 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, // All variants allowed
921				VariantPattern::Variants(variants) => Some(variants.iter().map(|v| v.to_string()).collect()),
922			};
923			(pt.name.to_string(), allowed)
924		})
925		.collect();
926
927	// Helper function to generate variant checks for a given check method
928	// `allowed_variants` is the set of variants allowed in the target pattern (None = wildcard)
929	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					// A variant is rejected if it's conditional AND not in the target pattern's allowed list
938					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						// Generate recursive checking for allowed variants
947						// Note: conditional variants have a _never field added, so use { .. } pattern
948						let is_conditional = conditional_variants.contains(&variant_name_str);
949						match &variant.fields {
950							None => {
951								// Unit variant - but if conditional, it has _never field added
952								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									// Use wildcard pattern when no field checks are needed
1002									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	// Generate conversion methods based on subtype implementations specified in the macro
1021	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			// Generate method names
1028			let upcast_ident = rel.upcast.clone();
1029			let upcast_ref_ident = syn::Ident::new(&format!("{}_ref", rel.upcast), subtype.span());
1030			// NOTE: We don't generate upcast_mut_ident because mutable upcasts are unsound
1031
1032			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			// Generate safe upcast conversions (subtype -> supertype)
1041			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					// NOTE: We intentionally do NOT generate an upcast_mut method
1052					// Upcasting &mut SubType to &mut SuperType is unsound!
1053					// It would allow writing SuperType-only variants through the reference,
1054					// violating SubType's invariants.
1055				}
1056			});
1057
1058			// Generate checked downcast conversions (supertype -> subtype)
1059			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
1096/// Generate automatic test code for subtyping relationships to verify transmute safety
1097fn 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			// Generate method names
1111			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			// Generate test function name
1116			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			// Find a non-conditional variant to use for testing
1126			'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				// Generate test constructor based on variant fields
1130				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									// Skip generating tests for variants with unsupported field types
1141									continue 'variant_loop;
1142								}
1143							}
1144						}
1145						quote! { #subtype::#variant_name { #(#field_inits),* } }
1146					}
1147					Some(VariantFields::Unnamed(types)) => {
1148						// For tuple variants, we need to handle union composition vs inline variants differently
1149						if types.len() == 1 {
1150							// This is likely a union composition variant like CoreAtoms(CoreAtoms)
1151							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									// Skip generating tests for variants with unsupported field types
1158									continue 'variant_loop;
1159								}
1160							}
1161						} else {
1162							// Multiple fields - generate test values for each
1163							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										// Skip generating tests for variants with unsupported field types
1171										continue 'variant_loop;
1172									}
1173								}
1174							}
1175							quote! { #subtype::#variant_name(#(#test_values),*) }
1176						}
1177					}
1178				};
1179
1180				// Generate appropriate match pattern based on variant type
1181				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						// Test discriminant preservation
1194						let strict = #test_constructor;
1195						let flex = strict.#upcast_ident();
1196
1197						// Get discriminant values
1198						let strict_disc = discriminant(&#test_constructor);
1199						let flex_disc = discriminant(&flex);
1200
1201						// Get raw discriminant values for comparison
1202						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						// Should have same raw value
1206						assert_eq!(strict_raw, flex_raw, "Raw discriminants should match between {} and {}", stringify!(#subtype), stringify!(#supertype));
1207
1208						// Test reference conversions
1209						let mut strict_for_ref = #test_constructor;
1210
1211						// Test immutable reference conversion
1212						let flex_ref: &#supertype = strict_for_ref.#upcast_ref_ident();
1213						assert!(matches!(flex_ref, #match_pattern), "Reference conversion failed");
1214
1215
1216						// Test pointer identity
1217						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						// Test round-trip conversion for allowed variants
1222						let upcast_value = #test_constructor.#upcast_ident();
1223						match upcast_value.#downcast_ident() {
1224							Ok(downcast) => {
1225								// Should be able to round-trip successfully
1226								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				// Successfully generated a test, break out of the variant loop
1236				break 'variant_loop;
1237			}
1238		}
1239	}
1240}
1241
1242/// Generate a simple test value for a given type
1243fn generate_test_value_for_type(
1244	ty: &syn::Type,
1245	enum_map: &std::collections::HashMap<String, &EnumDeclaration>,
1246) -> std::result::Result<TokenStream2, String> {
1247	// Extract the base type name for simple pattern matching
1248	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		// For Box<T>, recursively generate the inner value
1254		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		// Check if this is a known enum type
1274		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				// Find the first unit variant or simplest variant to construct
1278				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}