forked from libre-chip/fayalite
		
	fix handling of const and size type generics when generating Index impls
This commit is contained in:
		
							parent
							
								
									2c1afd1cd6
								
							
						
					
					
						commit
						9887d70f41
					
				
					 5 changed files with 519 additions and 212 deletions
				
			
		|  | @ -230,6 +230,7 @@ forward_fold!(syn::Path => fold_path); | |||
| forward_fold!(syn::Type => fold_type); | ||||
| forward_fold!(syn::TypePath => fold_type_path); | ||||
| forward_fold!(syn::WherePredicate => fold_where_predicate); | ||||
| no_op_fold!(proc_macro2::Span); | ||||
| no_op_fold!(syn::parse::Nothing); | ||||
| no_op_fold!(syn::token::Brace); | ||||
| no_op_fold!(syn::token::Bracket); | ||||
|  |  | |||
|  | @ -8,11 +8,12 @@ use syn::{ | |||
|     punctuated::{Pair, Punctuated}, | ||||
|     spanned::Spanned, | ||||
|     token::{Brace, Bracket, Paren}, | ||||
|     AngleBracketedGenericArguments, Attribute, ConstParam, Expr, ExprIndex, ExprPath, ExprTuple, | ||||
|     Field, FieldMutability, Fields, FieldsNamed, FieldsUnnamed, GenericArgument, GenericParam, | ||||
|     Generics, Ident, ImplGenerics, Index, ItemStruct, Path, PathArguments, PathSegment, | ||||
|     PredicateType, QSelf, Token, Turbofish, Type, TypeGenerics, TypeGroup, TypeParam, TypeParen, | ||||
|     TypePath, TypeTuple, Visibility, WhereClause, WherePredicate, | ||||
|     AngleBracketedGenericArguments, Attribute, Block, ConstParam, Expr, ExprBlock, ExprGroup, | ||||
|     ExprIndex, ExprParen, ExprPath, ExprTuple, Field, FieldMutability, Fields, FieldsNamed, | ||||
|     FieldsUnnamed, GenericArgument, GenericParam, Generics, Ident, ImplGenerics, Index, ItemStruct, | ||||
|     Path, PathArguments, PathSegment, PredicateType, QSelf, Stmt, Token, Turbofish, Type, | ||||
|     TypeGenerics, TypeGroup, TypeParam, TypeParen, TypePath, TypeTuple, Visibility, WhereClause, | ||||
|     WherePredicate, | ||||
| }; | ||||
| 
 | ||||
| crate::options! { | ||||
|  | @ -113,6 +114,230 @@ macro_rules! parse_failed { | |||
|     }}; | ||||
| } | ||||
| 
 | ||||
| #[derive(Copy, Clone, Debug)] | ||||
| pub(crate) enum ExprDelimiter { | ||||
|     Group(syn::token::Group), | ||||
|     Brace(Brace), | ||||
|     Paren(Paren), | ||||
| } | ||||
| 
 | ||||
| impl_fold! { | ||||
|     enum ExprDelimiter<> { | ||||
|         Group(syn::token::Group), | ||||
|         Brace(Brace), | ||||
|         Paren(Paren), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl ExprDelimiter { | ||||
|     pub(crate) fn surround<F: FnOnce(&mut TokenStream)>(self, tokens: &mut TokenStream, f: F) { | ||||
|         match self { | ||||
|             ExprDelimiter::Group(v) => v.surround(tokens, f), | ||||
|             ExprDelimiter::Brace(v) => v.surround(tokens, f), | ||||
|             ExprDelimiter::Paren(v) => v.surround(tokens, f), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub(crate) struct ParsedExprDelimited { | ||||
|     pub(crate) delim: ExprDelimiter, | ||||
|     pub(crate) expr: Box<ParsedExpr>, | ||||
| } | ||||
| 
 | ||||
| impl_fold! { | ||||
|     struct ParsedExprDelimited<> { | ||||
|         delim: ExprDelimiter, | ||||
|         expr: Box<ParsedExpr>, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<ParsedExprDelimited> for Expr { | ||||
|     fn from(value: ParsedExprDelimited) -> Self { | ||||
|         let ParsedExprDelimited { delim, expr } = value; | ||||
|         let expr = expr.into(); | ||||
|         match delim { | ||||
|             ExprDelimiter::Group(group_token) => Expr::Group(ExprGroup { | ||||
|                 attrs: vec![], | ||||
|                 group_token, | ||||
|                 expr: Box::new(expr), | ||||
|             }), | ||||
|             ExprDelimiter::Brace(brace_token) => Expr::Block(ExprBlock { | ||||
|                 attrs: vec![], | ||||
|                 label: None, | ||||
|                 block: Block { | ||||
|                     brace_token, | ||||
|                     stmts: vec![Stmt::Expr(expr, None)], | ||||
|                 }, | ||||
|             }), | ||||
|             ExprDelimiter::Paren(paren_token) => Expr::Paren(ExprParen { | ||||
|                 attrs: vec![], | ||||
|                 paren_token, | ||||
|                 expr: Box::new(expr), | ||||
|             }), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl ToTokens for ParsedExprDelimited { | ||||
|     fn to_tokens(&self, tokens: &mut TokenStream) { | ||||
|         let Self { delim, expr } = self; | ||||
|         delim.surround(tokens, |tokens| expr.to_tokens(tokens)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub(crate) struct ParsedExprNamedParamConst { | ||||
|     pub(crate) ident: Ident, | ||||
|     pub(crate) param_index: usize, | ||||
| } | ||||
| 
 | ||||
| impl_fold! { | ||||
|     struct ParsedExprNamedParamConst<> { | ||||
|         ident: Ident, | ||||
|         param_index: usize, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl ToTokens for ParsedExprNamedParamConst { | ||||
|     fn to_tokens(&self, tokens: &mut TokenStream) { | ||||
|         let Self { | ||||
|             ident, | ||||
|             param_index: _, | ||||
|         } = self; | ||||
|         ident.to_tokens(tokens); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<ParsedExprNamedParamConst> for Expr { | ||||
|     fn from(value: ParsedExprNamedParamConst) -> Self { | ||||
|         Expr::Path(ExprPath { | ||||
|             attrs: vec![], | ||||
|             qself: None, | ||||
|             path: value.ident.into(), | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub(crate) enum ParsedExpr { | ||||
|     Delimited(ParsedExprDelimited), | ||||
|     NamedParamConst(ParsedExprNamedParamConst), | ||||
|     Other(Box<Expr>), | ||||
| } | ||||
| 
 | ||||
| impl ParsedExpr { | ||||
|     pub(crate) fn named_param_const(mut self: &Self) -> Option<&ParsedExprNamedParamConst> { | ||||
|         loop { | ||||
|             match self { | ||||
|                 ParsedExpr::Delimited(ParsedExprDelimited { expr, .. }) => self = &**expr, | ||||
|                 ParsedExpr::NamedParamConst(retval) => return Some(retval), | ||||
|                 ParsedExpr::Other(_) => return None, | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl_fold! { | ||||
|     enum ParsedExpr<> { | ||||
|         Delimited(ParsedExprDelimited), | ||||
|         NamedParamConst(ParsedExprNamedParamConst), | ||||
|         Other(Box<Expr>), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl ToTokens for ParsedExpr { | ||||
|     fn to_tokens(&self, tokens: &mut TokenStream) { | ||||
|         match self { | ||||
|             ParsedExpr::Delimited(v) => v.to_tokens(tokens), | ||||
|             ParsedExpr::NamedParamConst(v) => v.to_tokens(tokens), | ||||
|             ParsedExpr::Other(v) => v.to_tokens(tokens), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<ParsedExpr> for Expr { | ||||
|     fn from(value: ParsedExpr) -> Self { | ||||
|         match value { | ||||
|             ParsedExpr::Delimited(expr) => expr.into(), | ||||
|             ParsedExpr::NamedParamConst(expr) => expr.into(), | ||||
|             ParsedExpr::Other(expr) => *expr, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<Box<ParsedExpr>> for Expr { | ||||
|     fn from(value: Box<ParsedExpr>) -> Self { | ||||
|         (*value).into() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl ParseTypes<Expr> for ParsedExpr { | ||||
|     fn parse_types(input: &mut Expr, parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> { | ||||
|         match input { | ||||
|             Expr::Block(ExprBlock { | ||||
|                 attrs, | ||||
|                 label: None, | ||||
|                 block: Block { brace_token, stmts }, | ||||
|             }) if attrs.is_empty() && stmts.len() == 1 => { | ||||
|                 if let Stmt::Expr(expr, None) = &mut stmts[0] { | ||||
|                     return Ok(ParsedExpr::Delimited(ParsedExprDelimited { | ||||
|                         delim: ExprDelimiter::Brace(*brace_token), | ||||
|                         expr: Box::new(parser.parse(expr)?), | ||||
|                     })); | ||||
|                 } | ||||
|             } | ||||
|             Expr::Group(ExprGroup { | ||||
|                 attrs, | ||||
|                 group_token, | ||||
|                 expr, | ||||
|             }) if attrs.is_empty() => { | ||||
|                 return Ok(ParsedExpr::Delimited(ParsedExprDelimited { | ||||
|                     delim: ExprDelimiter::Group(*group_token), | ||||
|                     expr: parser.parse(expr)?, | ||||
|                 })) | ||||
|             } | ||||
|             Expr::Paren(ExprParen { | ||||
|                 attrs, | ||||
|                 paren_token, | ||||
|                 expr, | ||||
|             }) if attrs.is_empty() => { | ||||
|                 return Ok(ParsedExpr::Delimited(ParsedExprDelimited { | ||||
|                     delim: ExprDelimiter::Paren(*paren_token), | ||||
|                     expr: parser.parse(expr)?, | ||||
|                 })) | ||||
|             } | ||||
|             Expr::Path(ExprPath { | ||||
|                 attrs, | ||||
|                 qself: None, | ||||
|                 path, | ||||
|             }) if attrs.is_empty() => { | ||||
|                 if let Some((param_index, ident)) = parser.get_named_param(path) { | ||||
|                     return Ok(Self::NamedParamConst( | ||||
|                         match parser.generics().params[param_index] { | ||||
|                             ParsedGenericParam::Const(_) => ParsedExprNamedParamConst { | ||||
|                                 ident: ident.clone(), | ||||
|                                 param_index, | ||||
|                             }, | ||||
|                             ParsedGenericParam::Type(ParsedTypeParam { ref ident, .. }) | ||||
|                             | ParsedGenericParam::SizeType(ParsedSizeTypeParam { | ||||
|                                 ref ident, .. | ||||
|                             }) => { | ||||
|                                 parser | ||||
|                                     .errors | ||||
|                                     .error(ident, "type provided when a constant was expected"); | ||||
|                                 return Err(ParseFailed); | ||||
|                             } | ||||
|                         }, | ||||
|                     )); | ||||
|                 } | ||||
|             } | ||||
|             _ => {} | ||||
|         } | ||||
|         Ok(ParsedExpr::Other(Box::new(input.clone()))) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Copy, Clone, Debug)] | ||||
| pub(crate) enum TypeDelimiter { | ||||
|     Group(syn::token::Group), | ||||
|  | @ -214,13 +439,13 @@ impl ParseTypes<TypeTuple> for ParsedTypeTuple { | |||
| #[derive(Debug, Clone)] | ||||
| pub(crate) enum ParsedGenericArgument { | ||||
|     Type(ParsedType), | ||||
|     Const(Expr), | ||||
|     Const(ParsedExpr), | ||||
| } | ||||
| 
 | ||||
| impl_fold! { | ||||
|     enum ParsedGenericArgument<> { | ||||
|         Type(ParsedType), | ||||
|         Const(Expr), | ||||
|         Const(ParsedExpr), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -246,20 +471,16 @@ impl ParseTypes<GenericArgument> for ParsedGenericArgument { | |||
|                         ty = &**elem; | ||||
|                     } | ||||
|                     if let Type::Path(TypePath { qself: None, path }) = ty { | ||||
|                         if let Some(ident) = path.get_ident() { | ||||
|                             if let Some(¶m_index) = | ||||
|                                 parser.generics.param_name_to_index_map.get(ident) | ||||
|                             { | ||||
|                                 match parser.generics.params[param_index] { | ||||
|                                     ParsedGenericParam::Type(_) | ||||
|                                     | ParsedGenericParam::SizeType(_) => {} | ||||
|                                     ParsedGenericParam::Const(_) => { | ||||
|                                         return Ok(Self::Const(Expr::Path(ExprPath { | ||||
|                                             attrs: vec![], | ||||
|                                             qself: None, | ||||
|                                             path: path.clone(), | ||||
|                                         }))); | ||||
|                                     } | ||||
|                         if let Some((param_index, ident)) = parser.get_named_param(path) { | ||||
|                             match parser.generics.params[param_index] { | ||||
|                                 ParsedGenericParam::Type(_) | ParsedGenericParam::SizeType(_) => {} | ||||
|                                 ParsedGenericParam::Const(_) => { | ||||
|                                     return Ok(Self::Const(ParsedExpr::NamedParamConst( | ||||
|                                         ParsedExprNamedParamConst { | ||||
|                                             ident: ident.clone(), | ||||
|                                             param_index, | ||||
|                                         }, | ||||
|                                     ))); | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|  | @ -267,7 +488,7 @@ impl ParseTypes<GenericArgument> for ParsedGenericArgument { | |||
|                 } | ||||
|                 Ok(Self::Type(parser.parse(ty)?)) | ||||
|             } | ||||
|             GenericArgument::Const(expr) => Ok(Self::Const(expr.clone())), | ||||
|             GenericArgument::Const(expr) => Ok(Self::Const(parser.parse(expr)?)), | ||||
|             _ => parse_failed!(parser, arg, "expected type or const generic argument"), | ||||
|         } | ||||
|     } | ||||
|  | @ -277,7 +498,7 @@ impl From<ParsedGenericArgument> for GenericArgument { | |||
|     fn from(value: ParsedGenericArgument) -> Self { | ||||
|         match value { | ||||
|             ParsedGenericArgument::Type(ty) => Self::Type(ty.into()), | ||||
|             ParsedGenericArgument::Const(expr) => Self::Const(expr), | ||||
|             ParsedGenericArgument::Const(expr) => Self::Const(expr.into()), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -496,7 +717,7 @@ impl ToTokens for ParsedTypeNamedParam { | |||
| pub(crate) struct ParsedTypeConstUsize { | ||||
|     pub(crate) const_usize: known_items::ConstUsize, | ||||
|     pub(crate) lt_token: Token![<], | ||||
|     pub(crate) value: Box<Expr>, | ||||
|     pub(crate) value: ParsedExpr, | ||||
|     pub(crate) gt_token: Token![>], | ||||
| } | ||||
| 
 | ||||
|  | @ -504,7 +725,7 @@ impl_fold! { | |||
|     struct ParsedTypeConstUsize<> { | ||||
|         const_usize: known_items::ConstUsize, | ||||
|         lt_token: Token![<], | ||||
|         value: Box<Expr>, | ||||
|         value: ParsedExpr, | ||||
|         gt_token: Token![>], | ||||
|     } | ||||
| } | ||||
|  | @ -518,7 +739,7 @@ impl From<ParsedTypeConstUsize> for Path { | |||
|             gt_token, | ||||
|         } = value; | ||||
|         let path = const_usize.path; | ||||
|         let args = Punctuated::from_iter([GenericArgument::Const(*value)]); | ||||
|         let args = Punctuated::from_iter([GenericArgument::Const(value.into())]); | ||||
|         let args = AngleBracketedGenericArguments { | ||||
|             colon2_token: Some(Token), | ||||
|             lt_token, | ||||
|  | @ -544,12 +765,16 @@ impl From<ParsedTypeConstUsize> for Type { | |||
| } | ||||
| 
 | ||||
| impl MakeHdlTypeExpr for ParsedTypeConstUsize { | ||||
|     fn make_hdl_type_expr(&self, _context: &MakeHdlTypeExprContext) -> Expr { | ||||
|         Expr::Path(ExprPath { | ||||
|             attrs: vec![], | ||||
|             qself: None, | ||||
|             path: self.clone().into(), | ||||
|         }) | ||||
|     fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr { | ||||
|         if let Some(named_param_const) = self.value.named_param_const() { | ||||
|             named_param_const.make_hdl_type_expr(context) | ||||
|         } else { | ||||
|             Expr::Path(ExprPath { | ||||
|                 attrs: vec![], | ||||
|                 qself: None, | ||||
|                 path: self.clone().into(), | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -606,7 +831,7 @@ impl ParsedTypeConstUsize { | |||
|         Ok(Ok(Self { | ||||
|             const_usize, | ||||
|             lt_token, | ||||
|             value: Box::new(value), | ||||
|             value, | ||||
|             gt_token, | ||||
|         })) | ||||
|     } | ||||
|  | @ -694,7 +919,7 @@ macro_rules! make_parsed_type_or_const { | |||
|                 let $type_arg = Box::new(ParsedType::ConstUsize(ParsedTypeConstUsize { | ||||
|                     const_usize: known_items::ConstUsize($span), | ||||
|                     lt_token: Token, | ||||
|                     value: Box::new($const_arg.clone()), | ||||
|                     value: $const_arg.clone(), | ||||
|                     gt_token: Token, | ||||
|                 })); | ||||
|                 ($type_arg, Some(Box::new($const_arg))) | ||||
|  | @ -887,7 +1112,7 @@ macro_rules! make_parsed_type_or_const { | |||
|                     let mut args = Punctuated::new(); | ||||
|                     $( | ||||
|                         args.push(( | ||||
|                             ($(|| GenericArgument::Const(*$const_arg),)? | ||||
|                             ($(|| GenericArgument::Const($const_arg.into()),)? | ||||
|                             || GenericArgument::Type($type_arg.into()), | ||||
|                         ).0)()); | ||||
|                         $(args.push_punct($separator);)? | ||||
|  | @ -1010,7 +1235,7 @@ make_parsed_type_or_const! { | |||
|         #[separator] | ||||
|         comma_token: Token![,], | ||||
|         #[const] | ||||
|         const_len: Option<Box<Expr>>, | ||||
|         const_len: Option<Box<ParsedExpr>>, | ||||
|         #[type(default = |span| ParsedType::DynSize(known_items::DynSize(span)))] | ||||
|         type_len: Box<ParsedType>, | ||||
|         gt_token: Token![>], | ||||
|  | @ -1024,7 +1249,7 @@ make_parsed_type_or_const! { | |||
|         uint_type: known_items::UIntType, | ||||
|         lt_token: Token![<], | ||||
|         #[const] | ||||
|         const_width: Option<Box<Expr>>, | ||||
|         const_width: Option<Box<ParsedExpr>>, | ||||
|         #[type(default = |span| ParsedType::DynSize(known_items::DynSize(span)))] | ||||
|         type_width: Box<ParsedType>, | ||||
|         gt_token: Token![>], | ||||
|  | @ -1038,7 +1263,7 @@ make_parsed_type_or_const! { | |||
|         uint_type: known_items::SIntType, | ||||
|         lt_token: Token![<], | ||||
|         #[const] | ||||
|         const_width: Option<Box<Expr>>, | ||||
|         const_width: Option<Box<ParsedExpr>>, | ||||
|         #[type(default = |span| ParsedType::DynSize(known_items::DynSize(span)))] | ||||
|         type_width: Box<ParsedType>, | ||||
|         gt_token: Token![>], | ||||
|  | @ -1207,40 +1432,29 @@ impl ParseTypes<Path> for ParsedType { | |||
|             }, | ||||
|             args, | ||||
|         }; | ||||
|         if let Some(ident) = named.path.get_ident() { | ||||
|             if let Some(¶m_index) = parser.generics().param_name_to_index_map.get(ident) { | ||||
|                 if parser | ||||
|                     .cur_param_index | ||||
|                     .is_some_and(|cur_param_index| param_index >= cur_param_index) | ||||
|                 { | ||||
|                     parser.errors.error( | ||||
|                         parser.generics().params[param_index].ident(), | ||||
|                         "cannot use forward declared identifier in generic parameter defaults", | ||||
|                     ); | ||||
|                 } | ||||
|                 return Ok(Self::NamedParam( | ||||
|                     match parser.generics().params[param_index] { | ||||
|                         ParsedGenericParam::Type(_) => { | ||||
|                             ParsedTypeNamedParam::Type(ParsedTypeNamedParamType { | ||||
|                                 ident: ident.clone(), | ||||
|                                 param_index, | ||||
|                             }) | ||||
|                         } | ||||
|                         ParsedGenericParam::SizeType(_) => { | ||||
|                             ParsedTypeNamedParam::SizeType(ParsedTypeNamedParamSizeType { | ||||
|                                 ident: ident.clone(), | ||||
|                                 param_index, | ||||
|                             }) | ||||
|                         } | ||||
|                         ParsedGenericParam::Const(ParsedConstParam { ref ident, .. }) => { | ||||
|                             parser | ||||
|                                 .errors | ||||
|                                 .error(ident, "constant provided when a type was expected"); | ||||
|                             return Err(ParseFailed); | ||||
|                         } | ||||
|                     }, | ||||
|                 )); | ||||
|             } | ||||
|         if let Some((param_index, ident)) = parser.get_named_param(&named.path) { | ||||
|             return Ok(Self::NamedParam( | ||||
|                 match parser.generics().params[param_index] { | ||||
|                     ParsedGenericParam::Type(_) => { | ||||
|                         ParsedTypeNamedParam::Type(ParsedTypeNamedParamType { | ||||
|                             ident: ident.clone(), | ||||
|                             param_index, | ||||
|                         }) | ||||
|                     } | ||||
|                     ParsedGenericParam::SizeType(_) => { | ||||
|                         ParsedTypeNamedParam::SizeType(ParsedTypeNamedParamSizeType { | ||||
|                             ident: ident.clone(), | ||||
|                             param_index, | ||||
|                         }) | ||||
|                     } | ||||
|                     ParsedGenericParam::Const(ParsedConstParam { ref ident, .. }) => { | ||||
|                         parser | ||||
|                             .errors | ||||
|                             .error(ident, "constant provided when a type was expected"); | ||||
|                         return Err(ParseFailed); | ||||
|                     } | ||||
|                 }, | ||||
|             )); | ||||
|         } | ||||
|         let named = match ParsedTypeArray::try_from_named(named, parser)? { | ||||
|             Ok(v) => return Ok(Self::Array(v)), | ||||
|  | @ -1489,6 +1703,18 @@ impl<'a> TypesParser<'a> { | |||
|     pub(crate) fn parse<T: ParseTypes<I>, I>(&mut self, input: &mut I) -> Result<T, ParseFailed> { | ||||
|         T::parse_types(input, self) | ||||
|     } | ||||
|     pub(crate) fn get_named_param<'b>(&mut self, path: &'b Path) -> Option<(usize, &'b Ident)> { | ||||
|         let ident = path.get_ident()?; | ||||
|         let param_index = *self.generics().param_name_to_index_map.get(ident)?; | ||||
|         if self | ||||
|             .cur_param_index | ||||
|             .is_some_and(|cur_param_index| param_index >= cur_param_index) | ||||
|         { | ||||
|             self.errors | ||||
|                 .error(path, "cannot use forward declared identifier here"); | ||||
|         } | ||||
|         Some((param_index, ident)) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub(crate) trait ParseTypes<I>: Sized { | ||||
|  | @ -2311,7 +2537,7 @@ impl ParsedGenerics { | |||
|     ) { | ||||
|         if self.params.is_empty() { | ||||
|             let target_expr = target_expr(&MakeHdlTypeExprContext { | ||||
|                 type_arg_values: vec![], | ||||
|                 named_param_values: vec![], | ||||
|                 is_const: true, | ||||
|             }); | ||||
|             quote_spanned! {ident.span()=> | ||||
|  | @ -2364,36 +2590,40 @@ impl ParsedGenerics { | |||
|                     .clone() | ||||
|                     .into() | ||||
|             }; | ||||
|             let next_generics = if is_last { | ||||
|                 &final_generics | ||||
|             } else { | ||||
|                 &generics_accumulation_types[next_param_count].generics | ||||
|             let make_next_target_args = |next_arg: Option<GenericArgument>| { | ||||
|                 let generics = if is_last { | ||||
|                     &final_generics | ||||
|                 } else { | ||||
|                     &generics_accumulation_types[next_param_count].generics | ||||
|                 }; | ||||
|                 let type_generics = generics.split_for_impl().1; | ||||
|                 let turbofish = type_generics.as_turbofish(); | ||||
|                 let mut retval: AngleBracketedGenericArguments = parse_quote! { #turbofish }; | ||||
|                 if let Some(next_arg) = next_arg { | ||||
|                     *retval.args.last_mut().unwrap() = next_arg; | ||||
|                 } | ||||
|                 retval | ||||
|             }; | ||||
|             let (cur_impl_generics, cur_type_generics, cur_where_clause) = | ||||
|                 cur_generics.split_for_impl(); | ||||
|             let (_next_impl_generics, next_type_generics, _next_where_clause) = | ||||
|                 next_generics.split_for_impl(); | ||||
|             let next_turbofish = next_type_generics.as_turbofish(); | ||||
|             let mut next_target_expr = |context: &MakeHdlTypeExprContext| -> Expr { | ||||
|                 if is_last { | ||||
|                     target_expr(context) | ||||
|                 } else { | ||||
|                     let args = &context.type_arg_values[..next_param_count]; | ||||
|                     parse_quote_spanned! {ident.span()=> | ||||
|                         #next_target #next_turbofish(#(#args),*) | ||||
|                     } | ||||
|                 } | ||||
|             }; | ||||
|             match next_param { | ||||
|                 ParsedGenericParam::Type(ParsedTypeParam { | ||||
|                     ident: param_ident, | ||||
|                     default, | ||||
|                     .. | ||||
|                 }) => { | ||||
|                     let mut generics = next_generics.clone(); | ||||
|                     let next_generics = if is_last { | ||||
|                         &final_generics | ||||
|                     } else { | ||||
|                         &generics_accumulation_types[next_param_count].generics | ||||
|                     }; | ||||
|                     let (_next_impl_generics, next_type_generics, _next_where_clause) = | ||||
|                         next_generics.split_for_impl(); | ||||
|                     let next_turbofish = next_type_generics.as_turbofish(); | ||||
|                     let mut param: Expr = parse_quote_spanned! {ident.span()=> | ||||
|                         __param | ||||
|                     }; | ||||
|                     let mut generics = next_generics.clone(); | ||||
|                     let mut index_type = param_ident.clone(); | ||||
|                     if let Some((_, default)) = default { | ||||
|                         index_type = format_ident!("__Param", span = ident.span()); | ||||
|  | @ -2402,24 +2632,34 @@ impl ParsedGenerics { | |||
|                             #index_type: ::fayalite::ty::TypeOrDefault<#default, Type = #param_ident> | ||||
|                         }); | ||||
|                         let default_expr = default.make_hdl_type_expr(&MakeHdlTypeExprContext { | ||||
|                             type_arg_values: self_members[..param_count].to_vec(), | ||||
|                             named_param_values: self_members[..param_count].to_vec(), | ||||
|                             is_const: false, | ||||
|                         }); | ||||
|                         param = parse_quote_spanned! {ident.span()=> | ||||
|                             ::fayalite::ty::TypeOrDefault::get(__param, || #default_expr) | ||||
|                         }; | ||||
|                         let output_expr = next_target_expr(&MakeHdlTypeExprContext { | ||||
|                             type_arg_values: self_members[..param_count] | ||||
|                         let context = MakeHdlTypeExprContext { | ||||
|                             named_param_values: self_members[..param_count] | ||||
|                                 .iter() | ||||
|                                 .cloned() | ||||
|                                 .chain([default_expr]) | ||||
|                                 .collect(), | ||||
|                             is_const: false, | ||||
|                         }); | ||||
|                         let mut next_target_args: AngleBracketedGenericArguments = | ||||
|                             parse_quote! { #next_type_generics }; | ||||
|                         *next_target_args.args.last_mut().unwrap() = | ||||
|                             GenericArgument::Type(default.clone().into()); | ||||
|                         }; | ||||
|                         let output_expr = { | ||||
|                             let next_turbofish = next_type_generics.as_turbofish(); | ||||
|                             if is_last { | ||||
|                                 target_expr(&context) | ||||
|                             } else { | ||||
|                                 let args = &context.named_param_values[..next_param_count]; | ||||
|                                 parse_quote_spanned! {ident.span()=> | ||||
|                                     #next_target #next_turbofish(#(#args),*) | ||||
|                                 } | ||||
|                             } | ||||
|                         }; | ||||
|                         let next_target_args = make_next_target_args(Some(GenericArgument::Type( | ||||
|                             default.clone().into(), | ||||
|                         ))); | ||||
|                         quote_spanned! {ident.span()=> | ||||
|                             impl #cur_impl_generics ::fayalite::ty::FillInDefaultedGenerics | ||||
|                             for #cur_target #cur_type_generics | ||||
|  | @ -2436,14 +2676,22 @@ impl ParsedGenerics { | |||
|                         .to_tokens(tokens); | ||||
|                     } | ||||
|                     let (impl_generics, _type_generics, where_clause) = generics.split_for_impl(); | ||||
|                     let output_expr = next_target_expr(&MakeHdlTypeExprContext { | ||||
|                         type_arg_values: self_members[..param_count] | ||||
|                     let context = MakeHdlTypeExprContext { | ||||
|                         named_param_values: self_members[..param_count] | ||||
|                             .iter() | ||||
|                             .cloned() | ||||
|                             .chain([param]) | ||||
|                             .collect(), | ||||
|                         is_const: false, | ||||
|                     }); | ||||
|                     }; | ||||
|                     let output_expr = if is_last { | ||||
|                         target_expr(&context) | ||||
|                     } else { | ||||
|                         let args = &context.named_param_values[..next_param_count]; | ||||
|                         parse_quote_spanned! {ident.span()=> | ||||
|                             #next_target #next_turbofish(#(#args),*) | ||||
|                         } | ||||
|                     }; | ||||
|                     quote_spanned! {ident.span()=> | ||||
|                         #[allow(non_upper_case_globals)] | ||||
|                         #[automatically_derived] | ||||
|  | @ -2468,46 +2716,9 @@ impl ParsedGenerics { | |||
|                     default, | ||||
|                     .. | ||||
|                 }) => { | ||||
|                     if bounds.KnownSize.is_none() { | ||||
|                         let output_expr = next_target_expr(&MakeHdlTypeExprContext { | ||||
|                             type_arg_values: self_members[..param_count] | ||||
|                                 .iter() | ||||
|                                 .cloned() | ||||
|                                 .chain([parse_quote_spanned! {ident.span()=> | ||||
|                                     __param | ||||
|                                 }]) | ||||
|                                 .collect(), | ||||
|                             is_const: false, | ||||
|                         }); | ||||
|                         let mut next_target_args: AngleBracketedGenericArguments = | ||||
|                             parse_quote! { #next_type_generics }; | ||||
|                         *next_target_args.args.last_mut().unwrap() = parse_quote_spanned! {ident.span()=> | ||||
|                             ::fayalite::int::DynSize | ||||
|                         }; | ||||
|                         quote_spanned! {ident.span()=> | ||||
|                             #[allow(non_upper_case_globals)] | ||||
|                             #[automatically_derived] | ||||
|                             impl #cur_impl_generics ::fayalite::__std::ops::Index<::fayalite::__std::primitive::usize> | ||||
|                             for #cur_target #cur_type_generics | ||||
|                             #cur_where_clause | ||||
|                             { | ||||
|                                 type Output = #next_target #next_target_args; | ||||
| 
 | ||||
|                                 fn index( | ||||
|                                     &self, | ||||
|                                     __param: ::fayalite::__std::primitive::usize, | ||||
|                                 ) -> &Self::Output { | ||||
|                                     ::fayalite::intern::Interned::<_>::into_inner( | ||||
|                                         ::fayalite::intern::Intern::intern_sized(#output_expr), | ||||
|                                     ) | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                         .to_tokens(tokens); | ||||
|                     } | ||||
|                     { | ||||
|                         let output_expr = next_target_expr(&MakeHdlTypeExprContext { | ||||
|                             type_arg_values: self_members[..param_count] | ||||
|                         let context = MakeHdlTypeExprContext { | ||||
|                             named_param_values: self_members[..param_count] | ||||
|                                 .iter() | ||||
|                                 .cloned() | ||||
|                                 .chain([parse_quote_spanned! {ident.span()=> | ||||
|  | @ -2515,43 +2726,42 @@ impl ParsedGenerics { | |||
|                                 }]) | ||||
|                                 .collect(), | ||||
|                             is_const: false, | ||||
|                         }); | ||||
|                         }; | ||||
|                         let next_target_args = | ||||
|                             make_next_target_args(Some(parse_quote_spanned! {ident.span()=> | ||||
|                                 <#param_ident as ::fayalite::int::SizeType>::Size | ||||
|                             })); | ||||
|                         let output_expr = if is_last { | ||||
|                             target_expr(&context) | ||||
|                         } else { | ||||
|                             let args = &context.named_param_values[..next_param_count]; | ||||
|                             parse_quote_spanned! {ident.span()=> | ||||
|                                 #next_target #next_target_args(#(#args),*) | ||||
|                             } | ||||
|                         }; | ||||
|                         let mut next_generics = cur_generics.clone(); | ||||
|                         next_generics | ||||
|                             .params | ||||
|                             .push(parse_quote_spanned! {ident.span()=> | ||||
|                                 const #param_ident: ::fayalite::__std::primitive::usize | ||||
|                                 #param_ident: ::fayalite::int::SizeType | ||||
|                             }); | ||||
|                         let known_size = bounds | ||||
|                             .KnownSize | ||||
|                             .clone() | ||||
|                             .unwrap_or_else(|| known_items::KnownSize(ident.span())); | ||||
|                         next_generics.make_where_clause().predicates.push( | ||||
|                             parse_quote_spanned! {ident.span()=> | ||||
|                                 ::fayalite::util::ConstUsize<#param_ident>: #known_size | ||||
|                                 <#param_ident as ::fayalite::int::SizeType>::Size: #bounds | ||||
|                             }, | ||||
|                         ); | ||||
|                         let (next_impl_generics, next_type_generics, next_where_clause) = | ||||
|                         let (next_impl_generics, _next_type_generics, next_where_clause) = | ||||
|                             next_generics.split_for_impl(); | ||||
|                         let mut next_target_args: AngleBracketedGenericArguments = | ||||
|                             parse_quote! { #next_type_generics }; | ||||
|                         *next_target_args.args.last_mut().unwrap() = parse_quote_spanned! {ident.span()=> | ||||
|                             ::fayalite::util::ConstUsize<#param_ident> | ||||
|                         }; | ||||
|                         quote_spanned! {ident.span()=> | ||||
|                             #[allow(non_upper_case_globals)] | ||||
|                             #[automatically_derived] | ||||
|                             impl #next_impl_generics ::fayalite::__std::ops::Index< | ||||
|                                 ::fayalite::util::ConstUsize<#param_ident>, | ||||
|                             > for #cur_target #cur_type_generics | ||||
|                             impl #next_impl_generics ::fayalite::__std::ops::Index<#param_ident> | ||||
|                             for #cur_target #cur_type_generics | ||||
|                             #next_where_clause | ||||
|                             { | ||||
|                                 type Output = #next_target #next_target_args; | ||||
| 
 | ||||
|                                 fn index( | ||||
|                                     &self, | ||||
|                                     __param: ::fayalite::util::ConstUsize<#param_ident>, | ||||
|                                 ) -> &Self::Output { | ||||
|                                 fn index(&self, __param: #param_ident) -> &Self::Output { | ||||
|                                     ::fayalite::intern::Interned::<_>::into_inner( | ||||
|                                         ::fayalite::intern::Intern::intern_sized(#output_expr), | ||||
|                                     ) | ||||
|  | @ -2565,7 +2775,71 @@ impl ParsedGenerics { | |||
|                         todo!(); | ||||
|                     } | ||||
|                 } | ||||
|                 ParsedGenericParam::Const(_) => todo!(), | ||||
|                 ParsedGenericParam::Const(ParsedConstParam { | ||||
|                     attrs: _, | ||||
|                     options: _, | ||||
|                     const_token, | ||||
|                     ident: param_ident, | ||||
|                     colon_token, | ||||
|                     ty: ParsedConstGenericType::Usize(ty), | ||||
|                     bounds: ParsedConstParamWhereBounds { bounds, .. }, | ||||
|                 }) => { | ||||
|                     let context = MakeHdlTypeExprContext { | ||||
|                         named_param_values: self_members[..param_count] | ||||
|                             .iter() | ||||
|                             .cloned() | ||||
|                             .chain([parse_quote_spanned! {ident.span()=> | ||||
|                                 __param | ||||
|                             }]) | ||||
|                             .collect(), | ||||
|                         is_const: false, | ||||
|                     }; | ||||
|                     let next_target_args = | ||||
|                         make_next_target_args(Some(parse_quote! { #param_ident })); | ||||
|                     let output_expr = if is_last { | ||||
|                         target_expr(&context) | ||||
|                     } else { | ||||
|                         let args = &context.named_param_values[..next_param_count]; | ||||
|                         parse_quote_spanned! {ident.span()=> | ||||
|                             #next_target #next_target_args(#(#args),*) | ||||
|                         } | ||||
|                     }; | ||||
|                     let mut next_generics = cur_generics.clone(); | ||||
|                     next_generics | ||||
|                         .params | ||||
|                         .push(parse_quote! { #const_token #param_ident #colon_token #ty }); | ||||
|                     next_generics | ||||
|                         .params | ||||
|                         .push(parse_quote_spanned! {ident.span()=> | ||||
|                             __Param: ::fayalite::int::SizeType< | ||||
|                                 Size = ::fayalite::util::ConstUsize<#param_ident>, | ||||
|                             > | ||||
|                         }); | ||||
|                     next_generics.make_where_clause().predicates.push( | ||||
|                         parse_quote_spanned! {ident.span()=> | ||||
|                             ::fayalite::util::ConstUsize<#param_ident>: ::fayalite::int::Size<SizeType = __Param> + #bounds | ||||
|                         }, | ||||
|                     ); | ||||
|                     let (next_impl_generics, _next_type_generics, next_where_clause) = | ||||
|                         next_generics.split_for_impl(); | ||||
|                     quote_spanned! {ident.span()=> | ||||
|                         #[allow(non_upper_case_globals)] | ||||
|                         #[automatically_derived] | ||||
|                         impl #next_impl_generics ::fayalite::__std::ops::Index<__Param> | ||||
|                         for #cur_target #cur_type_generics | ||||
|                         #next_where_clause | ||||
|                         { | ||||
|                             type Output = #next_target #next_target_args; | ||||
| 
 | ||||
|                             fn index(&self, __param: __Param) -> &Self::Output { | ||||
|                                 ::fayalite::intern::Interned::<_>::into_inner( | ||||
|                                     ::fayalite::intern::Intern::intern_sized(#output_expr), | ||||
|                                 ) | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     .to_tokens(tokens); | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|     } | ||||
|  | @ -3145,7 +3419,8 @@ impl ToTokens for ParsedGenericsWhereClause<'_> { | |||
|         let mut where_token = |span: Span| -> Option<Token![where]> { | ||||
|             mem::replace(&mut need_where_token, false).then(|| Token) | ||||
|         }; | ||||
|         for param in self.generics.params.iter().take(self.param_count) { | ||||
|         for param in self.generics.params.pairs().take(self.param_count) { | ||||
|             let (param, comma_token) = param.into_tuple(); | ||||
|             match param { | ||||
|                 ParsedGenericParam::Type(ParsedTypeParam { | ||||
|                     ident, | ||||
|  | @ -3156,7 +3431,7 @@ impl ToTokens for ParsedGenericsWhereClause<'_> { | |||
|                     if let Some(static_type) = &bounds.StaticType { | ||||
|                         where_token(static_type.span).to_tokens(tokens); | ||||
|                         quote_spanned! {static_type.span=> | ||||
|                             <#ident as ::fayalite::ty::Type>::MaskType #colon_token #static_type, | ||||
|                             <#ident as ::fayalite::ty::Type>::MaskType #colon_token #static_type #comma_token | ||||
|                         } | ||||
|                         .to_tokens(tokens); | ||||
|                     } | ||||
|  | @ -3182,6 +3457,7 @@ impl ToTokens for ParsedGenericsWhereClause<'_> { | |||
|                     gt_token.to_tokens(tokens); | ||||
|                     colon_token.to_tokens(tokens); | ||||
|                     bounds.to_tokens(tokens); | ||||
|                     comma_token.to_tokens(tokens); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | @ -3649,7 +3925,7 @@ impl From<MaybeParsed<ParsedFieldsNamed, FieldsNamed>> for FieldsNamed { | |||
| 
 | ||||
| #[derive(Debug)] | ||||
| pub(crate) struct MakeHdlTypeExprContext { | ||||
|     pub(crate) type_arg_values: Vec<Expr>, | ||||
|     pub(crate) named_param_values: Vec<Expr>, | ||||
|     pub(crate) is_const: bool, | ||||
| } | ||||
| 
 | ||||
|  | @ -3694,6 +3970,28 @@ impl MakeHdlTypeExpr for known_items::DynSize { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl MakeHdlTypeExpr for ParsedExprDelimited { | ||||
|     fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr { | ||||
|         self.expr.make_hdl_type_expr(context) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl MakeHdlTypeExpr for ParsedExprNamedParamConst { | ||||
|     fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr { | ||||
|         context.named_param_values[self.param_index].clone() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl MakeHdlTypeExpr for ParsedExpr { | ||||
|     fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr { | ||||
|         match self { | ||||
|             ParsedExpr::Delimited(expr) => expr.make_hdl_type_expr(context), | ||||
|             ParsedExpr::NamedParamConst(expr) => expr.make_hdl_type_expr(context), | ||||
|             ParsedExpr::Other(expr) => (**expr).clone(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl MakeHdlTypeExpr for ParsedTypeDelimited { | ||||
|     fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr { | ||||
|         self.elem.make_hdl_type_expr(context) | ||||
|  | @ -3743,7 +4041,7 @@ impl MakeHdlTypeExpr for ParsedGenericArgument { | |||
|     fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr { | ||||
|         match self { | ||||
|             ParsedGenericArgument::Type(v) => v.make_hdl_type_expr(context), | ||||
|             ParsedGenericArgument::Const(v) => v.clone(), | ||||
|             ParsedGenericArgument::Const(v) => v.make_hdl_type_expr(context), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -3759,13 +4057,13 @@ impl MakeHdlTypeExpr for ParsedTypeNamedParam { | |||
| 
 | ||||
| impl MakeHdlTypeExpr for ParsedTypeNamedParamType { | ||||
|     fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr { | ||||
|         context.type_arg_values[self.param_index].clone() | ||||
|         context.named_param_values[self.param_index].clone() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl MakeHdlTypeExpr for ParsedTypeNamedParamSizeType { | ||||
|     fn make_hdl_type_expr(&self, context: &MakeHdlTypeExprContext) -> Expr { | ||||
|         context.type_arg_values[self.param_index].clone() | ||||
|         context.named_param_values[self.param_index].clone() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue