fix handling of const and size type generics when generating Index impls
All checks were successful
/ test (push) Successful in 5m1s
All checks were successful
/ test (push) Successful in 5m1s
This commit is contained in:
parent
2c1afd1cd6
commit
9887d70f41
|
@ -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.span)),
|
||||
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![<]($span),
|
||||
value: Box::new($const_arg.clone()),
|
||||
value: $const_arg.clone(),
|
||||
gt_token: Token![>]($span),
|
||||
}));
|
||||
($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![where](span))
|
||||
};
|
||||
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…
Reference in a new issue