@@ -28,9 +28,11 @@ use syntax::ext::placeholders::placeholder;
2828use syntax:: ext:: tt:: macro_rules;
2929use syntax:: feature_gate:: { self , emit_feature_err, GateIssue } ;
3030use syntax:: fold:: { self , Folder } ;
31+ use syntax:: parse:: parser:: PathStyle ;
32+ use syntax:: parse:: token:: { self , Token } ;
3133use syntax:: ptr:: P ;
3234use syntax:: symbol:: { Symbol , keywords} ;
33- use syntax:: tokenstream:: TokenStream ;
35+ use syntax:: tokenstream:: { TokenStream , TokenTree , Delimited } ;
3436use syntax:: util:: lev_distance:: find_best_match_for_name;
3537use syntax_pos:: { Span , DUMMY_SP } ;
3638
@@ -200,16 +202,22 @@ impl<'a> base::Resolver for Resolver<'a> {
200202 let name = unwrap_or ! ( attrs[ i] . name( ) , continue ) ;
201203
202204 if name == "derive" {
203- let mut traits = match attrs[ i] . meta_item_list ( ) {
204- Some ( traits) => traits,
205- _ => continue ,
205+ let result = attrs[ i] . parse_list ( & self . session . parse_sess ,
206+ |parser| parser. parse_path ( PathStyle :: Mod ) ) ;
207+ let mut traits = match result {
208+ Ok ( traits) => traits,
209+ Err ( mut e) => {
210+ e. cancel ( ) ;
211+ continue
212+ }
206213 } ;
207214
208215 for j in 0 ..traits. len ( ) {
209- let legacy_name = Symbol :: intern ( & match traits[ j] . word ( ) {
210- Some ( ..) => format ! ( "derive_{}" , traits[ j] . name( ) . unwrap( ) ) ,
211- None => continue ,
212- } ) ;
216+ if traits[ j] . segments . len ( ) > 1 {
217+ continue
218+ }
219+ let trait_name = traits[ j] . segments [ 0 ] . identifier . name ;
220+ let legacy_name = Symbol :: intern ( & format ! ( "derive_{}" , trait_name) ) ;
213221 if !self . builtin_macros . contains_key ( & legacy_name) {
214222 continue
215223 }
@@ -218,7 +226,23 @@ impl<'a> base::Resolver for Resolver<'a> {
218226 if traits. is_empty ( ) {
219227 attrs. remove ( i) ;
220228 } else {
221- attrs[ i] . tokens = ast:: MetaItemKind :: List ( traits) . tokens ( attrs[ i] . span ) ;
229+ let mut tokens = Vec :: new ( ) ;
230+ for ( i, path) in traits. iter ( ) . enumerate ( ) {
231+ if i > 0 {
232+ tokens. push ( TokenTree :: Token ( attrs[ i] . span , Token :: Comma ) . into ( ) ) ;
233+ }
234+ for ( j, segment) in path. segments . iter ( ) . enumerate ( ) {
235+ if j > 0 {
236+ tokens. push ( TokenTree :: Token ( path. span , Token :: ModSep ) . into ( ) ) ;
237+ }
238+ let tok = Token :: Ident ( segment. identifier ) ;
239+ tokens. push ( TokenTree :: Token ( path. span , tok) . into ( ) ) ;
240+ }
241+ }
242+ attrs[ i] . tokens = TokenTree :: Delimited ( attrs[ i] . span , Delimited {
243+ delim : token:: Paren ,
244+ tts : TokenStream :: concat ( tokens) . into ( ) ,
245+ } ) . into ( ) ;
222246 }
223247 return Some ( ast:: Attribute {
224248 path : ast:: Path :: from_ident ( span, Ident :: with_empty_ctxt ( legacy_name) ) ,
@@ -262,9 +286,8 @@ impl<'a> Resolver<'a> {
262286 InvocationKind :: Bang { ref mac, .. } => {
263287 return self . resolve_macro_to_def ( scope, & mac. node . path , MacroKind :: Bang , force) ;
264288 }
265- InvocationKind :: Derive { name, span, .. } => {
266- let path = ast:: Path :: from_ident ( span, Ident :: with_empty_ctxt ( name) ) ;
267- return self . resolve_macro_to_def ( scope, & path, MacroKind :: Derive , force) ;
289+ InvocationKind :: Derive { ref path, .. } => {
290+ return self . resolve_macro_to_def ( scope, path, MacroKind :: Derive , force) ;
268291 }
269292 } ;
270293
@@ -282,9 +305,8 @@ impl<'a> Resolver<'a> {
282305 1 => path. segments [ 0 ] . identifier . name ,
283306 _ => return Err ( determinacy) ,
284307 } ;
285- for & ( name, span) in traits {
286- let path = ast:: Path :: from_ident ( span, Ident :: with_empty_ctxt ( name) ) ;
287- match self . resolve_macro ( scope, & path, MacroKind :: Derive , force) {
308+ for path in traits {
309+ match self . resolve_macro ( scope, path, MacroKind :: Derive , force) {
288310 Ok ( ext) => if let SyntaxExtension :: ProcMacroDerive ( _, ref inert_attrs) = * ext {
289311 if inert_attrs. contains ( & attr_name) {
290312 // FIXME(jseyfried) Avoid `mem::replace` here.
@@ -327,7 +349,7 @@ impl<'a> Resolver<'a> {
327349 self . current_module = invocation. module . get ( ) ;
328350
329351 if path. len ( ) > 1 {
330- if !self . use_extern_macros {
352+ if !self . use_extern_macros && self . gated_errors . insert ( span ) {
331353 let msg = "non-ident macro paths are experimental" ;
332354 let feature = "use_extern_macros" ;
333355 emit_feature_err ( & self . session . parse_sess , feature, span, GateIssue :: Language , msg) ;
0 commit comments