 705c144259
			
		
	
	
		705c144259
		
			
		
	
	
	
	
		
			
			# Objective Unblocks #11659. Currently the `Reflect` derive macro has to go through a merge process for each `#[reflect]`/`#[reflet_value]` attribute encountered on a container type. Not only is this a bit inefficient, but it also has a soft requirement that we can compare attributes such that an error can be thrown on duplicates, invalid states, etc. While working on #11659 this proved to be challenging due to the fact that `syn` types don't implement `PartialEq` or `Hash` without enabling the `extra-traits` feature. Ideally, we wouldn't have to enable another feature just to accommodate this one use case. ## Solution Removed `ContainerAttributes::merge`. This was a fairly simple change as we could just have the parsing functions take `&mut self` instead of returning `Self`. ## Testing CI should build as there should be no user-facing change.
		
			
				
	
	
		
			73 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			73 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use crate::container_attributes::ContainerAttributes;
 | |
| use crate::derive_data::ReflectTraitToImpl;
 | |
| use crate::type_path::CustomPathDef;
 | |
| use syn::parse::ParseStream;
 | |
| use syn::token::Paren;
 | |
| use syn::{parenthesized, Attribute, Generics, Path};
 | |
| 
 | |
| /// A struct used to define a simple reflected value type (such as primitives).
 | |
| ///
 | |
| ///
 | |
| ///
 | |
| /// This takes the form:
 | |
| ///
 | |
| /// ```ignore (Method expecting TokenStream is better represented with raw tokens)
 | |
| /// // Standard
 | |
| /// ::my_crate::foo::Bar(TraitA, TraitB)
 | |
| ///
 | |
| /// // With generics
 | |
| /// ::my_crate::foo::Bar<T1: Bar, T2>(TraitA, TraitB)
 | |
| ///
 | |
| /// // With generics and where clause
 | |
| /// ::my_crate::foo::Bar<T1, T2> where T1: Bar (TraitA, TraitB)
 | |
| ///
 | |
| /// // With a custom path (not with impl_from_reflect_value)
 | |
| /// (in my_crate::bar) Bar(TraitA, TraitB)
 | |
| /// ```
 | |
| pub(crate) struct ReflectValueDef {
 | |
|     #[allow(dead_code)]
 | |
|     pub attrs: Vec<Attribute>,
 | |
|     pub type_path: Path,
 | |
|     pub generics: Generics,
 | |
|     pub traits: Option<ContainerAttributes>,
 | |
|     pub custom_path: Option<CustomPathDef>,
 | |
| }
 | |
| 
 | |
| impl ReflectValueDef {
 | |
|     pub fn parse_reflect(input: ParseStream) -> syn::Result<Self> {
 | |
|         Self::parse(input, ReflectTraitToImpl::Reflect)
 | |
|     }
 | |
| 
 | |
|     pub fn parse_from_reflect(input: ParseStream) -> syn::Result<Self> {
 | |
|         Self::parse(input, ReflectTraitToImpl::FromReflect)
 | |
|     }
 | |
| 
 | |
|     fn parse(input: ParseStream, trait_: ReflectTraitToImpl) -> syn::Result<Self> {
 | |
|         let attrs = input.call(Attribute::parse_outer)?;
 | |
| 
 | |
|         let custom_path = CustomPathDef::parse_parenthesized(input)?;
 | |
| 
 | |
|         let type_path = Path::parse_mod_style(input)?;
 | |
|         let mut generics = input.parse::<Generics>()?;
 | |
|         generics.where_clause = input.parse()?;
 | |
| 
 | |
|         let mut traits = None;
 | |
|         if input.peek(Paren) {
 | |
|             let content;
 | |
|             parenthesized!(content in input);
 | |
|             traits = Some({
 | |
|                 let mut attrs = ContainerAttributes::default();
 | |
|                 attrs.parse_terminated(&content, trait_)?;
 | |
|                 attrs
 | |
|             });
 | |
|         }
 | |
|         Ok(ReflectValueDef {
 | |
|             attrs,
 | |
|             type_path,
 | |
|             generics,
 | |
|             traits,
 | |
|             custom_path,
 | |
|         })
 | |
|     }
 | |
| }
 |