8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use { Module , ModuleKind , NameBinding , NameBindingKind , Resolver , AmbiguityError } ;
11
+ use { AmbiguityError , Resolver , ResolutionError , resolve_error} ;
12
+ use { Module , ModuleKind , NameBinding , NameBindingKind , PathScope , PathResult } ;
12
13
use Namespace :: { self , MacroNS } ;
13
14
use build_reduced_graph:: BuildReducedGraphVisitor ;
14
15
use resolve_imports:: ImportResolver ;
@@ -25,6 +26,7 @@ use syntax::ext::base::{NormalTT, SyntaxExtension};
25
26
use syntax:: ext:: expand:: Expansion ;
26
27
use syntax:: ext:: hygiene:: Mark ;
27
28
use syntax:: ext:: tt:: macro_rules;
29
+ use syntax:: feature_gate:: { emit_feature_err, GateIssue } ;
28
30
use syntax:: fold:: Folder ;
29
31
use syntax:: ptr:: P ;
30
32
use syntax:: util:: lev_distance:: find_best_match_for_name;
@@ -193,7 +195,7 @@ impl<'a> base::Resolver for Resolver<'a> {
193
195
fn find_attr_invoc ( & mut self , attrs : & mut Vec < ast:: Attribute > ) -> Option < ast:: Attribute > {
194
196
for i in 0 ..attrs. len ( ) {
195
197
match self . builtin_macros . get ( & attrs[ i] . name ( ) ) . cloned ( ) {
196
- Some ( binding) => match * self . get_macro ( binding ) {
198
+ Some ( binding) => match * binding . get_macro ( self ) {
197
199
MultiModifier ( ..) | MultiDecorator ( ..) | SyntaxExtension :: AttrProcMacro ( ..) => {
198
200
return Some ( attrs. remove ( i) )
199
201
}
@@ -207,75 +209,103 @@ impl<'a> base::Resolver for Resolver<'a> {
207
209
208
210
fn resolve_macro ( & mut self , scope : Mark , path : & ast:: Path , force : bool )
209
211
-> Result < Rc < SyntaxExtension > , Determinacy > {
210
- if path. segments . len ( ) > 1 || path. global || !path. segments [ 0 ] . parameters . is_empty ( ) {
211
- self . session . span_err ( path. span , "expected macro name without module separators" ) ;
212
+ let ast:: Path { ref segments, global, span } = * path;
213
+ if segments. iter ( ) . any ( |segment| !segment. parameters . is_empty ( ) ) {
214
+ let kind =
215
+ if segments. last ( ) . unwrap ( ) . parameters . is_empty ( ) { "module" } else { "macro" } ;
216
+ let msg = format ! ( "type parameters are not allowed on {}s" , kind) ;
217
+ self . session . span_err ( path. span , & msg) ;
212
218
return Err ( Determinacy :: Determined ) ;
213
219
}
214
- let name = path. segments [ 0 ] . identifier . name ;
215
220
221
+ let path_scope = if global { PathScope :: Global } else { PathScope :: Lexical } ;
222
+ let path: Vec < _ > = segments. iter ( ) . map ( |seg| seg. identifier ) . collect ( ) ;
216
223
let invocation = self . invocations [ & scope] ;
217
224
self . current_module = invocation. module . get ( ) ;
225
+
226
+ if path. len ( ) > 1 || global {
227
+ if !self . use_extern_macros {
228
+ let msg = "non-ident macro paths are experimental" ;
229
+ let feature = "use_extern_macros" ;
230
+ emit_feature_err ( & self . session . parse_sess , feature, span, GateIssue :: Language , msg) ;
231
+ return Err ( Determinacy :: Determined ) ;
232
+ }
233
+
234
+ let ext = match self . resolve_path ( & path, path_scope, Some ( MacroNS ) , None ) {
235
+ PathResult :: NonModule ( path_res) => Ok ( self . get_macro ( path_res. base_def ) ) ,
236
+ PathResult :: Module ( ..) => unreachable ! ( ) ,
237
+ PathResult :: Indeterminate if !force => return Err ( Determinacy :: Undetermined ) ,
238
+ _ => Err ( Determinacy :: Determined ) ,
239
+ } ;
240
+ self . current_module . macro_resolutions . borrow_mut ( )
241
+ . push ( ( path. into_boxed_slice ( ) , path_scope, span) ) ;
242
+ return ext;
243
+ }
244
+
245
+ let name = path[ 0 ] . name ;
218
246
let result = match self . resolve_legacy_scope ( & invocation. legacy_scope , name, false ) {
219
247
Some ( MacroBinding :: Legacy ( binding) ) => Ok ( binding. ext . clone ( ) ) ,
220
- Some ( MacroBinding :: Modern ( binding) ) => Ok ( self . get_macro ( binding) ) ,
221
- None => match self . resolve_in_item_lexical_scope ( name, MacroNS , None ) {
222
- Some ( binding) => Ok ( self . get_macro ( binding) ) ,
223
- None => return Err ( if force {
248
+ Some ( MacroBinding :: Modern ( binding) ) => Ok ( binding. get_macro ( self ) ) ,
249
+ None => match self . resolve_lexical_macro_path_segment ( name, MacroNS , None ) {
250
+ Ok ( binding) => Ok ( binding. get_macro ( self ) ) ,
251
+ Err ( Determinacy :: Undetermined ) if !force => return Err ( Determinacy :: Undetermined ) ,
252
+ _ => {
224
253
let msg = format ! ( "macro undefined: '{}!'" , name) ;
225
- let mut err = self . session . struct_span_err ( path . span , & msg) ;
254
+ let mut err = self . session . struct_span_err ( span, & msg) ;
226
255
self . suggest_macro_name ( & name. as_str ( ) , & mut err) ;
227
256
err. emit ( ) ;
228
- Determinacy :: Determined
229
- } else {
230
- Determinacy :: Undetermined
231
- } ) ,
257
+ return Err ( Determinacy :: Determined ) ;
258
+ } ,
232
259
} ,
233
260
} ;
234
261
235
262
if self . use_extern_macros {
236
- self . current_module . legacy_macro_resolutions . borrow_mut ( )
237
- . push ( ( scope, name, path. span ) ) ;
263
+ self . current_module . legacy_macro_resolutions . borrow_mut ( ) . push ( ( scope, name, span) ) ;
238
264
}
239
265
result
240
266
}
241
267
}
242
268
243
269
impl < ' a > Resolver < ' a > {
244
- // Resolve the name in the module's lexical scope, excluding non-items.
245
- fn resolve_in_item_lexical_scope ( & mut self ,
246
- name : Name ,
247
- ns : Namespace ,
248
- record_used : Option < Span > )
249
- -> Option < & ' a NameBinding < ' a > > {
270
+ // Resolve the initial segment of a non-global macro path (e.g. `foo` in `foo::bar!();`)
271
+ pub fn resolve_lexical_macro_path_segment ( & mut self ,
272
+ name : Name ,
273
+ ns : Namespace ,
274
+ record_used : Option < Span > )
275
+ -> Result < & ' a NameBinding < ' a > , Determinacy > {
250
276
let mut module = self . current_module ;
251
- let mut potential_expanded_shadower = None ;
277
+ let mut potential_expanded_shadower: Option < & NameBinding > = None ;
252
278
loop {
253
279
// Since expanded macros may not shadow the lexical scope (enforced below),
254
280
// we can ignore unresolved invocations (indicated by the penultimate argument).
255
281
match self . resolve_name_in_module ( module, name, ns, true , record_used) {
256
282
Ok ( binding) => {
257
283
let span = match record_used {
258
284
Some ( span) => span,
259
- None => return Some ( binding) ,
285
+ None => return Ok ( binding) ,
260
286
} ;
261
- if let Some ( shadower ) = potential_expanded_shadower {
262
- self . ambiguity_errors . push ( AmbiguityError {
263
- span : span , name : name , b1 : shadower , b2 : binding , lexical : true ,
264
- } ) ;
265
- return Some ( shadower ) ;
266
- } else if binding . expansion == Mark :: root ( ) {
267
- return Some ( binding ) ;
268
- } else {
269
- potential_expanded_shadower = Some ( binding) ;
287
+ match potential_expanded_shadower {
288
+ Some ( shadower ) if shadower . def ( ) != binding . def ( ) => {
289
+ self . ambiguity_errors . push ( AmbiguityError {
290
+ span : span , name : name , b1 : shadower , b2 : binding , lexical : true ,
291
+ } ) ;
292
+ return Ok ( shadower ) ;
293
+ }
294
+ _ if binding . expansion == Mark :: root ( ) => return Ok ( binding ) ,
295
+ _ => potential_expanded_shadower = Some ( binding) ,
270
296
}
271
297
} ,
272
- Err ( Determinacy :: Undetermined ) => return None ,
298
+ Err ( Determinacy :: Undetermined ) => return Err ( Determinacy :: Undetermined ) ,
273
299
Err ( Determinacy :: Determined ) => { }
274
300
}
275
301
276
302
match module. kind {
277
303
ModuleKind :: Block ( ..) => module = module. parent . unwrap ( ) ,
278
- ModuleKind :: Def ( ..) => return potential_expanded_shadower,
304
+ ModuleKind :: Def ( ..) => return match potential_expanded_shadower {
305
+ Some ( binding) => Ok ( binding) ,
306
+ None if record_used. is_some ( ) => Err ( Determinacy :: Determined ) ,
307
+ None => Err ( Determinacy :: Undetermined ) ,
308
+ } ,
279
309
}
280
310
}
281
311
}
@@ -343,12 +373,22 @@ impl<'a> Resolver<'a> {
343
373
344
374
pub fn finalize_current_module_macro_resolutions ( & mut self ) {
345
375
let module = self . current_module ;
376
+ for & ( ref path, scope, span) in module. macro_resolutions . borrow ( ) . iter ( ) {
377
+ match self . resolve_path ( path, scope, Some ( MacroNS ) , Some ( span) ) {
378
+ PathResult :: NonModule ( _) => { } ,
379
+ PathResult :: Failed ( msg, _) => {
380
+ resolve_error ( self , span, ResolutionError :: FailedToResolve ( & msg) ) ;
381
+ }
382
+ _ => unreachable ! ( ) ,
383
+ }
384
+ }
385
+
346
386
for & ( mark, name, span) in module. legacy_macro_resolutions . borrow ( ) . iter ( ) {
347
387
let legacy_scope = & self . invocations [ & mark] . legacy_scope ;
348
388
let legacy_resolution = self . resolve_legacy_scope ( legacy_scope, name, true ) ;
349
- let resolution = self . resolve_in_item_lexical_scope ( name, MacroNS , Some ( span) ) ;
389
+ let resolution = self . resolve_lexical_macro_path_segment ( name, MacroNS , Some ( span) ) ;
350
390
let ( legacy_resolution, resolution) = match ( legacy_resolution, resolution) {
351
- ( Some ( legacy_resolution) , Some ( resolution) ) => ( legacy_resolution, resolution) ,
391
+ ( Some ( legacy_resolution) , Ok ( resolution) ) => ( legacy_resolution, resolution) ,
352
392
_ => continue ,
353
393
} ;
354
394
let ( legacy_span, participle) = match legacy_resolution {
0 commit comments