@@ -7,15 +7,17 @@ use syn::{
77 parse:: { discouraged:: Speculative , Parse , ParseStream } ,
88 punctuated:: Punctuated ,
99 spanned:: Spanned ,
10- Attribute , BoundLifetimes , Data , Ident , Meta , PredicateType , Result , Token , Type , TypePath ,
11- WhereClause , WherePredicate ,
10+ Attribute , BoundLifetimes , Data , Ident , Meta , Path , PredicateType , Result , Token , Type ,
11+ TypePath , WhereClause , WherePredicate ,
1212} ;
1313
1414use crate :: { trait_:: DeriveTrait , Error , Incomparable , Item , Skip , SkipGroup , Trait , DERIVE_WHERE } ;
1515
1616/// Attributes on item.
1717#[ derive( Default ) ]
1818pub struct ItemAttr {
19+ /// Path to `derive_where` if set by `#[derive_where(crate = ...)]`.
20+ pub crate_ : Option < Path > ,
1921 /// [`Trait`]s to skip all fields for.
2022 pub skip_inner : Skip ,
2123 /// Comparing item will yield `false` for [`PartialEq`] and [`None`] for
@@ -59,28 +61,29 @@ impl ItemAttr {
5961 // Needs to be parsed after all traits are known.
6062 incomparables. push ( meta)
6163 } else if meta. path ( ) . is_ident ( "crate" ) {
62- // Do nothing, we checked this before
63- // already.
64+ let ( path, _) = super :: parse_crate ( meta)
65+ . expect ( "failed to parse previously parsed attribute" ) ;
66+ self_. crate_ = Some ( path) ;
6467 }
6568 // The list can have one item but still not be the `skip_inner`
6669 // attribute, continue with parsing `DeriveWhere`.
6770 else {
6871 self_
6972 . derive_wheres
70- . push ( DeriveWhere :: from_attr ( span, data, attr) ?) ;
73+ . push ( DeriveWhere :: from_attr ( attrs , span, data, attr) ?) ;
7174 }
7275 }
7376 _ => self_
7477 . derive_wheres
75- . push ( DeriveWhere :: from_attr ( span, data, attr) ?) ,
78+ . push ( DeriveWhere :: from_attr ( attrs , span, data, attr) ?) ,
7679 }
7780 }
7881 // Anything list that isn't using `,` as separator, is because we expect
7982 // `A, B; C`.
8083 else {
8184 self_
8285 . derive_wheres
83- . push ( DeriveWhere :: from_attr ( span, data, attr) ?)
86+ . push ( DeriveWhere :: from_attr ( attrs , span, data, attr) ?)
8487 }
8588 } else {
8689 return Err ( Error :: option_syntax ( attr. meta . span ( ) ) ) ;
@@ -93,6 +96,18 @@ impl ItemAttr {
9396 return Err ( Error :: none ( span) ) ;
9497 }
9598
99+ // Check for `#[serde(...)]` attributes without `De/Serialize`.
100+ #[ cfg( feature = "serde" ) ]
101+ if !self_. derive_wheres . iter ( ) . any ( |derive_where| {
102+ derive_where. contains ( Trait :: Deserialize ) | derive_where. contains ( Trait :: Serialize )
103+ } ) {
104+ for attr in attrs {
105+ if attr. path ( ) . is_ident ( "serde" ) {
106+ return Err ( Error :: serde_without_serde ( attr. span ( ) ) ) ;
107+ }
108+ }
109+ }
110+
96111 // Merge `DeriveWhere`s with the same bounds.
97112 self_
98113 . derive_wheres
@@ -152,7 +167,7 @@ pub struct DeriveWhere {
152167
153168impl DeriveWhere {
154169 /// Create [`DeriveWhere`] from [`Attribute`].
155- fn from_attr ( span : Span , data : & Data , attr : & Attribute ) -> Result < Self > {
170+ fn from_attr ( attrs : & [ Attribute ] , span : Span , data : & Data , attr : & Attribute ) -> Result < Self > {
156171 attr. parse_args_with ( |input : ParseStream | {
157172 // Parse the attribute input, this should either be:
158173 // - Comma separated traits.
@@ -169,7 +184,7 @@ impl DeriveWhere {
169184 // Start with parsing a trait.
170185 // Not checking for duplicates here, we do that after merging `derive_where`s
171186 // with the same bounds.
172- let ( span, trait_) = DeriveTrait :: from_stream ( span, data, input) ?;
187+ let ( span, trait_) = DeriveTrait :: from_stream ( attrs , span, data, input) ?;
173188 spans. push ( span) ;
174189 traits. push ( trait_) ;
175190
0 commit comments