rustc_macros/
try_from.rs
1use proc_macro2::TokenStream;
2use quote::{quote, quote_spanned};
3use syn::Data;
4use syn::spanned::Spanned;
5use synstructure::Structure;
6
7pub(crate) fn try_from_u32(s: Structure<'_>) -> TokenStream {
8 let span_error = |span, message: &str| {
9 quote_spanned! { span => const _: () = ::core::compile_error!(#message); }
10 };
11
12 if let Some(span) = match &s.ast().data {
14 Data::Enum(_) => None,
15 Data::Struct(s) => Some(s.struct_token.span()),
16 Data::Union(u) => Some(u.union_token.span()),
17 } {
18 return span_error(span, "type is not an enum (TryFromU32)");
19 }
20
21 let variant_field_errors = s
23 .variants()
24 .iter()
25 .filter_map(|v| v.ast().fields.iter().map(|f| f.span()).next())
26 .map(|span| span_error(span, "enum variant cannot have fields (TryFromU32)"))
27 .collect::<TokenStream>();
28 if !variant_field_errors.is_empty() {
29 return variant_field_errors;
30 }
31
32 let ctor = s
33 .variants()
34 .iter()
35 .map(|v| v.construct(|_, _| -> TokenStream { unreachable!() }))
36 .collect::<Vec<_>>();
37 #[allow(keyword_idents_2024)]
39 s.gen_impl(quote! {
40 use ::core::convert::TryFrom;
42 use ::core::primitive::u32;
43 use ::core::result::Result::{self, Ok, Err};
44
45 gen impl TryFrom<u32> for @Self {
46 type Error = u32;
47
48 #[allow(deprecated)] fn try_from(value: u32) -> Result<Self, Self::Error> {
50 #( if value == const { #ctor as u32 } { return Ok(#ctor) } )*
51 Err(value)
52 }
53 }
54 })
55}