This commit is contained in:
parent
5835b995a9
commit
76ea7f82c3
|
@ -5,7 +5,7 @@ use std::{collections::HashMap, fmt, mem};
|
|||
use syn::{
|
||||
parse::{Parse, ParseStream},
|
||||
parse_quote, parse_quote_spanned,
|
||||
punctuated::Punctuated,
|
||||
punctuated::{Pair, Punctuated},
|
||||
spanned::Spanned,
|
||||
token::{Brace, Bracket, Paren},
|
||||
AngleBracketedGenericArguments, Attribute, ConstParam, Expr, ExprIndex, ExprPath, ExprTuple,
|
||||
|
@ -239,7 +239,34 @@ impl ParseTypes<GenericArgument> for ParsedGenericArgument {
|
|||
parser: &mut TypesParser<'_>,
|
||||
) -> Result<Self, ParseFailed> {
|
||||
match arg {
|
||||
GenericArgument::Type(ty) => Ok(Self::Type(parser.parse(ty)?)),
|
||||
GenericArgument::Type(ty) => {
|
||||
{
|
||||
let mut ty = &*ty;
|
||||
while let Type::Group(TypeGroup { elem, .. }) = ty {
|
||||
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(),
|
||||
})));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Self::Type(parser.parse(ty)?))
|
||||
}
|
||||
GenericArgument::Const(expr) => Ok(Self::Const(expr.clone())),
|
||||
_ => parse_failed!(parser, arg, "expected type or const generic argument"),
|
||||
}
|
||||
|
@ -1205,6 +1232,13 @@ impl ParseTypes<Path> for ParsedType {
|
|||
param_index,
|
||||
})
|
||||
}
|
||||
ParsedGenericParam::Const(ParsedConstParam { ref ident, .. }) => {
|
||||
parser
|
||||
.errors
|
||||
.error(ident, "constant provided when a type was expected");
|
||||
todo!();
|
||||
return Err(ParseFailed);
|
||||
}
|
||||
},
|
||||
));
|
||||
}
|
||||
|
@ -1291,6 +1325,120 @@ impl ParseTypes<Type> for ParsedType {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) enum ParsedConstGenericType {
|
||||
Usize(known_items::usize),
|
||||
}
|
||||
|
||||
impl_fold! {
|
||||
enum ParsedConstGenericType<> {
|
||||
Usize(known_items::usize),
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParsedConstGenericType> for Type {
|
||||
fn from(value: ParsedConstGenericType) -> Self {
|
||||
match value {
|
||||
ParsedConstGenericType::Usize(v) => parse_quote! { #v },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MaybeParsed<ParsedConstGenericType, Type>> for Type {
|
||||
fn from(value: MaybeParsed<ParsedConstGenericType, Type>) -> Self {
|
||||
match value {
|
||||
MaybeParsed::Unrecognized(value) => value,
|
||||
MaybeParsed::Parsed(value) => value.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<ParsedConstGenericType>> for Type {
|
||||
fn from(value: Box<ParsedConstGenericType>) -> Self {
|
||||
(*value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ParsedConstGenericType {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
match self {
|
||||
ParsedConstGenericType::Usize(ty) => ty.to_tokens(tokens),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ParseTypes<Path> for ParsedConstGenericType {
|
||||
fn parse_types(path: &mut Path, parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
|
||||
let Path {
|
||||
leading_colon,
|
||||
ref mut segments,
|
||||
} = *path;
|
||||
if segments.is_empty() {
|
||||
parse_failed!(parser, path, "path must not be empty");
|
||||
}
|
||||
let mut args = None;
|
||||
let segments = Punctuated::from_iter(segments.pairs_mut().map_pair_value_mut(|segment| {
|
||||
let PathSegment { ident, arguments } = segment;
|
||||
if let Some(_) = args {
|
||||
parser
|
||||
.errors()
|
||||
.error(&ident, "associated types/consts are not yet implemented");
|
||||
}
|
||||
args = match arguments {
|
||||
PathArguments::None => None,
|
||||
PathArguments::AngleBracketed(args) => parser.parse(args).ok(),
|
||||
PathArguments::Parenthesized(_) => {
|
||||
parser
|
||||
.errors()
|
||||
.error(&segment, "function traits are not allowed");
|
||||
None
|
||||
}
|
||||
};
|
||||
PathSegment::from(segment.ident.clone())
|
||||
}));
|
||||
let named = ParsedTypeNamed {
|
||||
path: Path {
|
||||
leading_colon,
|
||||
segments,
|
||||
},
|
||||
args,
|
||||
};
|
||||
let named = match known_items::usize::try_from_named(named, parser)? {
|
||||
Ok(v) => return Ok(Self::Usize(v)),
|
||||
Err(named) => named,
|
||||
};
|
||||
parser.errors.error(
|
||||
named,
|
||||
"const parameter types other than `usize` are not yet implemented",
|
||||
);
|
||||
Err(ParseFailed)
|
||||
}
|
||||
}
|
||||
|
||||
impl ParseTypes<TypePath> for ParsedConstGenericType {
|
||||
fn parse_types(ty: &mut TypePath, parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
|
||||
let TypePath { qself, path } = ty;
|
||||
if let Some(_qself) = qself {
|
||||
parse_failed!(
|
||||
parser,
|
||||
ty,
|
||||
"associated types/consts are not yet implemented"
|
||||
);
|
||||
} else {
|
||||
parser.parse(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ParseTypes<Type> for ParsedConstGenericType {
|
||||
fn parse_types(ty: &mut Type, parser: &mut TypesParser<'_>) -> Result<Self, ParseFailed> {
|
||||
Ok(match ty {
|
||||
Type::Path(ty) => parser.parse(ty)?,
|
||||
_ => parse_failed!(parser, ty, "unsupported const generic type"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ParseFailed;
|
||||
|
||||
impl fmt::Display for ParseFailed {
|
||||
|
@ -1377,6 +1525,14 @@ pub(crate) enum UnparsedGenericParam {
|
|||
colon_token: Token![:],
|
||||
bounds: ParsedBounds,
|
||||
},
|
||||
Const {
|
||||
attrs: Vec<Attribute>,
|
||||
options: HdlAttr<ConstParamOptions>,
|
||||
const_token: Token![const],
|
||||
ident: Ident,
|
||||
colon_token: Token![:],
|
||||
ty: ParsedConstGenericType,
|
||||
},
|
||||
}
|
||||
|
||||
pub(crate) mod known_items {
|
||||
|
@ -1390,7 +1546,7 @@ pub(crate) mod known_items {
|
|||
macro_rules! impl_known_item_body {
|
||||
($known_item:ident) => {
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(dead_code)]
|
||||
#[allow(dead_code, non_camel_case_types)]
|
||||
pub(crate) struct $known_item {
|
||||
pub(crate) path: Path,
|
||||
pub(crate) span: Span,
|
||||
|
@ -1509,6 +1665,7 @@ pub(crate) mod known_items {
|
|||
impl_known_item!(::fayalite::ty::StaticType);
|
||||
impl_known_item!(::fayalite::ty::Type);
|
||||
impl_known_item!(::fayalite::util::ConstUsize);
|
||||
impl_known_item!(::fayalite::__std::primitive::usize);
|
||||
}
|
||||
|
||||
macro_rules! impl_bounds {
|
||||
|
@ -1865,10 +2022,54 @@ impl ToTokens for ParsedSizeTypeParam {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct ParsedConstParamWhereBounds {
|
||||
pub(crate) const_usize: known_items::ConstUsize,
|
||||
pub(crate) lt_token: Token![<],
|
||||
pub(crate) ident: Ident,
|
||||
pub(crate) gt_token: Token![>],
|
||||
pub(crate) colon_token: Token![:],
|
||||
pub(crate) bounds: ParsedSizeTypeBounds,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct ParsedConstParam {
|
||||
pub(crate) attrs: Vec<Attribute>,
|
||||
pub(crate) options: HdlAttr<ConstParamOptions>,
|
||||
pub(crate) const_token: Token![const],
|
||||
pub(crate) ident: Ident,
|
||||
pub(crate) colon_token: Token![:],
|
||||
pub(crate) ty: ParsedConstGenericType,
|
||||
pub(crate) bounds: ParsedConstParamWhereBounds,
|
||||
}
|
||||
|
||||
impl ToTokens for ParsedConstParam {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let Self {
|
||||
attrs,
|
||||
options,
|
||||
const_token,
|
||||
ident,
|
||||
colon_token,
|
||||
ty,
|
||||
bounds: _,
|
||||
} = self;
|
||||
let ConstParamOptions {} = options.body;
|
||||
for attr in attrs {
|
||||
attr.to_tokens(tokens);
|
||||
}
|
||||
const_token.to_tokens(tokens);
|
||||
ident.to_tokens(tokens);
|
||||
colon_token.to_tokens(tokens);
|
||||
ty.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) enum ParsedGenericParam {
|
||||
Type(ParsedTypeParam),
|
||||
SizeType(ParsedSizeTypeParam),
|
||||
Const(ParsedConstParam),
|
||||
}
|
||||
|
||||
impl ToTokens for ParsedGenericParam {
|
||||
|
@ -1876,6 +2077,7 @@ impl ToTokens for ParsedGenericParam {
|
|||
match self {
|
||||
ParsedGenericParam::Type(v) => v.to_tokens(tokens),
|
||||
ParsedGenericParam::SizeType(v) => v.to_tokens(tokens),
|
||||
ParsedGenericParam::Const(v) => v.to_tokens(tokens),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1885,6 +2087,7 @@ impl ParsedGenericParam {
|
|||
match self {
|
||||
ParsedGenericParam::Type(v) => &v.ident,
|
||||
ParsedGenericParam::SizeType(v) => &v.ident,
|
||||
ParsedGenericParam::Const(v) => &v.ident,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1911,6 +2114,11 @@ impl ParsedGenerics {
|
|||
.KnownSize
|
||||
.get_or_insert_with(|| known_items::KnownSize(ident.span()));
|
||||
}
|
||||
ParsedGenericParam::Const(ParsedConstParam { ident, bounds, .. }) => {
|
||||
bounds
|
||||
.KnownSize
|
||||
.get_or_insert_with(|| known_items::KnownSize(ident.span()));
|
||||
}
|
||||
}
|
||||
}
|
||||
self
|
||||
|
@ -1982,6 +2190,13 @@ impl ParsedGenerics {
|
|||
<#ident as ::fayalite::int::Size>::SizeType
|
||||
}
|
||||
}
|
||||
ParsedGenericParam::Const(param) => {
|
||||
let ident = ¶m.ident;
|
||||
parse_quote_spanned! {span=>
|
||||
<::fayalite::util::ConstUsize<#ident>
|
||||
as ::fayalite::int::Size>::SizeType
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
|
@ -2254,98 +2469,117 @@ impl ParsedGenerics {
|
|||
todo!();
|
||||
}
|
||||
}
|
||||
ParsedGenericParam::Const(_) => todo!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
pub(crate) fn parse(generics: &mut Generics) -> syn::Result<Self> {
|
||||
pub(crate) fn parse<'a>(generics: &'a mut Generics) -> syn::Result<Self> {
|
||||
let Generics {
|
||||
lt_token,
|
||||
params,
|
||||
params: input_params,
|
||||
gt_token,
|
||||
where_clause,
|
||||
} = generics;
|
||||
let mut errors = Errors::new();
|
||||
let mut predicates: Vec<WherePredicate> = Vec::with_capacity(params.len());
|
||||
let mut defaults = Vec::with_capacity(params.len());
|
||||
let mut params = Punctuated::<UnparsedGenericParam, _>::from_iter(
|
||||
params.pairs_mut().filter_map_pair_value_mut(|param| {
|
||||
let (param, default) = match param {
|
||||
GenericParam::Lifetime(param) => {
|
||||
errors.unwrap_or_default(
|
||||
HdlAttr::<LifetimeParamOptions>::parse_and_take_attr(&mut param.attrs),
|
||||
);
|
||||
errors.error(param, "lifetime generics are not supported by #[hdl]");
|
||||
return None;
|
||||
let mut predicates: Vec<WherePredicate> = Vec::with_capacity(input_params.len());
|
||||
struct LateParsedParam<'a> {
|
||||
default: Option<(Token![=], &'a mut Type)>,
|
||||
const_param_type: Option<&'a mut Type>,
|
||||
}
|
||||
let mut late_parsed_params: Vec<LateParsedParam<'a>> =
|
||||
Vec::with_capacity(input_params.len());
|
||||
let mut unparsed_params: Punctuated<UnparsedGenericParam, _> = Punctuated::new();
|
||||
for input_param in input_params.pairs_mut() {
|
||||
let (input_param, punct) = input_param.into_tuple();
|
||||
let (unparsed_param, late_parsed_param) = match input_param {
|
||||
GenericParam::Lifetime(param) => {
|
||||
errors.unwrap_or_default(HdlAttr::<LifetimeParamOptions>::parse_and_take_attr(
|
||||
&mut param.attrs,
|
||||
));
|
||||
errors.error(param, "lifetime generics are not supported by #[hdl]");
|
||||
continue;
|
||||
}
|
||||
GenericParam::Type(TypeParam {
|
||||
attrs,
|
||||
ident,
|
||||
colon_token,
|
||||
bounds,
|
||||
eq_token,
|
||||
default,
|
||||
}) => {
|
||||
let span = ident.span();
|
||||
let options = errors
|
||||
.unwrap_or_default(HdlAttr::<TypeParamOptions>::parse_and_take_attr(attrs))
|
||||
.unwrap_or_default();
|
||||
let colon_token = colon_token.unwrap_or_else(|| Token![:](span));
|
||||
if !bounds.is_empty() {
|
||||
predicates.push(WherePredicate::Type(PredicateType {
|
||||
lifetimes: None,
|
||||
bounded_ty: parse_quote! { #ident },
|
||||
colon_token,
|
||||
bounds: bounds.clone(),
|
||||
}));
|
||||
}
|
||||
GenericParam::Type(TypeParam {
|
||||
attrs,
|
||||
ident,
|
||||
colon_token,
|
||||
bounds,
|
||||
eq_token,
|
||||
default,
|
||||
}) => {
|
||||
let span = ident.span();
|
||||
let options = errors
|
||||
.unwrap_or_default(HdlAttr::<TypeParamOptions>::parse_and_take_attr(
|
||||
attrs,
|
||||
))
|
||||
.unwrap_or_default();
|
||||
let colon_token = colon_token.unwrap_or_else(|| Token![:](span));
|
||||
if !bounds.is_empty() {
|
||||
predicates.push(WherePredicate::Type(PredicateType {
|
||||
lifetimes: None,
|
||||
bounded_ty: parse_quote! { #ident },
|
||||
colon_token,
|
||||
bounds: bounds.clone(),
|
||||
}));
|
||||
}
|
||||
(
|
||||
UnparsedGenericParam::Type {
|
||||
attrs: attrs.clone(),
|
||||
options,
|
||||
ident: ident.clone(),
|
||||
colon_token,
|
||||
bounds: ParsedBounds::default(),
|
||||
},
|
||||
default
|
||||
.clone()
|
||||
(
|
||||
UnparsedGenericParam::Type {
|
||||
attrs: attrs.clone(),
|
||||
options,
|
||||
ident: ident.clone(),
|
||||
colon_token,
|
||||
bounds: ParsedBounds::default(),
|
||||
},
|
||||
LateParsedParam {
|
||||
default: default
|
||||
.as_mut()
|
||||
.map(|v| (eq_token.unwrap_or_else(|| Token![=](span)), v)),
|
||||
)
|
||||
}
|
||||
GenericParam::Const(ConstParam {
|
||||
attrs,
|
||||
const_token,
|
||||
ident,
|
||||
colon_token,
|
||||
ty,
|
||||
eq_token,
|
||||
default,
|
||||
}) => {
|
||||
let options = errors
|
||||
.unwrap_or_default(HdlAttr::<ConstParamOptions>::parse_and_take_attr(
|
||||
attrs,
|
||||
))
|
||||
.unwrap_or_default();
|
||||
let _ = const_token;
|
||||
let _ = ident;
|
||||
let _ = colon_token;
|
||||
let _ = ty;
|
||||
const_param_type: None,
|
||||
},
|
||||
)
|
||||
}
|
||||
GenericParam::Const(ConstParam {
|
||||
attrs,
|
||||
const_token,
|
||||
ident,
|
||||
colon_token,
|
||||
ty,
|
||||
eq_token,
|
||||
default,
|
||||
}) => {
|
||||
let options = errors
|
||||
.unwrap_or_default(HdlAttr::<ConstParamOptions>::parse_and_take_attr(attrs))
|
||||
.unwrap_or_default();
|
||||
if let Some(default) = default {
|
||||
let _ = eq_token;
|
||||
let _ = default;
|
||||
let _ = options;
|
||||
todo!()
|
||||
errors.error(
|
||||
default,
|
||||
"const generics' default values are not yet implemented",
|
||||
);
|
||||
}
|
||||
};
|
||||
defaults.push(default);
|
||||
Some(param)
|
||||
}),
|
||||
);
|
||||
let param_name_to_index_map: HashMap<Ident, usize> = params
|
||||
(
|
||||
UnparsedGenericParam::Const {
|
||||
attrs: attrs.clone(),
|
||||
options,
|
||||
const_token: *const_token,
|
||||
ident: ident.clone(),
|
||||
colon_token: *colon_token,
|
||||
ty: ParsedConstGenericType::Usize(known_items::usize(ident.span())),
|
||||
},
|
||||
LateParsedParam {
|
||||
default: None,
|
||||
const_param_type: Some(ty),
|
||||
},
|
||||
)
|
||||
}
|
||||
};
|
||||
late_parsed_params.push(late_parsed_param);
|
||||
unparsed_params.extend([Pair::new(unparsed_param, punct.cloned())]);
|
||||
}
|
||||
let param_name_to_index_map: HashMap<Ident, usize> = unparsed_params
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, param)| {
|
||||
let UnparsedGenericParam::Type { ident, .. } = param;
|
||||
let (UnparsedGenericParam::Type { ident, .. }
|
||||
| UnparsedGenericParam::Const { ident, .. }) = param;
|
||||
(ident.clone(), index)
|
||||
})
|
||||
.collect();
|
||||
|
@ -2367,80 +2601,131 @@ impl ParsedGenerics {
|
|||
errors.error(predicate, "unsupported where predicate kind");
|
||||
continue;
|
||||
};
|
||||
ParsedTypeNamed {
|
||||
path: todo!(),
|
||||
args: todo!(),
|
||||
};
|
||||
let Some(&index) = bounded_ty
|
||||
.get_ident()
|
||||
.and_then(|bounded_ty| param_name_to_index_map.get(bounded_ty))
|
||||
else {
|
||||
errors.error(
|
||||
bounded_ty,
|
||||
"where predicate bounded type must be one of the generic parameters",
|
||||
"where predicate bounded type must be one of the generic type \
|
||||
parameters or `ConstUsize<A_CONST_PARAM>`",
|
||||
);
|
||||
continue;
|
||||
};
|
||||
let UnparsedGenericParam::Type {
|
||||
bounds: parsed_bounds,
|
||||
..
|
||||
} = &mut params[index];
|
||||
let parsed_bounds = match &mut unparsed_params[index] {
|
||||
UnparsedGenericParam::Type { bounds, .. } => bounds,
|
||||
UnparsedGenericParam::Const { ident, .. } => {
|
||||
errors.error(
|
||||
bounded_ty,
|
||||
format_args!("expected type, found const parameter `{ident}`"),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
parsed_bounds.extend(errors.ok(syn::parse2::<ParsedBounds>(
|
||||
unparsed_bounds.to_token_stream(),
|
||||
)));
|
||||
}
|
||||
let params =
|
||||
Punctuated::from_iter(params.into_pairs().map_pair_value(|param| match param {
|
||||
UnparsedGenericParam::Type {
|
||||
attrs,
|
||||
options,
|
||||
ident,
|
||||
colon_token,
|
||||
mut bounds,
|
||||
} => {
|
||||
bounds.add_implied_bounds();
|
||||
match bounds.categorize(&mut errors, ident.span()) {
|
||||
ParsedBoundsCategory::Type(bounds) => {
|
||||
ParsedGenericParam::Type(ParsedTypeParam {
|
||||
attrs,
|
||||
options,
|
||||
ident,
|
||||
colon_token,
|
||||
bounds,
|
||||
default: None,
|
||||
})
|
||||
}
|
||||
ParsedBoundsCategory::SizeType(bounds) => {
|
||||
ParsedGenericParam::SizeType(ParsedSizeTypeParam {
|
||||
attrs,
|
||||
options,
|
||||
ident,
|
||||
colon_token,
|
||||
bounds,
|
||||
default: None,
|
||||
})
|
||||
Punctuated::from_iter(unparsed_params.into_pairs().map_pair_value(
|
||||
|param| match param {
|
||||
UnparsedGenericParam::Type {
|
||||
attrs,
|
||||
options,
|
||||
ident,
|
||||
colon_token,
|
||||
mut bounds,
|
||||
} => {
|
||||
bounds.add_implied_bounds();
|
||||
match bounds.categorize(&mut errors, ident.span()) {
|
||||
ParsedBoundsCategory::Type(bounds) => {
|
||||
ParsedGenericParam::Type(ParsedTypeParam {
|
||||
attrs,
|
||||
options,
|
||||
ident,
|
||||
colon_token,
|
||||
bounds,
|
||||
default: None,
|
||||
})
|
||||
}
|
||||
ParsedBoundsCategory::SizeType(bounds) => {
|
||||
ParsedGenericParam::SizeType(ParsedSizeTypeParam {
|
||||
attrs,
|
||||
options,
|
||||
ident,
|
||||
colon_token,
|
||||
bounds,
|
||||
default: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
UnparsedGenericParam::Const {
|
||||
attrs,
|
||||
options,
|
||||
const_token,
|
||||
ident,
|
||||
colon_token,
|
||||
ty,
|
||||
} => ParsedGenericParam::Const(ParsedConstParam {
|
||||
bounds: ParsedSizeTypeBounds {
|
||||
KnownSize: None,
|
||||
Size: Some(known_items::Size(ident.span())),
|
||||
},
|
||||
attrs,
|
||||
options,
|
||||
const_token,
|
||||
ident,
|
||||
colon_token,
|
||||
ty,
|
||||
}),
|
||||
},
|
||||
));
|
||||
let mut retval = Self {
|
||||
lt_token: *lt_token,
|
||||
params,
|
||||
gt_token: *gt_token,
|
||||
param_name_to_index_map,
|
||||
};
|
||||
for (cur_param_index, default) in defaults.into_iter().enumerate() {
|
||||
let Some((eq, mut ty)) = default else {
|
||||
continue;
|
||||
};
|
||||
let Ok(ty) = TypesParser {
|
||||
for (
|
||||
cur_param_index,
|
||||
LateParsedParam {
|
||||
default,
|
||||
const_param_type,
|
||||
},
|
||||
) in late_parsed_params.into_iter().enumerate()
|
||||
{
|
||||
let mut parser = TypesParser {
|
||||
generics: &retval,
|
||||
cur_param_index: Some(cur_param_index),
|
||||
errors: &mut errors,
|
||||
}
|
||||
.parse(&mut ty) else {
|
||||
continue;
|
||||
};
|
||||
let parsed_default = default.and_then(|(eq, ty)| {
|
||||
let ty = parser.parse(ty).ok()?;
|
||||
Some((eq, ty))
|
||||
});
|
||||
let parsed_const_param_type = const_param_type.and_then(|ty| parser.parse(ty).ok());
|
||||
match &mut retval.params[cur_param_index] {
|
||||
ParsedGenericParam::Type(ParsedTypeParam { default, .. })
|
||||
| ParsedGenericParam::SizeType(ParsedSizeTypeParam { default, .. }) => {
|
||||
*default = Some((eq, ty))
|
||||
*default = parsed_default;
|
||||
}
|
||||
ParsedGenericParam::Const(ParsedConstParam {
|
||||
attrs: _,
|
||||
options: _,
|
||||
const_token: _,
|
||||
ident: _,
|
||||
colon_token: _,
|
||||
ty,
|
||||
bounds: _,
|
||||
}) => {
|
||||
if let Some(parsed_const_param_type) = parsed_const_param_type {
|
||||
*ty = parsed_const_param_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2517,6 +2802,21 @@ impl ToTokens for ParsedGenericsImplGenerics<'_> {
|
|||
colon_token.to_tokens(tokens);
|
||||
bounds.to_tokens(tokens);
|
||||
}
|
||||
ParsedGenericParam::Const(ParsedConstParam {
|
||||
attrs: _,
|
||||
options,
|
||||
const_token,
|
||||
ident,
|
||||
colon_token,
|
||||
ty,
|
||||
bounds: _,
|
||||
}) => {
|
||||
let ConstParamOptions {} = options.body;
|
||||
const_token.to_tokens(tokens);
|
||||
ident.to_tokens(tokens);
|
||||
colon_token.to_tokens(tokens);
|
||||
ty.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
punct.to_tokens(tokens);
|
||||
}
|
||||
|
@ -2609,6 +2909,27 @@ impl ToTokens for ParsedGenericsWhereClause<'_> {
|
|||
}
|
||||
}
|
||||
ParsedGenericParam::SizeType(_) => {}
|
||||
ParsedGenericParam::Const(ParsedConstParam {
|
||||
ident: _,
|
||||
bounds:
|
||||
ParsedConstParamWhereBounds {
|
||||
const_usize,
|
||||
lt_token,
|
||||
ident,
|
||||
gt_token,
|
||||
colon_token,
|
||||
bounds,
|
||||
},
|
||||
..
|
||||
}) => {
|
||||
where_token(ident.span()).to_tokens(tokens);
|
||||
const_usize.to_tokens(tokens);
|
||||
lt_token.to_tokens(tokens);
|
||||
ident.to_tokens(tokens);
|
||||
gt_token.to_tokens(tokens);
|
||||
colon_token.to_tokens(tokens);
|
||||
bounds.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue