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()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
 | 
			
		||||
use crate::{
 | 
			
		||||
    expr::{ops::ArrayIndex, Expr, ToExpr},
 | 
			
		||||
    int::{DynSize, KnownSize, Size},
 | 
			
		||||
    int::{DynSize, KnownSize, Size, SizeType, DYN_SIZE},
 | 
			
		||||
    intern::{Intern, Interned, LazyInterned},
 | 
			
		||||
    module::transform::visit::{Fold, Folder, Visit, Visitor},
 | 
			
		||||
    source_location::SourceLocation,
 | 
			
		||||
| 
						 | 
				
			
			@ -27,10 +27,7 @@ impl<T: Type, Len: Size> std::fmt::Debug for ArrayType<T, Len> {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub type Array<
 | 
			
		||||
    T = CanonicalType,
 | 
			
		||||
    const LEN: usize = { <DynSize as crate::util::GenericConstUsize>::VALUE },
 | 
			
		||||
> = ArrayType<T, ConstUsize<LEN>>;
 | 
			
		||||
pub type Array<T = CanonicalType, const LEN: usize = DYN_SIZE> = ArrayType<T, ConstUsize<LEN>>;
 | 
			
		||||
 | 
			
		||||
#[allow(non_upper_case_globals)]
 | 
			
		||||
pub const Array: ArrayWithoutGenerics = ArrayWithoutGenerics;
 | 
			
		||||
| 
						 | 
				
			
			@ -214,21 +211,10 @@ pub struct ArrayWithoutLen<T: Type> {
 | 
			
		|||
    element: T,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Type> Index<usize> for ArrayWithoutLen<T> {
 | 
			
		||||
    type Output = Array<T>;
 | 
			
		||||
impl<T: Type, L: SizeType> Index<L> for ArrayWithoutLen<T> {
 | 
			
		||||
    type Output = ArrayType<T, L::Size>;
 | 
			
		||||
 | 
			
		||||
    fn index(&self, len: usize) -> &Self::Output {
 | 
			
		||||
        Interned::<_>::into_inner(Intern::intern_sized(Array::new_dyn(self.element, len)))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Type, const LEN: usize> Index<ConstUsize<LEN>> for ArrayWithoutLen<T>
 | 
			
		||||
where
 | 
			
		||||
    ConstUsize<LEN>: KnownSize,
 | 
			
		||||
{
 | 
			
		||||
    type Output = Array<T, LEN>;
 | 
			
		||||
 | 
			
		||||
    fn index(&self, len: ConstUsize<LEN>) -> &Self::Output {
 | 
			
		||||
        Interned::<_>::into_inner(Intern::intern_sized(Array::new(self.element, len)))
 | 
			
		||||
    fn index(&self, len: L) -> &Self::Output {
 | 
			
		||||
        Interned::<_>::into_inner(Intern::intern_sized(ArrayType::new(self.element, len)))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@ use std::{
 | 
			
		|||
mod sealed {
 | 
			
		||||
    pub trait BoolOrIntTypeSealed {}
 | 
			
		||||
    pub trait SizeSealed {}
 | 
			
		||||
    pub trait SizeTypeSealed {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub const DYN_SIZE: usize = !0;
 | 
			
		||||
| 
						 | 
				
			
			@ -59,6 +60,12 @@ macro_rules! known_widths {
 | 
			
		|||
 | 
			
		||||
known_widths!([2 2 2 2 2 2 2 2 2]);
 | 
			
		||||
 | 
			
		||||
pub trait SizeType:
 | 
			
		||||
    sealed::SizeTypeSealed + Copy + Ord + std::hash::Hash + std::fmt::Debug + Send + Sync + 'static
 | 
			
		||||
{
 | 
			
		||||
    type Size: Size<SizeType = Self>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub trait Size:
 | 
			
		||||
    sealed::SizeSealed + Copy + Ord + std::hash::Hash + std::fmt::Debug + Send + Sync + 'static
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +83,14 @@ pub trait Size:
 | 
			
		|||
        + TryFrom<Vec<Expr<Element>>>
 | 
			
		||||
        + Into<Vec<Expr<Element>>>;
 | 
			
		||||
    const KNOWN_VALUE: Option<usize>;
 | 
			
		||||
    type SizeType: Copy + Ord + std::hash::Hash + std::fmt::Debug + Send + Sync + 'static;
 | 
			
		||||
    type SizeType: SizeType<Size = Self>
 | 
			
		||||
        + Copy
 | 
			
		||||
        + Ord
 | 
			
		||||
        + std::hash::Hash
 | 
			
		||||
        + std::fmt::Debug
 | 
			
		||||
        + Send
 | 
			
		||||
        + Sync
 | 
			
		||||
        + 'static;
 | 
			
		||||
    fn as_usize(size_type: Self::SizeType) -> usize;
 | 
			
		||||
    fn try_from_usize(v: usize) -> Option<Self::SizeType>;
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
| 
						 | 
				
			
			@ -85,6 +99,12 @@ pub trait Size:
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl sealed::SizeTypeSealed for usize {}
 | 
			
		||||
 | 
			
		||||
impl SizeType for usize {
 | 
			
		||||
    type Size = DynSize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Size for DynSize {
 | 
			
		||||
    type ArrayMatch<Element: Type> = Box<[Expr<Element>]>;
 | 
			
		||||
    const KNOWN_VALUE: Option<usize> = None;
 | 
			
		||||
| 
						 | 
				
			
			@ -101,6 +121,15 @@ impl Size for DynSize {
 | 
			
		|||
 | 
			
		||||
impl<const VALUE: usize> sealed::SizeSealed for ConstUsize<VALUE> {}
 | 
			
		||||
 | 
			
		||||
impl<const VALUE: usize> sealed::SizeTypeSealed for ConstUsize<VALUE> {}
 | 
			
		||||
 | 
			
		||||
impl<const VALUE: usize> SizeType for ConstUsize<VALUE>
 | 
			
		||||
where
 | 
			
		||||
    ConstUsize<VALUE>: KnownSize,
 | 
			
		||||
{
 | 
			
		||||
    type Size = ConstUsize<VALUE>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<const VALUE: usize> Size for ConstUsize<VALUE>
 | 
			
		||||
where
 | 
			
		||||
    ConstUsize<VALUE>: KnownSize,
 | 
			
		||||
| 
						 | 
				
			
			@ -138,9 +167,7 @@ macro_rules! impl_int {
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        pub type $pretty_name<
 | 
			
		||||
            const WIDTH: usize = { <DynSize as crate::util::GenericConstUsize>::VALUE },
 | 
			
		||||
        > = $name<ConstUsize<WIDTH>>;
 | 
			
		||||
        pub type $pretty_name<const WIDTH: usize = DYN_SIZE> = $name<ConstUsize<WIDTH>>;
 | 
			
		||||
 | 
			
		||||
        #[allow(non_upper_case_globals)]
 | 
			
		||||
        pub const $pretty_name: $generic_name = $generic_name;
 | 
			
		||||
| 
						 | 
				
			
			@ -269,21 +296,10 @@ macro_rules! impl_int {
 | 
			
		|||
        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)]
 | 
			
		||||
        pub struct $generic_name;
 | 
			
		||||
 | 
			
		||||
        impl Index<usize> for $generic_name {
 | 
			
		||||
            type Output = $name;
 | 
			
		||||
        impl<Width: SizeType> Index<Width> for $generic_name {
 | 
			
		||||
            type Output = $name<Width::Size>;
 | 
			
		||||
 | 
			
		||||
            fn index(&self, width: usize) -> &Self::Output {
 | 
			
		||||
                Interned::<_>::into_inner(Intern::intern_sized($name::new_dyn(width)))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        impl<const WIDTH: usize> Index<ConstUsize<WIDTH>> for $generic_name
 | 
			
		||||
        where
 | 
			
		||||
            ConstUsize<WIDTH>: KnownSize,
 | 
			
		||||
        {
 | 
			
		||||
            type Output = $pretty_name<WIDTH>;
 | 
			
		||||
 | 
			
		||||
            fn index(&self, width: ConstUsize<WIDTH>) -> &Self::Output {
 | 
			
		||||
            fn index(&self, width: Width) -> &Self::Output {
 | 
			
		||||
                Interned::<_>::into_inner(Intern::intern_sized($name::new(width)))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,16 +1,22 @@
 | 
			
		|||
// SPDX-License-Identifier: LGPL-3.0-or-later
 | 
			
		||||
// See Notices.txt for copyright information
 | 
			
		||||
use fayalite::{
 | 
			
		||||
    array::ArrayType,
 | 
			
		||||
    hdl,
 | 
			
		||||
    int::{IntType, Size, UInt},
 | 
			
		||||
};
 | 
			
		||||
use fayalite::prelude::*;
 | 
			
		||||
 | 
			
		||||
#[hdl(outline_generated)]
 | 
			
		||||
pub struct S<T: IntType, Len: Size> {
 | 
			
		||||
pub struct S<T, Len: Size, T2> {
 | 
			
		||||
    pub a: T,
 | 
			
		||||
    b: UInt<3>,
 | 
			
		||||
    pub(crate) c: ArrayType<UInt<1>, Len>,
 | 
			
		||||
    pub d: T2,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//#[cfg(todo)]
 | 
			
		||||
#[hdl(outline_generated)]
 | 
			
		||||
pub struct S3<const LEN: usize, T> {
 | 
			
		||||
    pub a: T,
 | 
			
		||||
    b: UInt<3>,
 | 
			
		||||
    pub(crate) c: Array<UInt<1>, LEN>,
 | 
			
		||||
    pub d: S<T, ConstUsize<LEN>, ()>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[hdl(outline_generated)]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue