This commit is contained in:
		
							parent
							
								
									76ea7f82c3
								
							
						
					
					
						commit
						2c1afd1cd6
					
				
					 3 changed files with 355 additions and 86 deletions
				
			
		|  | @ -11,8 +11,8 @@ use syn::{ | ||||||
|     AngleBracketedGenericArguments, Attribute, ConstParam, Expr, ExprIndex, ExprPath, ExprTuple, |     AngleBracketedGenericArguments, Attribute, ConstParam, Expr, ExprIndex, ExprPath, ExprTuple, | ||||||
|     Field, FieldMutability, Fields, FieldsNamed, FieldsUnnamed, GenericArgument, GenericParam, |     Field, FieldMutability, Fields, FieldsNamed, FieldsUnnamed, GenericArgument, GenericParam, | ||||||
|     Generics, Ident, ImplGenerics, Index, ItemStruct, Path, PathArguments, PathSegment, |     Generics, Ident, ImplGenerics, Index, ItemStruct, Path, PathArguments, PathSegment, | ||||||
|     PredicateType, Token, Turbofish, Type, TypeGenerics, TypeGroup, TypeParam, TypeParen, TypePath, |     PredicateType, QSelf, Token, Turbofish, Type, TypeGenerics, TypeGroup, TypeParam, TypeParen, | ||||||
|     TypeTuple, Visibility, WhereClause, WherePredicate, |     TypePath, TypeTuple, Visibility, WhereClause, WherePredicate, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| crate::options! { | crate::options! { | ||||||
|  | @ -1236,7 +1236,6 @@ impl ParseTypes<Path> for ParsedType { | ||||||
|                             parser |                             parser | ||||||
|                                 .errors |                                 .errors | ||||||
|                                 .error(ident, "constant provided when a type was expected"); |                                 .error(ident, "constant provided when a type was expected"); | ||||||
|                             todo!(); |  | ||||||
|                             return Err(ParseFailed); |                             return Err(ParseFailed); | ||||||
|                         } |                         } | ||||||
|                     }, |                     }, | ||||||
|  | @ -1524,6 +1523,7 @@ pub(crate) enum UnparsedGenericParam { | ||||||
|         ident: Ident, |         ident: Ident, | ||||||
|         colon_token: Token![:], |         colon_token: Token![:], | ||||||
|         bounds: ParsedBounds, |         bounds: ParsedBounds, | ||||||
|  |         mask_type_bounds: ParsedTypeBounds, | ||||||
|     }, |     }, | ||||||
|     Const { |     Const { | ||||||
|         attrs: Vec<Attribute>, |         attrs: Vec<Attribute>, | ||||||
|  | @ -1532,6 +1532,7 @@ pub(crate) enum UnparsedGenericParam { | ||||||
|         ident: Ident, |         ident: Ident, | ||||||
|         colon_token: Token![:], |         colon_token: Token![:], | ||||||
|         ty: ParsedConstGenericType, |         ty: ParsedConstGenericType, | ||||||
|  |         bounds: Option<ParsedConstParamWhereBounds>, | ||||||
|     }, |     }, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1595,6 +1596,20 @@ pub(crate) mod known_items { | ||||||
|                         Err(path) |                         Err(path) | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |                 #[allow(dead_code)] | ||||||
|  |                 pub(crate) fn parse_path_with_arguments(mut path: Path) -> Result<(Self, PathArguments), Path> { | ||||||
|  |                     let Some(last_segment) = path.segments.last_mut() else { | ||||||
|  |                         return Err(path); | ||||||
|  |                     }; | ||||||
|  |                     let arguments = std::mem::replace(&mut last_segment.arguments, PathArguments::None); | ||||||
|  |                     match Self::parse_path(path) { | ||||||
|  |                         Ok(retval) => Ok((retval, arguments)), | ||||||
|  |                         Err(mut path) => { | ||||||
|  |                             path.segments.last_mut().unwrap().arguments = arguments; | ||||||
|  |                             Err(path) | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             impl Parse for $known_item { |             impl Parse for $known_item { | ||||||
|  | @ -1664,6 +1679,7 @@ pub(crate) mod known_items { | ||||||
|     impl_known_item!(::fayalite::ty::CanonicalType); |     impl_known_item!(::fayalite::ty::CanonicalType); | ||||||
|     impl_known_item!(::fayalite::ty::StaticType); |     impl_known_item!(::fayalite::ty::StaticType); | ||||||
|     impl_known_item!(::fayalite::ty::Type); |     impl_known_item!(::fayalite::ty::Type); | ||||||
|  |     impl_known_item!(::fayalite::ty::Type::MaskType); | ||||||
|     impl_known_item!(::fayalite::util::ConstUsize); |     impl_known_item!(::fayalite::util::ConstUsize); | ||||||
|     impl_known_item!(::fayalite::__std::primitive::usize); |     impl_known_item!(::fayalite::__std::primitive::usize); | ||||||
| } | } | ||||||
|  | @ -1822,6 +1838,19 @@ macro_rules! impl_bounds { | ||||||
|                 Ok(retval) |                 Ok(retval) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         impl $struct_type { | ||||||
|  |             #[allow(dead_code)] | ||||||
|  |             $vis fn add_implied_bounds(&mut self) { | ||||||
|  |                 let orig_bounds = self.clone(); | ||||||
|  |                 self.extend( | ||||||
|  |                     self.clone() | ||||||
|  |                         .into_iter() | ||||||
|  |                         .map($enum_type::implied_bounds), | ||||||
|  |                 ); | ||||||
|  |                 self.extend([orig_bounds]); // keep spans of explicitly provided bounds
 | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1849,6 +1878,64 @@ impl_bounds! { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl From<ParsedTypeBound> for ParsedBound { | ||||||
|  |     fn from(value: ParsedTypeBound) -> Self { | ||||||
|  |         match value { | ||||||
|  |             ParsedTypeBound::BundleType(v) => ParsedBound::BundleType(v), | ||||||
|  |             ParsedTypeBound::EnumType(v) => ParsedBound::EnumType(v), | ||||||
|  |             ParsedTypeBound::IntType(v) => ParsedBound::IntType(v), | ||||||
|  |             ParsedTypeBound::StaticType(v) => ParsedBound::StaticType(v), | ||||||
|  |             ParsedTypeBound::Type(v) => ParsedBound::Type(v), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<ParsedTypeBounds> for ParsedBounds { | ||||||
|  |     fn from(value: ParsedTypeBounds) -> Self { | ||||||
|  |         let ParsedTypeBounds { | ||||||
|  |             BundleType, | ||||||
|  |             EnumType, | ||||||
|  |             IntType, | ||||||
|  |             StaticType, | ||||||
|  |             Type, | ||||||
|  |         } = value; | ||||||
|  |         Self { | ||||||
|  |             BundleType, | ||||||
|  |             EnumType, | ||||||
|  |             IntType, | ||||||
|  |             KnownSize: None, | ||||||
|  |             Size: None, | ||||||
|  |             StaticType, | ||||||
|  |             Type, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl ParsedTypeBound { | ||||||
|  |     fn implied_bounds(self) -> ParsedTypeBounds { | ||||||
|  |         let span = self.span(); | ||||||
|  |         match self { | ||||||
|  |             Self::BundleType(v) => ParsedTypeBounds::from_iter([ | ||||||
|  |                 ParsedTypeBound::from(v), | ||||||
|  |                 ParsedTypeBound::Type(known_items::Type(span)), | ||||||
|  |             ]), | ||||||
|  |             Self::EnumType(v) => ParsedTypeBounds::from_iter([ | ||||||
|  |                 ParsedTypeBound::from(v), | ||||||
|  |                 ParsedTypeBound::Type(known_items::Type(span)), | ||||||
|  |             ]), | ||||||
|  |             Self::IntType(v) => ParsedTypeBounds::from_iter([ | ||||||
|  |                 ParsedTypeBound::from(v), | ||||||
|  |                 ParsedTypeBound::Type(known_items::Type(span)), | ||||||
|  |             ]), | ||||||
|  |             Self::StaticType(v) => ParsedTypeBounds::from_iter([ | ||||||
|  |                 ParsedTypeBound::from(v), | ||||||
|  |                 ParsedTypeBound::Type(known_items::Type(span)), | ||||||
|  |             ]), | ||||||
|  |             Self::Type(v) => ParsedTypeBounds::from_iter([ParsedTypeBound::from(v)]), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl_bounds! { | impl_bounds! { | ||||||
|     #[struct = ParsedSizeTypeBounds] |     #[struct = ParsedSizeTypeBounds] | ||||||
|     pub(crate) enum ParsedSizeTypeBound { |     pub(crate) enum ParsedSizeTypeBound { | ||||||
|  | @ -1857,6 +1944,43 @@ impl_bounds! { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl From<ParsedSizeTypeBound> for ParsedBound { | ||||||
|  |     fn from(value: ParsedSizeTypeBound) -> Self { | ||||||
|  |         match value { | ||||||
|  |             ParsedSizeTypeBound::KnownSize(v) => ParsedBound::KnownSize(v), | ||||||
|  |             ParsedSizeTypeBound::Size(v) => ParsedBound::Size(v), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<ParsedSizeTypeBounds> for ParsedBounds { | ||||||
|  |     fn from(value: ParsedSizeTypeBounds) -> Self { | ||||||
|  |         let ParsedSizeTypeBounds { KnownSize, Size } = value; | ||||||
|  |         Self { | ||||||
|  |             BundleType: None, | ||||||
|  |             EnumType: None, | ||||||
|  |             IntType: None, | ||||||
|  |             KnownSize, | ||||||
|  |             Size, | ||||||
|  |             StaticType: None, | ||||||
|  |             Type: None, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl ParsedSizeTypeBound { | ||||||
|  |     fn implied_bounds(self) -> ParsedSizeTypeBounds { | ||||||
|  |         let span = self.span(); | ||||||
|  |         match self { | ||||||
|  |             Self::KnownSize(v) => ParsedSizeTypeBounds::from_iter([ | ||||||
|  |                 ParsedSizeTypeBound::from(v), | ||||||
|  |                 ParsedSizeTypeBound::Size(known_items::Size(span)), | ||||||
|  |             ]), | ||||||
|  |             Self::Size(v) => ParsedSizeTypeBounds::from_iter([ParsedSizeTypeBound::from(v)]), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[derive(Clone, Debug)] | #[derive(Clone, Debug)] | ||||||
| pub(crate) enum ParsedBoundsCategory { | pub(crate) enum ParsedBoundsCategory { | ||||||
|     Type(ParsedTypeBounds), |     Type(ParsedTypeBounds), | ||||||
|  | @ -1918,42 +2042,13 @@ impl ParsedBound { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     fn implied_bounds(self) -> ParsedBounds { |     fn implied_bounds(self) -> ParsedBounds { | ||||||
|         let span = self.span(); |         match self.categorize() { | ||||||
|         match self { |             ParsedBoundCategory::Type(v) => v.implied_bounds().into(), | ||||||
|             Self::BundleType(v) => ParsedBounds::from_iter([ |             ParsedBoundCategory::SizeType(v) => v.implied_bounds().into(), | ||||||
|                 ParsedBound::from(v), |  | ||||||
|                 ParsedBound::Type(known_items::Type(span)), |  | ||||||
|             ]), |  | ||||||
|             Self::EnumType(v) => ParsedBounds::from_iter([ |  | ||||||
|                 ParsedBound::from(v), |  | ||||||
|                 ParsedBound::Type(known_items::Type(span)), |  | ||||||
|             ]), |  | ||||||
|             Self::IntType(v) => ParsedBounds::from_iter([ |  | ||||||
|                 ParsedBound::from(v), |  | ||||||
|                 ParsedBound::Type(known_items::Type(span)), |  | ||||||
|             ]), |  | ||||||
|             Self::KnownSize(v) => ParsedBounds::from_iter([ |  | ||||||
|                 ParsedBound::from(v), |  | ||||||
|                 ParsedBound::Size(known_items::Size(span)), |  | ||||||
|             ]), |  | ||||||
|             Self::Size(v) => ParsedBounds::from_iter([ParsedBound::from(v)]), |  | ||||||
|             Self::StaticType(v) => ParsedBounds::from_iter([ |  | ||||||
|                 ParsedBound::from(v), |  | ||||||
|                 ParsedBound::Type(known_items::Type(span)), |  | ||||||
|             ]), |  | ||||||
|             Self::Type(v) => ParsedBounds::from_iter([ParsedBound::from(v)]), |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ParsedBounds { |  | ||||||
|     fn add_implied_bounds(&mut self) { |  | ||||||
|         let orig_bounds = self.clone(); |  | ||||||
|         self.extend(self.clone().into_iter().map(ParsedBound::implied_bounds)); |  | ||||||
|         self.extend([orig_bounds]); // keep spans of explicitly provided bounds
 |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug, Clone)] | #[derive(Debug, Clone)] | ||||||
| pub(crate) struct ParsedTypeParam { | pub(crate) struct ParsedTypeParam { | ||||||
|     pub(crate) attrs: Vec<Attribute>, |     pub(crate) attrs: Vec<Attribute>, | ||||||
|  | @ -2116,6 +2211,7 @@ impl ParsedGenerics { | ||||||
|                 } |                 } | ||||||
|                 ParsedGenericParam::Const(ParsedConstParam { ident, bounds, .. }) => { |                 ParsedGenericParam::Const(ParsedConstParam { ident, bounds, .. }) => { | ||||||
|                     bounds |                     bounds | ||||||
|  |                         .bounds | ||||||
|                         .KnownSize |                         .KnownSize | ||||||
|                         .get_or_insert_with(|| known_items::KnownSize(ident.span())); |                         .get_or_insert_with(|| known_items::KnownSize(ident.span())); | ||||||
|                 } |                 } | ||||||
|  | @ -2527,6 +2623,7 @@ impl ParsedGenerics { | ||||||
|                             ident: ident.clone(), |                             ident: ident.clone(), | ||||||
|                             colon_token, |                             colon_token, | ||||||
|                             bounds: ParsedBounds::default(), |                             bounds: ParsedBounds::default(), | ||||||
|  |                             mask_type_bounds: ParsedTypeBounds::default(), | ||||||
|                         }, |                         }, | ||||||
|                         LateParsedParam { |                         LateParsedParam { | ||||||
|                             default: default |                             default: default | ||||||
|  | @ -2563,6 +2660,7 @@ impl ParsedGenerics { | ||||||
|                             ident: ident.clone(), |                             ident: ident.clone(), | ||||||
|                             colon_token: *colon_token, |                             colon_token: *colon_token, | ||||||
|                             ty: ParsedConstGenericType::Usize(known_items::usize(ident.span())), |                             ty: ParsedConstGenericType::Usize(known_items::usize(ident.span())), | ||||||
|  |                             bounds: None, | ||||||
|                         }, |                         }, | ||||||
|                         LateParsedParam { |                         LateParsedParam { | ||||||
|                             default: None, |                             default: None, | ||||||
|  | @ -2591,20 +2689,139 @@ impl ParsedGenerics { | ||||||
|                 lifetimes: None, |                 lifetimes: None, | ||||||
|                 bounded_ty: |                 bounded_ty: | ||||||
|                     Type::Path(TypePath { |                     Type::Path(TypePath { | ||||||
|                         qself: None, |                         qself, | ||||||
|                         path: bounded_ty, |                         path: bounded_ty, | ||||||
|                     }), |                     }), | ||||||
|                 colon_token: _, |                 colon_token, | ||||||
|                 bounds: unparsed_bounds, |                 bounds: unparsed_bounds, | ||||||
|             }) = predicate |             }) = predicate | ||||||
|             else { |             else { | ||||||
|                 errors.error(predicate, "unsupported where predicate kind"); |                 errors.error(predicate, "unsupported where predicate kind"); | ||||||
|                 continue; |                 continue; | ||||||
|             }; |             }; | ||||||
|             ParsedTypeNamed { |             if let Some(qself) = &qself { | ||||||
|                 path: todo!(), |                 if let QSelf { | ||||||
|                 args: todo!(), |                     lt_token: _, | ||||||
|             }; |                     ty: base_ty, | ||||||
|  |                     position: 3, | ||||||
|  |                     as_token: Some(_), | ||||||
|  |                     gt_token: _, | ||||||
|  |                 } = qself | ||||||
|  |                 { | ||||||
|  |                     if bounded_ty.segments.len() == 4 && unparsed_bounds.len() == 1 { | ||||||
|  |                         if let ( | ||||||
|  |                             Ok(_), | ||||||
|  |                             Type::Path(TypePath { | ||||||
|  |                                 qself: None, | ||||||
|  |                                 path: base_ty, | ||||||
|  |                             }), | ||||||
|  |                         ) = ( | ||||||
|  |                             known_items::MaskType::parse_path(bounded_ty.clone()), | ||||||
|  |                             &**base_ty, | ||||||
|  |                         ) { | ||||||
|  |                             let Some(&index) = base_ty | ||||||
|  |                                 .get_ident() | ||||||
|  |                                 .and_then(|base_ty| param_name_to_index_map.get(base_ty)) | ||||||
|  |                             else { | ||||||
|  |                                 errors.error( | ||||||
|  |                                     TypePath { | ||||||
|  |                                         qself: Some(qself.clone()), | ||||||
|  |                                         path: bounded_ty, | ||||||
|  |                                     }, | ||||||
|  |                                     "unsupported where predicate kind", | ||||||
|  |                                 ); | ||||||
|  |                                 continue; | ||||||
|  |                             }; | ||||||
|  |                             let parsed_bounds = match &mut unparsed_params[index] { | ||||||
|  |                                 UnparsedGenericParam::Type { | ||||||
|  |                                     mask_type_bounds, .. | ||||||
|  |                                 } => mask_type_bounds, | ||||||
|  |                                 UnparsedGenericParam::Const { ident, .. } => { | ||||||
|  |                                     errors.error( | ||||||
|  |                                         bounded_ty, | ||||||
|  |                                         format_args!( | ||||||
|  |                                             "expected type, found const parameter `{ident}`" | ||||||
|  |                                         ), | ||||||
|  |                                     ); | ||||||
|  |                                     continue; | ||||||
|  |                                 } | ||||||
|  |                             }; | ||||||
|  |                             parsed_bounds.extend(errors.ok(syn::parse2::<ParsedTypeBounds>( | ||||||
|  |                                 unparsed_bounds.to_token_stream(), | ||||||
|  |                             ))); | ||||||
|  |                             continue; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 errors.error( | ||||||
|  |                     TypePath { | ||||||
|  |                         qself: Some(qself.clone()), | ||||||
|  |                         path: bounded_ty, | ||||||
|  |                     }, | ||||||
|  |                     "unsupported where predicate kind", | ||||||
|  |                 ); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             if let Ok(( | ||||||
|  |                 const_usize, | ||||||
|  |                 PathArguments::AngleBracketed(AngleBracketedGenericArguments { | ||||||
|  |                     colon2_token: _, | ||||||
|  |                     lt_token, | ||||||
|  |                     args, | ||||||
|  |                     gt_token, | ||||||
|  |                 }), | ||||||
|  |             )) = known_items::ConstUsize::parse_path_with_arguments(bounded_ty.clone()) | ||||||
|  |             { | ||||||
|  |                 if args.len() != 1 { | ||||||
|  |                     errors.error(const_usize, "ConstUsize must have one argument"); | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 let GenericArgument::Type(Type::Path(TypePath { | ||||||
|  |                     qself: None, | ||||||
|  |                     path: arg, | ||||||
|  |                 })) = &args[0] | ||||||
|  |                 else { | ||||||
|  |                     errors.error( | ||||||
|  |                         const_usize, | ||||||
|  |                         "the only supported ConstUsize argument is a const generic parameter", | ||||||
|  |                     ); | ||||||
|  |                     continue; | ||||||
|  |                 }; | ||||||
|  |                 let arg = arg.get_ident(); | ||||||
|  |                 let Some((arg, &index)) = | ||||||
|  |                     arg.and_then(|arg| Some((arg, param_name_to_index_map.get(arg)?))) | ||||||
|  |                 else { | ||||||
|  |                     errors.error( | ||||||
|  |                         const_usize, | ||||||
|  |                         "the only supported ConstUsize argument is a const generic parameter", | ||||||
|  |                     ); | ||||||
|  |                     continue; | ||||||
|  |                 }; | ||||||
|  |                 let parsed_bounds = match &mut unparsed_params[index] { | ||||||
|  |                     UnparsedGenericParam::Const { bounds, .. } => bounds, | ||||||
|  |                     UnparsedGenericParam::Type { ident, .. } => { | ||||||
|  |                         errors.error( | ||||||
|  |                             bounded_ty, | ||||||
|  |                             format_args!("expected const generic parameter, found type `{ident}`"), | ||||||
|  |                         ); | ||||||
|  |                         continue; | ||||||
|  |                     } | ||||||
|  |                 }; | ||||||
|  |                 parsed_bounds | ||||||
|  |                     .get_or_insert_with(|| ParsedConstParamWhereBounds { | ||||||
|  |                         const_usize, | ||||||
|  |                         lt_token, | ||||||
|  |                         ident: arg.clone(), | ||||||
|  |                         gt_token, | ||||||
|  |                         colon_token, | ||||||
|  |                         bounds: ParsedSizeTypeBounds::default(), | ||||||
|  |                     }) | ||||||
|  |                     .bounds | ||||||
|  |                     .extend(errors.ok(syn::parse2::<ParsedSizeTypeBounds>( | ||||||
|  |                         unparsed_bounds.to_token_stream(), | ||||||
|  |                     ))); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|             let Some(&index) = bounded_ty |             let Some(&index) = bounded_ty | ||||||
|                 .get_ident() |                 .get_ident() | ||||||
|                 .and_then(|bounded_ty| param_name_to_index_map.get(bounded_ty)) |                 .and_then(|bounded_ty| param_name_to_index_map.get(bounded_ty)) | ||||||
|  | @ -2639,7 +2856,26 @@ impl ParsedGenerics { | ||||||
|                         ident, |                         ident, | ||||||
|                         colon_token, |                         colon_token, | ||||||
|                         mut bounds, |                         mut bounds, | ||||||
|  |                         mask_type_bounds, | ||||||
|                     } => { |                     } => { | ||||||
|  |                         for bound in mask_type_bounds { | ||||||
|  |                             bounds | ||||||
|  |                                 .Type | ||||||
|  |                                 .get_or_insert_with(|| known_items::Type(bound.span())); | ||||||
|  |                             match bound { | ||||||
|  |                                 ParsedTypeBound::BundleType(_) | ||||||
|  |                                 | ParsedTypeBound::EnumType(_) | ||||||
|  |                                 | ParsedTypeBound::IntType(_) => { | ||||||
|  |                                     errors.error(bound, "bound on mask type not implemented"); | ||||||
|  |                                 } | ||||||
|  |                                 ParsedTypeBound::StaticType(bound) => { | ||||||
|  |                                     if bounds.StaticType.is_none() { | ||||||
|  |                                         errors.error(bound, "StaticType bound on mask type without corresponding StaticType bound on original type is not implemented"); | ||||||
|  |                                     } | ||||||
|  |                                 }, | ||||||
|  |                                 ParsedTypeBound::Type(_) => {} | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|                         bounds.add_implied_bounds(); |                         bounds.add_implied_bounds(); | ||||||
|                         match bounds.categorize(&mut errors, ident.span()) { |                         match bounds.categorize(&mut errors, ident.span()) { | ||||||
|                             ParsedBoundsCategory::Type(bounds) => { |                             ParsedBoundsCategory::Type(bounds) => { | ||||||
|  | @ -2671,18 +2907,35 @@ impl ParsedGenerics { | ||||||
|                         ident, |                         ident, | ||||||
|                         colon_token, |                         colon_token, | ||||||
|                         ty, |                         ty, | ||||||
|                     } => ParsedGenericParam::Const(ParsedConstParam { |                         bounds, | ||||||
|                         bounds: ParsedSizeTypeBounds { |                     } => { | ||||||
|                             KnownSize: None, |                         let span = ident.span(); | ||||||
|                             Size: Some(known_items::Size(ident.span())), |                         let mut bounds = bounds.unwrap_or_else(|| ParsedConstParamWhereBounds { | ||||||
|                         }, |                             const_usize: known_items::ConstUsize(span), | ||||||
|                         attrs, |                             lt_token: Token, | ||||||
|                         options, |                             ident: ident.clone(), | ||||||
|                         const_token, |                             gt_token: Token, | ||||||
|                         ident, |                             colon_token: Token, | ||||||
|                         colon_token, |                             bounds: ParsedSizeTypeBounds { | ||||||
|                         ty, |                                 KnownSize: None, | ||||||
|                     }), |                                 Size: Some(known_items::Size(span)), | ||||||
|  |                             }, | ||||||
|  |                         }); | ||||||
|  |                         bounds | ||||||
|  |                             .bounds | ||||||
|  |                             .Size | ||||||
|  |                             .get_or_insert_with(|| known_items::Size(span)); | ||||||
|  |                         bounds.bounds.add_implied_bounds(); | ||||||
|  |                         ParsedGenericParam::Const(ParsedConstParam { | ||||||
|  |                             bounds, | ||||||
|  |                             attrs, | ||||||
|  |                             options, | ||||||
|  |                             const_token, | ||||||
|  |                             ident, | ||||||
|  |                             colon_token, | ||||||
|  |                             ty, | ||||||
|  |                         }) | ||||||
|  |                     } | ||||||
|                 }, |                 }, | ||||||
|             )); |             )); | ||||||
|         let mut retval = Self { |         let mut retval = Self { | ||||||
|  |  | ||||||
|  | @ -66,8 +66,8 @@ pub(crate) struct ModuleFn { | ||||||
|     vis: Visibility, |     vis: Visibility, | ||||||
|     sig: Signature, |     sig: Signature, | ||||||
|     block: Box<Block>, |     block: Box<Block>, | ||||||
|     io: Vec<ModuleIO>, |  | ||||||
|     struct_generics: ParsedGenerics, |     struct_generics: ParsedGenerics, | ||||||
|  |     the_struct: TokenStream, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | ||||||
|  | @ -224,6 +224,41 @@ impl Parse for ModuleFn { | ||||||
|         errors.finish()?; |         errors.finish()?; | ||||||
|         let struct_generics = struct_generics.unwrap(); |         let struct_generics = struct_generics.unwrap(); | ||||||
|         let (block, io) = body_results.unwrap(); |         let (block, io) = body_results.unwrap(); | ||||||
|  |         let (_struct_impl_generics, _struct_type_generics, struct_where_clause) = | ||||||
|  |             struct_generics.split_for_impl(); | ||||||
|  |         let struct_where_clause: Option<WhereClause> = parse_quote! { #struct_where_clause }; | ||||||
|  |         if let Some(struct_where_clause) = &struct_where_clause { | ||||||
|  |             sig.generics | ||||||
|  |                 .where_clause | ||||||
|  |                 .get_or_insert_with(|| WhereClause { | ||||||
|  |                     where_token: struct_where_clause.where_token, | ||||||
|  |                     predicates: Default::default(), | ||||||
|  |                 }) | ||||||
|  |                 .predicates | ||||||
|  |                 .extend(struct_where_clause.predicates.clone()); | ||||||
|  |         } | ||||||
|  |         let fn_name = &sig.ident; | ||||||
|  |         let io_flips = io | ||||||
|  |             .iter() | ||||||
|  |             .map(|io| match io.kind.kind { | ||||||
|  |                 ModuleIOKind::Input((input,)) => quote_spanned! {input.span=> | ||||||
|  |                     #[hdl(flip)] | ||||||
|  |                 }, | ||||||
|  |                 ModuleIOKind::Output(_) => quote! {}, | ||||||
|  |             }) | ||||||
|  |             .collect::<Vec<_>>(); | ||||||
|  |         let io_types = io.iter().map(|io| &io.kind.ty).collect::<Vec<_>>(); | ||||||
|  |         let io_names = io.iter().map(|io| &io.name).collect::<Vec<_>>(); | ||||||
|  |         let the_struct: ItemStruct = parse_quote! { | ||||||
|  |             #[allow(non_camel_case_types)] | ||||||
|  |             #[hdl(no_runtime_generics, no_static)] | ||||||
|  |             #vis struct #fn_name #struct_generics #struct_where_clause { | ||||||
|  |                 #( | ||||||
|  |                 #io_flips | ||||||
|  |                 #vis #io_names: #io_types,)* | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |         let the_struct = crate::hdl_bundle::hdl_bundle(the_struct)?; | ||||||
|         Ok(Self { |         Ok(Self { | ||||||
|             attrs, |             attrs, | ||||||
|             config_options, |             config_options, | ||||||
|  | @ -231,8 +266,8 @@ impl Parse for ModuleFn { | ||||||
|             vis, |             vis, | ||||||
|             sig, |             sig, | ||||||
|             block, |             block, | ||||||
|             io, |  | ||||||
|             struct_generics, |             struct_generics, | ||||||
|  |             the_struct, | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -246,8 +281,8 @@ impl ModuleFn { | ||||||
|             vis, |             vis, | ||||||
|             sig, |             sig, | ||||||
|             block, |             block, | ||||||
|             io, |  | ||||||
|             struct_generics, |             struct_generics, | ||||||
|  |             the_struct, | ||||||
|         } = self; |         } = self; | ||||||
|         let ConfigOptions { |         let ConfigOptions { | ||||||
|             outline_generated: _, |             outline_generated: _, | ||||||
|  | @ -279,7 +314,7 @@ impl ModuleFn { | ||||||
|             ModuleKind::Normal => quote! { ::fayalite::module::ModuleKind::Normal }, |             ModuleKind::Normal => quote! { ::fayalite::module::ModuleKind::Normal }, | ||||||
|         }; |         }; | ||||||
|         let fn_name = &outer_sig.ident; |         let fn_name = &outer_sig.ident; | ||||||
|         let (_struct_impl_generics, struct_type_generics, struct_where_clause) = |         let (_struct_impl_generics, struct_type_generics, _struct_where_clause) = | ||||||
|             struct_generics.split_for_impl(); |             struct_generics.split_for_impl(); | ||||||
|         let struct_ty = quote! {#fn_name #struct_type_generics}; |         let struct_ty = quote! {#fn_name #struct_type_generics}; | ||||||
|         body_sig.ident = parse_quote! {__body}; |         body_sig.ident = parse_quote! {__body}; | ||||||
|  | @ -294,17 +329,6 @@ impl ModuleFn { | ||||||
|         }; |         }; | ||||||
|         outer_sig.output = |         outer_sig.output = | ||||||
|             parse_quote! {-> ::fayalite::intern::Interned<::fayalite::module::Module<#struct_ty>>}; |             parse_quote! {-> ::fayalite::intern::Interned<::fayalite::module::Module<#struct_ty>>}; | ||||||
|         let io_flips = io |  | ||||||
|             .iter() |  | ||||||
|             .map(|io| match io.kind.kind { |  | ||||||
|                 ModuleIOKind::Input((input,)) => quote_spanned! {input.span=> |  | ||||||
|                     #[hdl(flip)] |  | ||||||
|                 }, |  | ||||||
|                 ModuleIOKind::Output(_) => quote! {}, |  | ||||||
|             }) |  | ||||||
|             .collect::<Vec<_>>(); |  | ||||||
|         let io_types = io.iter().map(|io| &io.kind.ty).collect::<Vec<_>>(); |  | ||||||
|         let io_names = io.iter().map(|io| &io.name).collect::<Vec<_>>(); |  | ||||||
|         let fn_name_str = fn_name.to_string(); |         let fn_name_str = fn_name.to_string(); | ||||||
|         let (_, body_type_generics, _) = body_fn.sig.generics.split_for_impl(); |         let (_, body_type_generics, _) = body_fn.sig.generics.split_for_impl(); | ||||||
|         let body_turbofish_type_generics = body_type_generics.as_turbofish(); |         let body_turbofish_type_generics = body_type_generics.as_turbofish(); | ||||||
|  | @ -316,15 +340,6 @@ impl ModuleFn { | ||||||
|                 |m| __body #body_turbofish_type_generics(m, #(#param_names,)*), |                 |m| __body #body_turbofish_type_generics(m, #(#param_names,)*), | ||||||
|             ) |             ) | ||||||
|         }}; |         }}; | ||||||
|         let the_struct: ItemStruct = parse_quote! { |  | ||||||
|             #[allow(non_camel_case_types)] |  | ||||||
|             #[hdl(no_runtime_generics, no_static)] |  | ||||||
|             #vis struct #fn_name #struct_generics #struct_where_clause { |  | ||||||
|                 #( |  | ||||||
|                 #io_flips |  | ||||||
|                 #vis #io_names: #io_types,)* |  | ||||||
|             } |  | ||||||
|         }; |  | ||||||
|         let outer_fn = ItemFn { |         let outer_fn = ItemFn { | ||||||
|             attrs, |             attrs, | ||||||
|             vis, |             vis, | ||||||
|  | @ -332,7 +347,7 @@ impl ModuleFn { | ||||||
|             block, |             block, | ||||||
|         }; |         }; | ||||||
|         let mut retval = outer_fn.into_token_stream(); |         let mut retval = outer_fn.into_token_stream(); | ||||||
|         retval.extend(crate::hdl_bundle::hdl_bundle(the_struct).unwrap()); |         retval.extend(the_struct); | ||||||
|         retval |         retval | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ use fayalite::{ | ||||||
|     intern::Intern, |     intern::Intern, | ||||||
|     module::transform::simplify_enums::{simplify_enums, SimplifyEnumsKind}, |     module::transform::simplify_enums::{simplify_enums, SimplifyEnumsKind}, | ||||||
|     prelude::*, |     prelude::*, | ||||||
|  |     ty::StaticType, | ||||||
| }; | }; | ||||||
| use serde_json::json; | use serde_json::json; | ||||||
| 
 | 
 | ||||||
|  | @ -133,9 +134,11 @@ circuit my_module: | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[cfg(todo)] |  | ||||||
| #[hdl_module(outline_generated)] | #[hdl_module(outline_generated)] | ||||||
| pub fn check_array_repeat<const N: usize>() { | pub fn check_array_repeat<const N: usize>() | ||||||
|  | where | ||||||
|  |     ConstUsize<N>: KnownSize, | ||||||
|  | { | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let i: UInt<8> = m.input(); |     let i: UInt<8> = m.input(); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|  | @ -147,7 +150,6 @@ pub fn check_array_repeat<const N: usize>() { | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[cfg(todo)] |  | ||||||
| #[test] | #[test] | ||||||
| fn test_array_repeat() { | fn test_array_repeat() { | ||||||
|     let _n = SourceLocation::normalize_files_for_tests(); |     let _n = SourceLocation::normalize_files_for_tests(); | ||||||
|  | @ -188,21 +190,21 @@ circuit check_array_repeat_1: | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[cfg(todo)] |  | ||||||
| #[hdl_module(outline_generated)] | #[hdl_module(outline_generated)] | ||||||
| pub fn check_skipped_generics<T, #[hdl(skip)] U, const N: usize, #[hdl(skip)] const M: usize>(v: U) | pub fn check_skipped_generics<T, #[hdl(skip)] U, const N: usize, #[hdl(skip)] const M: usize>(v: U) | ||||||
| where | where | ||||||
|     T: StaticValue, |     T: StaticType, | ||||||
|  |     ConstUsize<N>: KnownSize, | ||||||
|     U: std::fmt::Display, |     U: std::fmt::Display, | ||||||
| { | { | ||||||
|     dbg!(M); |     dbg!(M); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let i: T = m.input(); |     let i: T = m.input(); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let o: Array<[T; N]> = m.output(); |     let o: Array<T, N> = m.output(); | ||||||
|     let bytes = v.to_string().as_bytes().to_expr(); |     let bytes = v.to_string().as_bytes().to_expr(); | ||||||
|     #[hdl] |     #[hdl] | ||||||
|     let o2: Array<[UInt<8>]> = m.output(bytes.ty()); |     let o2: Array<UInt<8>> = m.output(Expr::ty(bytes)); | ||||||
|     connect( |     connect( | ||||||
|         o, |         o, | ||||||
|         #[hdl] |         #[hdl] | ||||||
|  | @ -211,7 +213,6 @@ where | ||||||
|     connect(o2, bytes); |     connect(o2, bytes); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[cfg(todo)] |  | ||||||
| #[test] | #[test] | ||||||
| fn test_skipped_generics() { | fn test_skipped_generics() { | ||||||
|     let _n = SourceLocation::normalize_files_for_tests(); |     let _n = SourceLocation::normalize_files_for_tests(); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue