This commit is contained in:
parent
bf907c3872
commit
59cef3f398
|
@ -1273,6 +1273,130 @@ make_parsed_type_or_const! {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct ParsedTypePhantomData {
|
||||
pub(crate) phantom_data: known_items::PhantomData,
|
||||
pub(crate) lt_token: Token![<],
|
||||
pub(crate) ty: Box<ParsedType>,
|
||||
pub(crate) gt_token: Token![>],
|
||||
}
|
||||
|
||||
impl_fold! {
|
||||
struct ParsedTypePhantomData<> {
|
||||
phantom_data: known_items::PhantomData,
|
||||
lt_token: Token![<],
|
||||
ty: Box<ParsedType>,
|
||||
gt_token: Token![>],
|
||||
}
|
||||
}
|
||||
|
||||
impl ParsedTypePhantomData {
|
||||
pub(crate) fn try_from_named(
|
||||
named: ParsedTypeNamed,
|
||||
parser: &mut TypesParser<'_>,
|
||||
) -> Result<Result<Self, ParsedTypeNamed>, ParseFailed> {
|
||||
let ParsedTypeNamed { path, args } = named;
|
||||
let parsed_path = known_items::PhantomData::parse_path(path);
|
||||
let phantom_data = match parsed_path {
|
||||
Ok(phantom_data) => phantom_data,
|
||||
Err(path) => return Ok(Err(ParsedTypeNamed { path, args })),
|
||||
};
|
||||
let Some(ParsedGenericArguments {
|
||||
colon2_token: _,
|
||||
lt_token,
|
||||
args,
|
||||
gt_token,
|
||||
}) = args
|
||||
else {
|
||||
parser
|
||||
.errors()
|
||||
.error(phantom_data, "PhantomData requires generic arguments");
|
||||
return Err(ParseFailed);
|
||||
};
|
||||
let args_len = args.len();
|
||||
if args_len != 1 {
|
||||
parser.errors().error(
|
||||
phantom_data,
|
||||
format_args!(
|
||||
"wrong number of generic arguments supplied: got {args_len}, expected 1"
|
||||
),
|
||||
);
|
||||
return Err(ParseFailed);
|
||||
}
|
||||
let ty = args.into_iter().next().unwrap();
|
||||
let ParsedGenericArgument::Type(ty) = ty else {
|
||||
parser.errors().error(ty, "expected a type");
|
||||
return Err(ParseFailed);
|
||||
};
|
||||
Ok(Ok(Self {
|
||||
phantom_data,
|
||||
lt_token,
|
||||
ty: Box::new(ty),
|
||||
gt_token,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParsedTypePhantomData> for Type {
|
||||
fn from(value: ParsedTypePhantomData) -> Type {
|
||||
let ParsedTypePhantomData {
|
||||
phantom_data,
|
||||
lt_token,
|
||||
ty,
|
||||
gt_token,
|
||||
} = value;
|
||||
let path = phantom_data.path;
|
||||
let mut args = Punctuated::new();
|
||||
args.push(GenericArgument::Type(ty.into()));
|
||||
let args = AngleBracketedGenericArguments {
|
||||
colon2_token: Some(Token![::](lt_token.span)),
|
||||
lt_token,
|
||||
args,
|
||||
gt_token,
|
||||
};
|
||||
let mut segments = path.segments;
|
||||
segments.last_mut().unwrap().arguments = PathArguments::AngleBracketed(args);
|
||||
Type::Path(TypePath {
|
||||
qself: None,
|
||||
path: Path {
|
||||
leading_colon: path.leading_colon,
|
||||
segments,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl MakeHdlTypeExpr for ParsedTypePhantomData {
|
||||
fn make_hdl_type_expr(&self, _context: &MakeHdlTypeExprContext) -> Expr {
|
||||
let ParsedTypePhantomData {
|
||||
phantom_data,
|
||||
lt_token: _,
|
||||
ty: _,
|
||||
gt_token: _,
|
||||
} = self;
|
||||
Expr::Path(ExprPath {
|
||||
attrs: vec![],
|
||||
qself: None,
|
||||
path: phantom_data.path.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ParsedTypePhantomData {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let Self {
|
||||
phantom_data,
|
||||
lt_token,
|
||||
ty,
|
||||
gt_token,
|
||||
} = self;
|
||||
phantom_data.to_tokens(tokens);
|
||||
lt_token.to_tokens(tokens);
|
||||
ty.to_tokens(tokens);
|
||||
gt_token.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) enum ParsedType {
|
||||
Delimited(ParsedTypeDelimited),
|
||||
|
@ -1280,6 +1404,7 @@ pub(crate) enum ParsedType {
|
|||
NamedParam(ParsedTypeNamedParam),
|
||||
Tuple(ParsedTypeTuple),
|
||||
ConstUsize(ParsedTypeConstUsize),
|
||||
PhantomData(ParsedTypePhantomData),
|
||||
Array(ParsedTypeArray),
|
||||
UInt(ParsedTypeUInt),
|
||||
SInt(ParsedTypeSInt),
|
||||
|
@ -1294,6 +1419,7 @@ impl_fold! {
|
|||
NamedParam(ParsedTypeNamedParam),
|
||||
Tuple(ParsedTypeTuple),
|
||||
ConstUsize(ParsedTypeConstUsize),
|
||||
PhantomData(ParsedTypePhantomData),
|
||||
Array(ParsedTypeArray),
|
||||
UInt(ParsedTypeUInt),
|
||||
SInt(ParsedTypeSInt),
|
||||
|
@ -1310,6 +1436,7 @@ impl From<ParsedType> for Type {
|
|||
ParsedType::NamedParam(v) => v.into(),
|
||||
ParsedType::Tuple(v) => v.into(),
|
||||
ParsedType::ConstUsize(v) => v.into(),
|
||||
ParsedType::PhantomData(v) => v.into(),
|
||||
ParsedType::Array(v) => v.into(),
|
||||
ParsedType::UInt(v) => v.into(),
|
||||
ParsedType::SInt(v) => v.into(),
|
||||
|
@ -1360,6 +1487,7 @@ impl ToTokens for ParsedType {
|
|||
ParsedType::Named(ty) => ty.to_tokens(tokens),
|
||||
ParsedType::Tuple(ty) => ty.to_tokens(tokens),
|
||||
ParsedType::ConstUsize(ty) => ty.to_tokens(tokens),
|
||||
ParsedType::PhantomData(ty) => ty.to_tokens(tokens),
|
||||
ParsedType::Array(ty) => ty.to_tokens(tokens),
|
||||
ParsedType::UInt(ty) => ty.to_tokens(tokens),
|
||||
ParsedType::SInt(ty) => ty.to_tokens(tokens),
|
||||
|
@ -1467,6 +1595,10 @@ impl ParseTypes<Path> for ParsedType {
|
|||
Ok(v) => return Ok(Self::ConstUsize(v)),
|
||||
Err(named) => named,
|
||||
};
|
||||
let named = match ParsedTypePhantomData::try_from_named(named, parser)? {
|
||||
Ok(v) => return Ok(Self::PhantomData(v)),
|
||||
Err(named) => named,
|
||||
};
|
||||
let named = match ParsedTypeUInt::try_from_named(named, parser)? {
|
||||
Ok(v) => return Ok(Self::UInt(v)),
|
||||
Err(named) => named,
|
||||
|
@ -1784,7 +1916,7 @@ pub(crate) mod known_items {
|
|||
|
||||
#[allow(non_snake_case, dead_code)]
|
||||
pub(crate) fn $known_item(span: Span) -> $known_item {
|
||||
let segments = $known_item::PATH_SEGMENTS.iter()
|
||||
let segments = $known_item::PATH_SEGMENTS[0].iter()
|
||||
.copied()
|
||||
.map(|seg| PathSegment::from(Ident::new(seg, span)))
|
||||
.collect();
|
||||
|
@ -1810,20 +1942,21 @@ pub(crate) mod known_items {
|
|||
return Ok(Self { span: ident.span(), path });
|
||||
}
|
||||
}
|
||||
if path.segments.len() == Self::PATH_SEGMENTS.len()
|
||||
&& path
|
||||
.segments
|
||||
.iter()
|
||||
.zip(Self::PATH_SEGMENTS)
|
||||
.all(|(seg, expected)| {
|
||||
matches!(seg.arguments, PathArguments::None)
|
||||
&& seg.ident == *expected
|
||||
})
|
||||
{
|
||||
Ok(Self { span: path.segments.last().unwrap().ident.span(), path })
|
||||
} else {
|
||||
Err(path)
|
||||
for &path_segments in Self::PATH_SEGMENTS.iter() {
|
||||
if path.segments.len() == path_segments.len()
|
||||
&& path
|
||||
.segments
|
||||
.iter()
|
||||
.zip(path_segments)
|
||||
.all(|(seg, expected)| {
|
||||
matches!(seg.arguments, PathArguments::None)
|
||||
&& seg.ident == *expected
|
||||
})
|
||||
{
|
||||
return Ok(Self { span: path.segments.last().unwrap().ident.span(), path });
|
||||
}
|
||||
}
|
||||
Err(path)
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn parse_path_with_arguments(mut path: Path) -> Result<(Self, PathArguments), Path> {
|
||||
|
@ -1878,19 +2011,24 @@ pub(crate) mod known_items {
|
|||
}
|
||||
|
||||
macro_rules! impl_known_item {
|
||||
($([$(::$head:ident)*])? ::$next:ident $(::$tail:ident)+) => {
|
||||
impl_known_item!([$($(::$head)*)? ::$next] $(::$tail)+);
|
||||
};
|
||||
([$(::$seg:ident)+] ::$known_item:ident) => {
|
||||
($(#[alias = $(::$alias:ident)+])* [$(::$seg:ident)+] ::$known_item:ident) => {
|
||||
impl_known_item_body!($known_item);
|
||||
|
||||
impl $known_item {
|
||||
pub(crate) const PATH_SEGMENTS: &'static [&'static str] = &[
|
||||
$(stringify!($seg),)+
|
||||
stringify!($known_item),
|
||||
pub(crate) const PATH_SEGMENTS: &'static [&'static [&'static str]] = &[
|
||||
&[
|
||||
$(stringify!($seg),)+
|
||||
stringify!($known_item),
|
||||
],
|
||||
$(&[
|
||||
$(stringify!($alias),)+
|
||||
],)*
|
||||
];
|
||||
}
|
||||
};
|
||||
($(#[alias = $(::$alias:ident)+])* $([$(::$head:ident)*])? ::$next:ident $(::$tail:ident)+) => {
|
||||
impl_known_item!($(#[alias = $(::$alias)+])* [$($(::$head)*)? ::$next] $(::$tail)+);
|
||||
};
|
||||
}
|
||||
|
||||
impl_known_item!(::fayalite::array::Array);
|
||||
|
@ -1911,7 +2049,16 @@ pub(crate) mod known_items {
|
|||
impl_known_item!(::fayalite::ty::Type);
|
||||
impl_known_item!(::fayalite::ty::Type::MaskType);
|
||||
impl_known_item!(::fayalite::util::ConstUsize);
|
||||
impl_known_item!(::fayalite::__std::primitive::usize);
|
||||
impl_known_item!(
|
||||
#[alias = ::std::primitive::usize]
|
||||
#[alias = ::core::primitive::usize]
|
||||
::fayalite::__std::primitive::usize
|
||||
);
|
||||
impl_known_item!(
|
||||
#[alias = ::std::marker::PhantomData]
|
||||
#[alias = ::core::marker::PhantomData]
|
||||
::fayalite::__std::marker::PhantomData
|
||||
);
|
||||
}
|
||||
|
||||
macro_rules! impl_bounds {
|
||||
|
@ -3969,6 +4116,7 @@ impl MakeHdlTypeExpr for ParsedType {
|
|||
Self::NamedParam(v) => v.make_hdl_type_expr(context),
|
||||
Self::Tuple(v) => v.make_hdl_type_expr(context),
|
||||
Self::ConstUsize(v) => v.make_hdl_type_expr(context),
|
||||
Self::PhantomData(v) => v.make_hdl_type_expr(context),
|
||||
Self::Array(v) => v.make_hdl_type_expr(context),
|
||||
Self::UInt(v) => v.make_hdl_type_expr(context),
|
||||
Self::SInt(v) => v.make_hdl_type_expr(context),
|
||||
|
|
|
@ -446,3 +446,85 @@ impl_tuples! {
|
|||
{#[num = 11, field = field_11] v11: T11}
|
||||
]
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> Type for PhantomData<T> {
|
||||
type BaseType = Bundle;
|
||||
type MaskType = ();
|
||||
type MatchVariant = PhantomData<T>;
|
||||
type MatchActiveScope = ();
|
||||
type MatchVariantAndInactiveScope = MatchVariantWithoutScope<Self::MatchVariant>;
|
||||
type MatchVariantsIter = std::iter::Once<Self::MatchVariantAndInactiveScope>;
|
||||
fn match_variants(
|
||||
this: Expr<Self>,
|
||||
source_location: SourceLocation,
|
||||
) -> Self::MatchVariantsIter {
|
||||
let _ = this;
|
||||
let _ = source_location;
|
||||
std::iter::once(MatchVariantWithoutScope(PhantomData))
|
||||
}
|
||||
fn mask_type(&self) -> Self::MaskType {
|
||||
()
|
||||
}
|
||||
fn canonical(&self) -> CanonicalType {
|
||||
Bundle::new(self.fields()).canonical()
|
||||
}
|
||||
#[track_caller]
|
||||
fn from_canonical(canonical_type: CanonicalType) -> Self {
|
||||
let CanonicalType::Bundle(bundle) = canonical_type else {
|
||||
panic!("expected bundle");
|
||||
};
|
||||
assert!(
|
||||
bundle.fields().is_empty(),
|
||||
"bundle has wrong number of fields"
|
||||
);
|
||||
PhantomData
|
||||
}
|
||||
fn source_location() -> SourceLocation {
|
||||
SourceLocation::builtin()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PhantomDataBuilder<T: ?Sized + Send + Sync + 'static>(PhantomData<T>);
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> Default for PhantomDataBuilder<T> {
|
||||
fn default() -> Self {
|
||||
Self(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> ToExpr for PhantomDataBuilder<T> {
|
||||
type Type = PhantomData<T>;
|
||||
|
||||
fn to_expr(&self) -> Expr<Self::Type> {
|
||||
PhantomData.to_expr()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> BundleType for PhantomData<T> {
|
||||
type Builder = PhantomDataBuilder<T>;
|
||||
type FilledBuilder = PhantomDataBuilder<T>;
|
||||
fn fields(&self) -> Interned<[BundleField]> {
|
||||
Interned::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> TypeWithDeref for PhantomData<T> {
|
||||
fn expr_deref(_this: &Expr<Self>) -> &Self::MatchVariant {
|
||||
&PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> StaticType for PhantomData<T> {
|
||||
const TYPE: Self = PhantomData;
|
||||
const MASK_TYPE: Self::MaskType = ();
|
||||
const TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
|
||||
const MASK_TYPE_PROPERTIES: TypeProperties = <()>::TYPE_PROPERTIES;
|
||||
}
|
||||
|
||||
impl<T: ?Sized + Send + Sync + 'static> ToExpr for PhantomData<T> {
|
||||
type Type = PhantomData<T>;
|
||||
|
||||
fn to_expr(&self) -> Expr<Self::Type> {
|
||||
BundleLiteral::new(PhantomData, Interned::default()).to_expr()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
use fayalite::prelude::*;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[hdl(outline_generated)]
|
||||
pub struct S<T, Len: Size, T2> {
|
||||
|
@ -8,6 +9,8 @@ pub struct S<T, Len: Size, T2> {
|
|||
b: UInt<3>,
|
||||
pub(crate) c: ArrayType<UInt<1>, Len>,
|
||||
pub d: T2,
|
||||
pub e: PhantomData<T>,
|
||||
pub f: PhantomData<Len>,
|
||||
}
|
||||
|
||||
#[hdl(outline_generated)]
|
||||
|
|
Loading…
Reference in a new issue