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