add PhantomConstGet to the known Type bounds for #[hdl] struct/enum
This commit is contained in:
		
							parent
							
								
									4b24a88641
								
							
						
					
					
						commit
						0b82178740
					
				
					 4 changed files with 251 additions and 117 deletions
				
			
		|  | @ -3,111 +3,19 @@ | ||||||
| use crate::{ | use crate::{ | ||||||
|     Errors, HdlAttr, |     Errors, HdlAttr, | ||||||
|     hdl_type_common::{ |     hdl_type_common::{ | ||||||
|         ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedGenerics, ParsedType, TypesParser, |         ItemOptions, MakeHdlTypeExpr, MaybeParsed, ParsedGenerics, ParsedType, | ||||||
|         WrappedInConst, common_derives, get_target, known_items, |         PhantomConstGetBound, TypesParser, WrappedInConst, common_derives, get_target, known_items, | ||||||
|     }, |     }, | ||||||
|     kw, |     kw, | ||||||
| }; | }; | ||||||
| use proc_macro2::TokenStream; | use proc_macro2::TokenStream; | ||||||
| use quote::{ToTokens, format_ident, quote_spanned}; | use quote::{ToTokens, format_ident, quote_spanned}; | ||||||
| use syn::{ | use syn::{ | ||||||
|     AngleBracketedGenericArguments, Attribute, Expr, Fields, GenericArgument, GenericParam, |     Attribute, Expr, Fields, GenericParam, Generics, Ident, ItemStruct, ItemType, Token, Type, | ||||||
|     Generics, Ident, ItemStruct, ItemType, Path, PathArguments, Token, TraitBound, |     TypeGroup, TypeParam, TypeParen, Visibility, parse_quote_spanned, punctuated::Pair, | ||||||
|     TraitBoundModifier, Type, TypeGroup, TypeParam, TypeParamBound, TypeParen, Visibility, |     token::Paren, | ||||||
|     parse_quote_spanned, punctuated::Pair, token::Paren, |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug)] |  | ||||||
| pub(crate) struct PhantomConstGetBound { |  | ||||||
|     pub(crate) phantom_const_get: known_items::PhantomConstGet, |  | ||||||
|     pub(crate) colon2_token: Option<Token![::]>, |  | ||||||
|     pub(crate) lt_token: Token![<], |  | ||||||
|     pub(crate) ty: Type, |  | ||||||
|     pub(crate) comma_token: Option<Token![,]>, |  | ||||||
|     pub(crate) gt_token: Token![>], |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl From<PhantomConstGetBound> for Path { |  | ||||||
|     fn from(value: PhantomConstGetBound) -> Self { |  | ||||||
|         let PhantomConstGetBound { |  | ||||||
|             phantom_const_get, |  | ||||||
|             colon2_token, |  | ||||||
|             lt_token, |  | ||||||
|             ty, |  | ||||||
|             comma_token, |  | ||||||
|             gt_token, |  | ||||||
|         } = value; |  | ||||||
|         let mut path = phantom_const_get.path; |  | ||||||
|         path.segments.last_mut().expect("known to exist").arguments = |  | ||||||
|             PathArguments::AngleBracketed(AngleBracketedGenericArguments { |  | ||||||
|                 colon2_token, |  | ||||||
|                 lt_token, |  | ||||||
|                 args: FromIterator::from_iter([Pair::new(GenericArgument::Type(ty), comma_token)]), |  | ||||||
|                 gt_token, |  | ||||||
|             }); |  | ||||||
|         path |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl From<PhantomConstGetBound> for TraitBound { |  | ||||||
|     fn from(value: PhantomConstGetBound) -> Self { |  | ||||||
|         let path = Path::from(value); |  | ||||||
|         TraitBound { |  | ||||||
|             paren_token: None, |  | ||||||
|             modifier: TraitBoundModifier::None, |  | ||||||
|             lifetimes: None, |  | ||||||
|             path, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl From<PhantomConstGetBound> for TypeParamBound { |  | ||||||
|     fn from(value: PhantomConstGetBound) -> Self { |  | ||||||
|         TraitBound::from(value).into() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl PhantomConstGetBound { |  | ||||||
|     fn parse_opt(bound: TypeParamBound) -> Option<Self> { |  | ||||||
|         let TypeParamBound::Trait(TraitBound { |  | ||||||
|             paren_token: None, |  | ||||||
|             modifier: TraitBoundModifier::None, |  | ||||||
|             lifetimes: None, |  | ||||||
|             path, |  | ||||||
|         }) = bound |  | ||||||
|         else { |  | ||||||
|             return None; |  | ||||||
|         }; |  | ||||||
|         let Ok(( |  | ||||||
|             phantom_const_get, |  | ||||||
|             PathArguments::AngleBracketed(AngleBracketedGenericArguments { |  | ||||||
|                 colon2_token, |  | ||||||
|                 lt_token, |  | ||||||
|                 args, |  | ||||||
|                 gt_token, |  | ||||||
|             }), |  | ||||||
|         )) = known_items::PhantomConstGet::parse_path_with_arguments(path) |  | ||||||
|         else { |  | ||||||
|             return None; |  | ||||||
|         }; |  | ||||||
|         let mut args = args.into_pairs(); |  | ||||||
|         let (GenericArgument::Type(ty), comma_token) = args.next()?.into_tuple() else { |  | ||||||
|             return None; |  | ||||||
|         }; |  | ||||||
|         let None = args.next() else { |  | ||||||
|             return None; |  | ||||||
|         }; |  | ||||||
|         Some(Self { |  | ||||||
|             phantom_const_get, |  | ||||||
|             colon2_token, |  | ||||||
|             lt_token, |  | ||||||
|             ty, |  | ||||||
|             comma_token, |  | ||||||
|             gt_token, |  | ||||||
|         }) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Clone, Debug)] | #[derive(Clone, Debug)] | ||||||
| pub(crate) struct PhantomConstAccessorTypeParam { | pub(crate) struct PhantomConstAccessorTypeParam { | ||||||
|     attrs: Vec<Attribute>, |     attrs: Vec<Attribute>, | ||||||
|  | @ -162,7 +70,9 @@ impl PhantomConstAccessorTypeParam { | ||||||
|         let colon_token = colon_token.unwrap_or(Token)); |         let colon_token = colon_token.unwrap_or(Token)); | ||||||
|         let mut bounds = bounds.into_pairs(); |         let mut bounds = bounds.into_pairs(); | ||||||
|         let (bound, plus_token) = bounds.next()?.into_tuple(); |         let (bound, plus_token) = bounds.next()?.into_tuple(); | ||||||
|         let phantom_const_get_bound = PhantomConstGetBound::parse_opt(bound)?; |         let phantom_const_get_bound = PhantomConstGetBound::parse_type_param_bound(bound) | ||||||
|  |             .ok()? | ||||||
|  |             .ok()?; | ||||||
|         let None = bounds.next() else { |         let None = bounds.next() else { | ||||||
|             return None; |             return None; | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  | @ -8,9 +8,9 @@ use syn::{ | ||||||
|     AngleBracketedGenericArguments, Attribute, Block, ConstParam, Expr, ExprBlock, ExprGroup, |     AngleBracketedGenericArguments, Attribute, Block, ConstParam, Expr, ExprBlock, ExprGroup, | ||||||
|     ExprIndex, ExprParen, ExprPath, ExprTuple, Field, FieldMutability, Fields, FieldsNamed, |     ExprIndex, ExprParen, ExprPath, ExprTuple, Field, FieldMutability, Fields, FieldsNamed, | ||||||
|     FieldsUnnamed, GenericArgument, GenericParam, Generics, Ident, ImplGenerics, Index, ItemStruct, |     FieldsUnnamed, GenericArgument, GenericParam, Generics, Ident, ImplGenerics, Index, ItemStruct, | ||||||
|     Path, PathArguments, PathSegment, PredicateType, QSelf, Stmt, Token, Turbofish, Type, |     Path, PathArguments, PathSegment, PredicateType, QSelf, Stmt, Token, TraitBound, Turbofish, | ||||||
|     TypeGenerics, TypeGroup, TypeParam, TypeParen, TypePath, TypeTuple, Visibility, WhereClause, |     Type, TypeGenerics, TypeGroup, TypeParam, TypeParamBound, TypeParen, TypePath, TypeTuple, | ||||||
|     WherePredicate, |     Visibility, WhereClause, WherePredicate, | ||||||
|     parse::{Parse, ParseStream}, |     parse::{Parse, ParseStream}, | ||||||
|     parse_quote, parse_quote_spanned, |     parse_quote, parse_quote_spanned, | ||||||
|     punctuated::{Pair, Punctuated}, |     punctuated::{Pair, Punctuated}, | ||||||
|  | @ -2065,6 +2065,174 @@ pub(crate) mod known_items { | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Clone, Debug)] | ||||||
|  | pub(crate) struct PhantomConstGetBound { | ||||||
|  |     pub(crate) phantom_const_get: known_items::PhantomConstGet, | ||||||
|  |     pub(crate) colon2_token: Option<Token![::]>, | ||||||
|  |     pub(crate) lt_token: Token![<], | ||||||
|  |     pub(crate) ty: Type, | ||||||
|  |     pub(crate) comma_token: Option<Token![,]>, | ||||||
|  |     pub(crate) gt_token: Token![>], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl PhantomConstGetBound { | ||||||
|  |     pub(crate) fn parse_path_with_arguments(path: Path) -> syn::Result<Result<Self, Path>> { | ||||||
|  |         match known_items::PhantomConstGet::parse_path_with_arguments(path) { | ||||||
|  |             Ok((phantom_const_get, arguments)) => { | ||||||
|  |                 Self::parse_path_and_arguments(phantom_const_get, arguments).map(Ok) | ||||||
|  |             } | ||||||
|  |             Err(path) => Ok(Err(path)), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     pub(crate) fn parse_path_and_arguments( | ||||||
|  |         phantom_const_get: known_items::PhantomConstGet, | ||||||
|  |         arguments: PathArguments, | ||||||
|  |     ) -> syn::Result<Self> { | ||||||
|  |         let error = |arguments: PathArguments, message: &str| { | ||||||
|  |             let mut path = phantom_const_get.path.clone(); | ||||||
|  |             path.segments.last_mut().expect("known to exist").arguments = arguments; | ||||||
|  |             syn::Error::new_spanned(path, message) | ||||||
|  |         }; | ||||||
|  |         match arguments { | ||||||
|  |             PathArguments::None => Err(error(arguments, "missing generics for PhantomConstGet")), | ||||||
|  |             PathArguments::AngleBracketed(AngleBracketedGenericArguments { | ||||||
|  |                 colon2_token, | ||||||
|  |                 lt_token, | ||||||
|  |                 args, | ||||||
|  |                 gt_token, | ||||||
|  |             }) => { | ||||||
|  |                 let error = |args: Punctuated<GenericArgument, Token![,]>, message| { | ||||||
|  |                     error( | ||||||
|  |                         PathArguments::AngleBracketed(AngleBracketedGenericArguments { | ||||||
|  |                             colon2_token, | ||||||
|  |                             lt_token, | ||||||
|  |                             args, | ||||||
|  |                             gt_token, | ||||||
|  |                         }), | ||||||
|  |                         message, | ||||||
|  |                     ) | ||||||
|  |                 }; | ||||||
|  |                 let mut args = args.into_pairs().peekable(); | ||||||
|  |                 let Some((generic_argument, comma_token)) = args.next().map(Pair::into_tuple) | ||||||
|  |                 else { | ||||||
|  |                     return Err(error( | ||||||
|  |                         Default::default(), | ||||||
|  |                         "PhantomConstGet takes a type argument but no generic arguments were supplied", | ||||||
|  |                     )); | ||||||
|  |                 }; | ||||||
|  |                 if args.peek().is_some() { | ||||||
|  |                     return Err(error( | ||||||
|  |                         [Pair::new(generic_argument, comma_token)] | ||||||
|  |                             .into_iter() | ||||||
|  |                             .chain(args) | ||||||
|  |                             .collect(), | ||||||
|  |                         "PhantomConstGet takes a single type argument but too many generic arguments were supplied", | ||||||
|  |                     )); | ||||||
|  |                 }; | ||||||
|  |                 let GenericArgument::Type(ty) = generic_argument else { | ||||||
|  |                     return Err(error( | ||||||
|  |                         Punctuated::from_iter([Pair::new(generic_argument, comma_token)]), | ||||||
|  |                         "PhantomConstGet requires a type argument", | ||||||
|  |                     )); | ||||||
|  |                 }; | ||||||
|  |                 Ok(Self { | ||||||
|  |                     phantom_const_get, | ||||||
|  |                     colon2_token, | ||||||
|  |                     lt_token, | ||||||
|  |                     ty, | ||||||
|  |                     comma_token, | ||||||
|  |                     gt_token, | ||||||
|  |                 }) | ||||||
|  |             } | ||||||
|  |             PathArguments::Parenthesized(_) => Err(error( | ||||||
|  |                 arguments, | ||||||
|  |                 "parenthetical generics are not valid for PhantomConstGet", | ||||||
|  |             )), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     pub(crate) fn parse_type_param_bound( | ||||||
|  |         bound: TypeParamBound, | ||||||
|  |     ) -> syn::Result<Result<Self, TypeParamBound>> { | ||||||
|  |         let TypeParamBound::Trait(TraitBound { | ||||||
|  |             paren_token: None, | ||||||
|  |             modifier: syn::TraitBoundModifier::None, | ||||||
|  |             lifetimes: None, | ||||||
|  |             path, | ||||||
|  |         }) = bound | ||||||
|  |         else { | ||||||
|  |             return Ok(Err(bound)); | ||||||
|  |         }; | ||||||
|  |         Ok(match Self::parse_path_with_arguments(path)? { | ||||||
|  |             Ok(v) => Ok(v), | ||||||
|  |             Err(path) => Err(TypeParamBound::Trait(TraitBound { | ||||||
|  |                 paren_token: None, | ||||||
|  |                 modifier: syn::TraitBoundModifier::None, | ||||||
|  |                 lifetimes: None, | ||||||
|  |                 path, | ||||||
|  |             })), | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl ToTokens for PhantomConstGetBound { | ||||||
|  |     fn to_tokens(&self, tokens: &mut TokenStream) { | ||||||
|  |         let Self { | ||||||
|  |             phantom_const_get, | ||||||
|  |             colon2_token, | ||||||
|  |             lt_token, | ||||||
|  |             ty, | ||||||
|  |             comma_token, | ||||||
|  |             gt_token, | ||||||
|  |         } = self; | ||||||
|  |         phantom_const_get.to_tokens(tokens); | ||||||
|  |         colon2_token.to_tokens(tokens); | ||||||
|  |         lt_token.to_tokens(tokens); | ||||||
|  |         ty.to_tokens(tokens); | ||||||
|  |         comma_token.to_tokens(tokens); | ||||||
|  |         gt_token.to_tokens(tokens); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<PhantomConstGetBound> for Path { | ||||||
|  |     fn from(value: PhantomConstGetBound) -> Self { | ||||||
|  |         let PhantomConstGetBound { | ||||||
|  |             phantom_const_get, | ||||||
|  |             colon2_token, | ||||||
|  |             lt_token, | ||||||
|  |             ty, | ||||||
|  |             comma_token, | ||||||
|  |             gt_token, | ||||||
|  |         } = value; | ||||||
|  |         let mut path = phantom_const_get.path; | ||||||
|  |         path.segments.last_mut().expect("known to exist").arguments = | ||||||
|  |             PathArguments::AngleBracketed(AngleBracketedGenericArguments { | ||||||
|  |                 colon2_token, | ||||||
|  |                 lt_token, | ||||||
|  |                 args: FromIterator::from_iter([Pair::new(GenericArgument::Type(ty), comma_token)]), | ||||||
|  |                 gt_token, | ||||||
|  |             }); | ||||||
|  |         path | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<PhantomConstGetBound> for TraitBound { | ||||||
|  |     fn from(value: PhantomConstGetBound) -> Self { | ||||||
|  |         let path = Path::from(value); | ||||||
|  |         TraitBound { | ||||||
|  |             paren_token: None, | ||||||
|  |             modifier: syn::TraitBoundModifier::None, | ||||||
|  |             lifetimes: None, | ||||||
|  |             path, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<PhantomConstGetBound> for TypeParamBound { | ||||||
|  |     fn from(value: PhantomConstGetBound) -> Self { | ||||||
|  |         TraitBound::from(value).into() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| macro_rules! impl_bounds { | macro_rules! impl_bounds { | ||||||
|     ( |     ( | ||||||
|         #[struct = $struct_type:ident] |         #[struct = $struct_type:ident] | ||||||
|  | @ -2072,6 +2240,10 @@ macro_rules! impl_bounds { | ||||||
|             $( |             $( | ||||||
|                 $Variant:ident, |                 $Variant:ident, | ||||||
|             )* |             )* | ||||||
|  |             $( | ||||||
|  |                 #[has_body] | ||||||
|  |                 $VariantHasBody:ident($variant_has_body_ty:ty), | ||||||
|  |             )* | ||||||
|             $( |             $( | ||||||
|                 #[unknown] |                 #[unknown] | ||||||
|                 $Unknown:ident, |                 $Unknown:ident, | ||||||
|  | @ -2081,6 +2253,7 @@ macro_rules! impl_bounds { | ||||||
|         #[derive(Clone, Debug)] |         #[derive(Clone, Debug)] | ||||||
|         $vis enum $enum_type { |         $vis enum $enum_type { | ||||||
|             $($Variant(known_items::$Variant),)* |             $($Variant(known_items::$Variant),)* | ||||||
|  |             $($VariantHasBody($variant_has_body_ty),)* | ||||||
|             $($Unknown(syn::TypeParamBound),)? |             $($Unknown(syn::TypeParamBound),)? | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -2090,31 +2263,42 @@ macro_rules! impl_bounds { | ||||||
|             } |             } | ||||||
|         })* |         })* | ||||||
| 
 | 
 | ||||||
|  |         $(impl From<$variant_has_body_ty> for $enum_type { | ||||||
|  |             fn from(v: $variant_has_body_ty) -> Self { | ||||||
|  |                 Self::$VariantHasBody(v) | ||||||
|  |             } | ||||||
|  |         })* | ||||||
|  | 
 | ||||||
|         impl ToTokens for $enum_type { |         impl ToTokens for $enum_type { | ||||||
|             fn to_tokens(&self, tokens: &mut TokenStream) { |             fn to_tokens(&self, tokens: &mut TokenStream) { | ||||||
|                 match self { |                 match self { | ||||||
|                     $(Self::$Variant(v) => v.to_tokens(tokens),)* |                     $(Self::$Variant(v) => v.to_tokens(tokens),)* | ||||||
|  |                     $(Self::$VariantHasBody(v) => v.to_tokens(tokens),)* | ||||||
|                     $(Self::$Unknown(v) => v.to_tokens(tokens),)? |                     $(Self::$Unknown(v) => v.to_tokens(tokens),)? | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         impl $enum_type { |         impl $enum_type { | ||||||
|             $vis fn parse_path(path: Path) -> Result<Self, Path> { |             $vis fn parse_path_with_arguments(path: Path) -> syn::Result<Result<Self, Path>> { | ||||||
|                 #![allow(unreachable_code)] |                 #![allow(unreachable_code)] | ||||||
|                 $(let path = match known_items::$Variant::parse_path(path) { |                 $(let path = match known_items::$Variant::parse_path(path) { | ||||||
|                     Ok(v) => return Ok(Self::$Variant(v)), |                     Ok(v) => return Ok(Ok(Self::$Variant(v))), | ||||||
|                     Err(path) => path, |                     Err(path) => path, | ||||||
|                 };)* |                 };)* | ||||||
|                 $(return Ok(Self::$Unknown(syn::TraitBound { |                 $(let path = match <$variant_has_body_ty>::parse_path_with_arguments(path)? { | ||||||
|  |                     Ok(v) => return Ok(Ok(Self::$VariantHasBody(v))), | ||||||
|  |                     Err(path) => path, | ||||||
|  |                 };)* | ||||||
|  |                 $(return Ok(Ok(Self::$Unknown(syn::TraitBound { | ||||||
|                     paren_token: None, |                     paren_token: None, | ||||||
|                     modifier: syn::TraitBoundModifier::None, |                     modifier: syn::TraitBoundModifier::None, | ||||||
|                     lifetimes: None, |                     lifetimes: None, | ||||||
|                     path, |                     path, | ||||||
|                 }.into()));)? |                 }.into())));)? | ||||||
|                 Err(path) |                 Ok(Err(path)) | ||||||
|             } |             } | ||||||
|             $vis fn parse_type_param_bound(mut type_param_bound: syn::TypeParamBound) -> Result<Self, syn::TypeParamBound> { |             $vis fn parse_type_param_bound(mut type_param_bound: syn::TypeParamBound) -> syn::Result<Result<Self, syn::TypeParamBound>> { | ||||||
|                 #![allow(unreachable_code)] |                 #![allow(unreachable_code)] | ||||||
|                 if let syn::TypeParamBound::Trait(mut trait_bound) = type_param_bound { |                 if let syn::TypeParamBound::Trait(mut trait_bound) = type_param_bound { | ||||||
|                     if let syn::TraitBound { |                     if let syn::TraitBound { | ||||||
|  | @ -2123,24 +2307,24 @@ macro_rules! impl_bounds { | ||||||
|                         lifetimes: None, |                         lifetimes: None, | ||||||
|                         path: _, |                         path: _, | ||||||
|                     } = trait_bound { |                     } = trait_bound { | ||||||
|                         match Self::parse_path(trait_bound.path) { |                         match Self::parse_path_with_arguments(trait_bound.path)? { | ||||||
|                             Ok(retval) => return Ok(retval), |                             Ok(retval) => return Ok(Ok(retval)), | ||||||
|                             Err(path) => trait_bound.path = path, |                             Err(path) => trait_bound.path = path, | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     type_param_bound = trait_bound.into(); |                     type_param_bound = trait_bound.into(); | ||||||
|                 } |                 } | ||||||
|                 $(return Ok(Self::$Unknown(type_param_bound));)? |                 $(return Ok(Ok(Self::$Unknown(type_param_bound)));)? | ||||||
|                 Err(type_param_bound) |                 Ok(Err(type_param_bound)) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         impl Parse for $enum_type { |         impl Parse for $enum_type { | ||||||
|             fn parse(input: ParseStream) -> syn::Result<Self> { |             fn parse(input: ParseStream) -> syn::Result<Self> { | ||||||
|                 Self::parse_type_param_bound(input.parse()?) |                 Self::parse_type_param_bound(input.parse()?)? | ||||||
|                     .map_err(|type_param_bound| syn::Error::new_spanned( |                     .map_err(|type_param_bound| syn::Error::new_spanned( | ||||||
|                         type_param_bound, |                         type_param_bound, | ||||||
|                         format_args!("expected one of: {}", [$(stringify!($Variant)),*].join(", ")), |                         format_args!("expected one of: {}", [$(stringify!($Variant),)* $(stringify!($VariantHasBody)),*].join(", ")), | ||||||
|                     )) |                     )) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -2149,6 +2333,7 @@ macro_rules! impl_bounds { | ||||||
|         #[allow(non_snake_case)] |         #[allow(non_snake_case)] | ||||||
|         $vis struct $struct_type { |         $vis struct $struct_type { | ||||||
|             $($vis $Variant: Option<known_items::$Variant>,)* |             $($vis $Variant: Option<known_items::$Variant>,)* | ||||||
|  |             $($vis $VariantHasBody: Option<$variant_has_body_ty>,)* | ||||||
|             $($vis $Unknown: Vec<syn::TypeParamBound>,)? |             $($vis $Unknown: Vec<syn::TypeParamBound>,)? | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -2161,6 +2346,11 @@ macro_rules! impl_bounds { | ||||||
|                     separator = Some(<Token![+]>::default()); |                     separator = Some(<Token![+]>::default()); | ||||||
|                     v.to_tokens(tokens); |                     v.to_tokens(tokens); | ||||||
|                 })* |                 })* | ||||||
|  |                 $(if let Some(v) = &self.$VariantHasBody { | ||||||
|  |                     separator.to_tokens(tokens); | ||||||
|  |                     separator = Some(<Token![+]>::default()); | ||||||
|  |                     v.to_tokens(tokens); | ||||||
|  |                 })* | ||||||
|                 $(for v in &self.$Unknown { |                 $(for v in &self.$Unknown { | ||||||
|                     separator.to_tokens(tokens); |                     separator.to_tokens(tokens); | ||||||
|                     separator = Some(<Token![+]>::default()); |                     separator = Some(<Token![+]>::default()); | ||||||
|  | @ -2174,6 +2364,7 @@ macro_rules! impl_bounds { | ||||||
|             #[allow(non_snake_case)] |             #[allow(non_snake_case)] | ||||||
|             $vis struct Iter { |             $vis struct Iter { | ||||||
|                 $($Variant: Option<known_items::$Variant>,)* |                 $($Variant: Option<known_items::$Variant>,)* | ||||||
|  |                 $($VariantHasBody: Option<$variant_has_body_ty>,)* | ||||||
|                 $($Unknown: std::vec::IntoIter<syn::TypeParamBound>,)? |                 $($Unknown: std::vec::IntoIter<syn::TypeParamBound>,)? | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -2184,6 +2375,7 @@ macro_rules! impl_bounds { | ||||||
|                 fn into_iter(self) -> Self::IntoIter { |                 fn into_iter(self) -> Self::IntoIter { | ||||||
|                     Iter { |                     Iter { | ||||||
|                         $($Variant: self.$Variant,)* |                         $($Variant: self.$Variant,)* | ||||||
|  |                         $($VariantHasBody: self.$VariantHasBody,)* | ||||||
|                         $($Unknown: self.$Unknown.into_iter(),)? |                         $($Unknown: self.$Unknown.into_iter(),)? | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  | @ -2198,6 +2390,11 @@ macro_rules! impl_bounds { | ||||||
|                             return Some($enum_type::$Variant(value)); |                             return Some($enum_type::$Variant(value)); | ||||||
|                         } |                         } | ||||||
|                     )* |                     )* | ||||||
|  |                     $( | ||||||
|  |                         if let Some(value) = self.$VariantHasBody.take() { | ||||||
|  |                             return Some($enum_type::$VariantHasBody(value)); | ||||||
|  |                         } | ||||||
|  |                     )* | ||||||
|                     $( |                     $( | ||||||
|                         if let Some(value) = self.$Unknown.next() { |                         if let Some(value) = self.$Unknown.next() { | ||||||
|                             return Some($enum_type::$Unknown(value)); |                             return Some($enum_type::$Unknown(value)); | ||||||
|  | @ -2213,6 +2410,11 @@ macro_rules! impl_bounds { | ||||||
|                             init = f(init, $enum_type::$Variant(value)); |                             init = f(init, $enum_type::$Variant(value)); | ||||||
|                         } |                         } | ||||||
|                     )* |                     )* | ||||||
|  |                     $( | ||||||
|  |                         if let Some(value) = self.$VariantHasBody.take() { | ||||||
|  |                             init = f(init, $enum_type::$VariantHasBody(value)); | ||||||
|  |                         } | ||||||
|  |                     )* | ||||||
|                     $( |                     $( | ||||||
|                         if let Some(value) = self.$Unknown.next() { |                         if let Some(value) = self.$Unknown.next() { | ||||||
|                             init = f(init, $enum_type::$Unknown(value)); |                             init = f(init, $enum_type::$Unknown(value)); | ||||||
|  | @ -2229,6 +2431,9 @@ macro_rules! impl_bounds { | ||||||
|                     $($enum_type::$Variant(v) => { |                     $($enum_type::$Variant(v) => { | ||||||
|                         self.$Variant = Some(v); |                         self.$Variant = Some(v); | ||||||
|                     })* |                     })* | ||||||
|  |                     $($enum_type::$VariantHasBody(v) => { | ||||||
|  |                         self.$VariantHasBody = Some(v); | ||||||
|  |                     })* | ||||||
|                     $($enum_type::$Unknown(v) => { |                     $($enum_type::$Unknown(v) => { | ||||||
|                         self.$Unknown.push(v); |                         self.$Unknown.push(v); | ||||||
|                     })? |                     })? | ||||||
|  | @ -2250,6 +2455,9 @@ macro_rules! impl_bounds { | ||||||
|                     $(if let Some(v) = v.$Variant { |                     $(if let Some(v) = v.$Variant { | ||||||
|                         self.$Variant = Some(v); |                         self.$Variant = Some(v); | ||||||
|                     })* |                     })* | ||||||
|  |                     $(if let Some(v) = v.$VariantHasBody { | ||||||
|  |                         self.$VariantHasBody = Some(v); | ||||||
|  |                     })* | ||||||
|                     $(self.$Unknown.extend(v.$Unknown);)* |                     $(self.$Unknown.extend(v.$Unknown);)* | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|  | @ -2304,6 +2512,8 @@ impl_bounds! { | ||||||
|         Size, |         Size, | ||||||
|         StaticType, |         StaticType, | ||||||
|         Type, |         Type, | ||||||
|  |         #[has_body] | ||||||
|  |         PhantomConstGet(PhantomConstGetBound), | ||||||
|         #[unknown] |         #[unknown] | ||||||
|         Unknown, |         Unknown, | ||||||
|     } |     } | ||||||
|  | @ -2319,6 +2529,8 @@ impl_bounds! { | ||||||
|         ResetType, |         ResetType, | ||||||
|         StaticType, |         StaticType, | ||||||
|         Type, |         Type, | ||||||
|  |         #[has_body] | ||||||
|  |         PhantomConstGet(PhantomConstGetBound), | ||||||
|         #[unknown] |         #[unknown] | ||||||
|         Unknown, |         Unknown, | ||||||
|     } |     } | ||||||
|  | @ -2334,6 +2546,7 @@ impl From<ParsedTypeBound> for ParsedBound { | ||||||
|             ParsedTypeBound::ResetType(v) => ParsedBound::ResetType(v), |             ParsedTypeBound::ResetType(v) => ParsedBound::ResetType(v), | ||||||
|             ParsedTypeBound::StaticType(v) => ParsedBound::StaticType(v), |             ParsedTypeBound::StaticType(v) => ParsedBound::StaticType(v), | ||||||
|             ParsedTypeBound::Type(v) => ParsedBound::Type(v), |             ParsedTypeBound::Type(v) => ParsedBound::Type(v), | ||||||
|  |             ParsedTypeBound::PhantomConstGet(v) => ParsedBound::PhantomConstGet(v), | ||||||
|             ParsedTypeBound::Unknown(v) => ParsedBound::Unknown(v), |             ParsedTypeBound::Unknown(v) => ParsedBound::Unknown(v), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -2349,6 +2562,7 @@ impl From<ParsedTypeBounds> for ParsedBounds { | ||||||
|             ResetType, |             ResetType, | ||||||
|             StaticType, |             StaticType, | ||||||
|             Type, |             Type, | ||||||
|  |             PhantomConstGet, | ||||||
|             Unknown, |             Unknown, | ||||||
|         } = value; |         } = value; | ||||||
|         Self { |         Self { | ||||||
|  | @ -2361,6 +2575,7 @@ impl From<ParsedTypeBounds> for ParsedBounds { | ||||||
|             Size: None, |             Size: None, | ||||||
|             StaticType, |             StaticType, | ||||||
|             Type, |             Type, | ||||||
|  |             PhantomConstGet, | ||||||
|             Unknown, |             Unknown, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -2397,6 +2612,10 @@ impl ParsedTypeBound { | ||||||
|                 ParsedTypeBound::Type(known_items::Type(span)), |                 ParsedTypeBound::Type(known_items::Type(span)), | ||||||
|             ]), |             ]), | ||||||
|             Self::Type(v) => ParsedTypeBounds::from_iter([ParsedTypeBound::from(v)]), |             Self::Type(v) => ParsedTypeBounds::from_iter([ParsedTypeBound::from(v)]), | ||||||
|  |             Self::PhantomConstGet(v) => ParsedTypeBounds::from_iter([ | ||||||
|  |                 ParsedTypeBound::from(v), | ||||||
|  |                 ParsedTypeBound::Type(known_items::Type(span)), | ||||||
|  |             ]), | ||||||
|             Self::Unknown(v) => ParsedTypeBounds::from_iter([ParsedTypeBound::Unknown(v)]), |             Self::Unknown(v) => ParsedTypeBounds::from_iter([ParsedTypeBound::Unknown(v)]), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -2432,6 +2651,7 @@ impl From<ParsedSizeTypeBounds> for ParsedBounds { | ||||||
|             Size, |             Size, | ||||||
|             StaticType: None, |             StaticType: None, | ||||||
|             Type: None, |             Type: None, | ||||||
|  |             PhantomConstGet: None, | ||||||
|             Unknown: vec![], |             Unknown: vec![], | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -2534,6 +2754,9 @@ impl ParsedBound { | ||||||
|             Self::Size(v) => ParsedBoundCategory::SizeType(ParsedSizeTypeBound::Size(v)), |             Self::Size(v) => ParsedBoundCategory::SizeType(ParsedSizeTypeBound::Size(v)), | ||||||
|             Self::StaticType(v) => ParsedBoundCategory::Type(ParsedTypeBound::StaticType(v)), |             Self::StaticType(v) => ParsedBoundCategory::Type(ParsedTypeBound::StaticType(v)), | ||||||
|             Self::Type(v) => ParsedBoundCategory::Type(ParsedTypeBound::Type(v)), |             Self::Type(v) => ParsedBoundCategory::Type(ParsedTypeBound::Type(v)), | ||||||
|  |             Self::PhantomConstGet(v) => { | ||||||
|  |                 ParsedBoundCategory::Type(ParsedTypeBound::PhantomConstGet(v)) | ||||||
|  |             } | ||||||
|             Self::Unknown(v) => ParsedBoundCategory::Unknown(v), |             Self::Unknown(v) => ParsedBoundCategory::Unknown(v), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -3419,7 +3642,8 @@ impl ParsedGenerics { | ||||||
|                                 | ParsedTypeBound::BundleType(_) |                                 | ParsedTypeBound::BundleType(_) | ||||||
|                                 | ParsedTypeBound::EnumType(_) |                                 | ParsedTypeBound::EnumType(_) | ||||||
|                                 | ParsedTypeBound::IntType(_) |                                 | ParsedTypeBound::IntType(_) | ||||||
|                                 | ParsedTypeBound::ResetType(_) => { |                                 | ParsedTypeBound::ResetType(_) | ||||||
|  |                                 | ParsedTypeBound::PhantomConstGet(_) => { | ||||||
|                                     errors.error(bound, "bounds on mask types are not implemented"); |                                     errors.error(bound, "bounds on mask types are not implemented"); | ||||||
|                                 } |                                 } | ||||||
|                                 ParsedTypeBound::StaticType(bound) => { |                                 ParsedTypeBound::StaticType(bound) => { | ||||||
|  |  | ||||||
|  | @ -166,7 +166,7 @@ pub use fayalite_proc_macros::hdl_module; | ||||||
| /// // you can then use it in other types:
 | /// // you can then use it in other types:
 | ||||||
| ///
 | ///
 | ||||||
| /// #[hdl(no_static)]
 | /// #[hdl(no_static)]
 | ||||||
| /// pub struct WrapMyArray<P: Type + PhantomConstGet<Config>> {
 | /// pub struct WrapMyArray<P: PhantomConstGet<Config>> {
 | ||||||
| ///     pub my_array: GetMyArray<P>,
 | ///     pub my_array: GetMyArray<P>,
 | ||||||
| /// }
 | /// }
 | ||||||
| ///
 | ///
 | ||||||
|  | @ -202,7 +202,7 @@ pub use fayalite_proc_macros::hdl_module; | ||||||
| /// // you can then use it in other types:
 | /// // you can then use it in other types:
 | ||||||
| ///
 | ///
 | ||||||
| /// #[hdl(no_static)]
 | /// #[hdl(no_static)]
 | ||||||
| /// pub struct FlagPerItem<P: Type + PhantomConstGet<Config>> {
 | /// pub struct FlagPerItem<P: PhantomConstGet<Config>> {
 | ||||||
| ///     pub flags: ArrayType<Bool, GetItemsLen<P>>,
 | ///     pub flags: ArrayType<Bool, GetItemsLen<P>>,
 | ||||||
| /// }
 | /// }
 | ||||||
| ///
 | ///
 | ||||||
|  |  | ||||||
|  | @ -210,7 +210,7 @@ pub type GetA<P: PhantomConstGet<MyPhantomConstInner>> = DynSize; | ||||||
| pub type GetB<P: PhantomConstGet<MyPhantomConstInner>> = UInt; | pub type GetB<P: PhantomConstGet<MyPhantomConstInner>> = UInt; | ||||||
| 
 | 
 | ||||||
| #[hdl(outline_generated, no_static)] | #[hdl(outline_generated, no_static)] | ||||||
| pub struct MyTypeWithPhantomConstParameter<P: Type + PhantomConstGet<MyPhantomConstInner>> { | pub struct MyTypeWithPhantomConstParameter<P: PhantomConstGet<MyPhantomConstInner>> { | ||||||
|     pub a: ArrayType<Bool, GetA<P>>, |     pub a: ArrayType<Bool, GetA<P>>, | ||||||
|     pub b: HdlOption<GetB<P>>, |     pub b: HdlOption<GetB<P>>, | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue