@@ -28,9 +28,11 @@ use syntax::ext::placeholders::placeholder;
28
28
use syntax:: ext:: tt:: macro_rules;
29
29
use syntax:: feature_gate:: { self , emit_feature_err, GateIssue } ;
30
30
use syntax:: fold:: { self , Folder } ;
31
+ use syntax:: parse:: parser:: PathStyle ;
32
+ use syntax:: parse:: token:: { self , Token } ;
31
33
use syntax:: ptr:: P ;
32
34
use syntax:: symbol:: { Symbol , keywords} ;
33
- use syntax:: tokenstream:: TokenStream ;
35
+ use syntax:: tokenstream:: { TokenStream , TokenTree , Delimited } ;
34
36
use syntax:: util:: lev_distance:: find_best_match_for_name;
35
37
use syntax_pos:: { Span , DUMMY_SP } ;
36
38
@@ -200,16 +202,22 @@ impl<'a> base::Resolver for Resolver<'a> {
200
202
let name = unwrap_or ! ( attrs[ i] . name( ) , continue ) ;
201
203
202
204
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
+ }
206
213
} ;
207
214
208
215
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) ) ;
213
221
if !self . builtin_macros . contains_key ( & legacy_name) {
214
222
continue
215
223
}
@@ -218,7 +226,23 @@ impl<'a> base::Resolver for Resolver<'a> {
218
226
if traits. is_empty ( ) {
219
227
attrs. remove ( i) ;
220
228
} 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 ( ) ;
222
246
}
223
247
return Some ( ast:: Attribute {
224
248
path : ast:: Path :: from_ident ( span, Ident :: with_empty_ctxt ( legacy_name) ) ,
@@ -262,9 +286,8 @@ impl<'a> Resolver<'a> {
262
286
InvocationKind :: Bang { ref mac, .. } => {
263
287
return self . resolve_macro_to_def ( scope, & mac. node . path , MacroKind :: Bang , force) ;
264
288
}
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) ;
268
291
}
269
292
} ;
270
293
@@ -282,9 +305,8 @@ impl<'a> Resolver<'a> {
282
305
1 => path. segments [ 0 ] . identifier . name ,
283
306
_ => return Err ( determinacy) ,
284
307
} ;
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) {
288
310
Ok ( ext) => if let SyntaxExtension :: ProcMacroDerive ( _, ref inert_attrs) = * ext {
289
311
if inert_attrs. contains ( & attr_name) {
290
312
// FIXME(jseyfried) Avoid `mem::replace` here.
@@ -327,7 +349,7 @@ impl<'a> Resolver<'a> {
327
349
self . current_module = invocation. module . get ( ) ;
328
350
329
351
if path. len ( ) > 1 {
330
- if !self . use_extern_macros {
352
+ if !self . use_extern_macros && self . gated_errors . insert ( span ) {
331
353
let msg = "non-ident macro paths are experimental" ;
332
354
let feature = "use_extern_macros" ;
333
355
emit_feature_err ( & self . session . parse_sess , feature, span, GateIssue :: Language , msg) ;
0 commit comments