@@ -24,6 +24,7 @@ use syntax::attr;
2424use syntax:: errors:: DiagnosticBuilder ;
2525use syntax:: ext:: base:: { self , Determinacy , MultiModifier , MultiDecorator } ;
2626use syntax:: ext:: base:: { NormalTT , Resolver as SyntaxResolver , SyntaxExtension } ;
27+ use syntax:: ext:: base:: MacroKind ;
2728use syntax:: ext:: expand:: { Expansion , mark_tts} ;
2829use syntax:: ext:: hygiene:: Mark ;
2930use syntax:: ext:: tt:: macro_rules;
@@ -236,8 +237,8 @@ impl<'a> base::Resolver for Resolver<'a> {
236237 None
237238 }
238239
239- fn resolve_macro ( & mut self , scope : Mark , path : & ast:: Path , force : bool )
240- -> Result < Rc < SyntaxExtension > , Determinacy > {
240+ fn resolve_macro ( & mut self , scope : Mark , path : & ast:: Path , kind : MacroKind ,
241+ force : bool ) -> Result < Rc < SyntaxExtension > , Determinacy > {
241242 let ast:: Path { ref segments, span } = * path;
242243 if segments. iter ( ) . any ( |segment| segment. parameters . is_some ( ) ) {
243244 let kind =
@@ -256,6 +257,7 @@ impl<'a> base::Resolver for Resolver<'a> {
256257 let msg = "non-ident macro paths are experimental" ;
257258 let feature = "use_extern_macros" ;
258259 emit_feature_err ( & self . session . parse_sess , feature, span, GateIssue :: Language , msg) ;
260+ self . found_unresolved_macro = true ;
259261 return Err ( Determinacy :: Determined ) ;
260262 }
261263
@@ -266,7 +268,10 @@ impl<'a> base::Resolver for Resolver<'a> {
266268 } ,
267269 PathResult :: Module ( ..) => unreachable ! ( ) ,
268270 PathResult :: Indeterminate if !force => return Err ( Determinacy :: Undetermined ) ,
269- _ => Err ( Determinacy :: Determined ) ,
271+ _ => {
272+ self . found_unresolved_macro = true ;
273+ Err ( Determinacy :: Determined )
274+ } ,
270275 } ;
271276 self . current_module . macro_resolutions . borrow_mut ( )
272277 . push ( ( path. into_boxed_slice ( ) , span) ) ;
@@ -279,40 +284,19 @@ impl<'a> base::Resolver for Resolver<'a> {
279284 Some ( MacroBinding :: Modern ( binding) ) => Ok ( binding. get_macro ( self ) ) ,
280285 None => match self . resolve_lexical_macro_path_segment ( path[ 0 ] , MacroNS , None ) {
281286 Ok ( binding) => Ok ( binding. get_macro ( self ) ) ,
282- Err ( Determinacy :: Undetermined ) if !force => return Err ( Determinacy :: Undetermined ) ,
283- _ => {
284- let msg = format ! ( "macro undefined: `{}`" , name) ;
285- let mut err = self . session . struct_span_err ( span, & msg) ;
286- self . suggest_macro_name ( & name. as_str ( ) , & mut err) ;
287- err. emit ( ) ;
288- return Err ( Determinacy :: Determined ) ;
289- } ,
287+ Err ( Determinacy :: Undetermined ) if !force =>
288+ return Err ( Determinacy :: Undetermined ) ,
289+ Err ( _) => {
290+ self . found_unresolved_macro = true ;
291+ Err ( Determinacy :: Determined )
292+ }
290293 } ,
291294 } ;
292295
293- if self . use_extern_macros {
294- self . current_module . legacy_macro_resolutions . borrow_mut ( ) . push ( ( scope, path[ 0 ] , span) ) ;
295- }
296- result
297- }
296+ self . current_module . legacy_macro_resolutions . borrow_mut ( )
297+ . push ( ( scope, path[ 0 ] , span, kind) ) ;
298298
299- fn resolve_derive_macro ( & mut self , scope : Mark , path : & ast:: Path , force : bool )
300- -> Result < Rc < SyntaxExtension > , Determinacy > {
301- let ast:: Path { span, .. } = * path;
302- match self . resolve_macro ( scope, path, false ) {
303- Ok ( ext) => match * ext {
304- SyntaxExtension :: BuiltinDerive ( ..) |
305- SyntaxExtension :: ProcMacroDerive ( ..) => Ok ( ext) ,
306- _ => Err ( Determinacy :: Determined ) ,
307- } ,
308- Err ( Determinacy :: Undetermined ) if force => {
309- let msg = format ! ( "cannot find derive macro `{}` in this scope" , path) ;
310- let mut err = self . session . struct_span_err ( span, & msg) ;
311- err. emit ( ) ;
312- Err ( Determinacy :: Determined )
313- } ,
314- Err ( err) => Err ( err) ,
315- }
299+ result
316300 }
317301}
318302
@@ -438,37 +422,74 @@ impl<'a> Resolver<'a> {
438422 }
439423 }
440424
441- for & ( mark, ident, span) in module. legacy_macro_resolutions . borrow ( ) . iter ( ) {
425+ for & ( mark, ident, span, kind ) in module. legacy_macro_resolutions . borrow ( ) . iter ( ) {
442426 let legacy_scope = & self . invocations [ & mark] . legacy_scope ;
443427 let legacy_resolution = self . resolve_legacy_scope ( legacy_scope, ident. name , true ) ;
444428 let resolution = self . resolve_lexical_macro_path_segment ( ident, MacroNS , Some ( span) ) ;
445- let ( legacy_resolution, resolution) = match ( legacy_resolution, resolution) {
446- ( Some ( legacy_resolution) , Ok ( resolution) ) => ( legacy_resolution, resolution) ,
429+ match ( legacy_resolution, resolution) {
430+ ( Some ( legacy_resolution) , Ok ( resolution) ) => {
431+ let ( legacy_span, participle) = match legacy_resolution {
432+ MacroBinding :: Modern ( binding)
433+ if binding. def ( ) == resolution. def ( ) => continue ,
434+ MacroBinding :: Modern ( binding) => ( binding. span , "imported" ) ,
435+ MacroBinding :: Legacy ( binding) => ( binding. span , "defined" ) ,
436+ } ;
437+ let msg1 = format ! ( "`{}` could refer to the macro {} here" , ident, participle) ;
438+ let msg2 = format ! ( "`{}` could also refer to the macro imported here" , ident) ;
439+ self . session . struct_span_err ( span, & format ! ( "`{}` is ambiguous" , ident) )
440+ . span_note ( legacy_span, & msg1)
441+ . span_note ( resolution. span , & msg2)
442+ . emit ( ) ;
443+ } ,
447444 ( Some ( MacroBinding :: Modern ( binding) ) , Err ( _) ) => {
448445 self . record_use ( ident, MacroNS , binding, span) ;
449446 self . err_if_macro_use_proc_macro ( ident. name , span, binding) ;
450- continue
451447 } ,
452- _ => continue ,
453- } ;
454- let ( legacy_span, participle) = match legacy_resolution {
455- MacroBinding :: Modern ( binding) if binding. def ( ) == resolution. def ( ) => continue ,
456- MacroBinding :: Modern ( binding) => ( binding. span , "imported" ) ,
457- MacroBinding :: Legacy ( binding) => ( binding. span , "defined" ) ,
448+ ( None , Err ( _) ) => {
449+ let msg = match kind {
450+ MacroKind :: Bang =>
451+ format ! ( "cannot find macro `{}!` in this scope" , ident) ,
452+ MacroKind :: Attr =>
453+ format ! ( "cannot find attribute macro `{}` in this scope" , ident) ,
454+ MacroKind :: Derive =>
455+ format ! ( "cannot find derive macro `{}` in this scope" , ident) ,
456+ } ;
457+ let mut err = self . session . struct_span_err ( span, & msg) ;
458+ self . suggest_macro_name ( & ident. name . as_str ( ) , kind, & mut err) ;
459+ err. emit ( ) ;
460+ } ,
461+ _ => { } ,
458462 } ;
459- let msg1 = format ! ( "`{}` could refer to the macro {} here" , ident, participle) ;
460- let msg2 = format ! ( "`{}` could also refer to the macro imported here" , ident) ;
461- self . session . struct_span_err ( span, & format ! ( "`{}` is ambiguous" , ident) )
462- . span_note ( legacy_span, & msg1)
463- . span_note ( resolution. span , & msg2)
464- . emit ( ) ;
465463 }
466464 }
467465
468- fn suggest_macro_name ( & mut self , name : & str , err : & mut DiagnosticBuilder < ' a > ) {
469- if let Some ( suggestion) = find_best_match_for_name ( self . macro_names . iter ( ) , name, None ) {
466+ fn suggest_macro_name ( & mut self , name : & str , kind : MacroKind ,
467+ err : & mut DiagnosticBuilder < ' a > ) {
468+ let suggestion = match kind {
469+ MacroKind :: Bang =>
470+ find_best_match_for_name ( self . macro_names . iter ( ) , name, None ) ,
471+ MacroKind :: Attr |
472+ MacroKind :: Derive => {
473+ // Find a suggestion from the legacy namespace.
474+ // FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
475+ let builtin_macros = self . builtin_macros . clone ( ) ;
476+ let names = builtin_macros. iter ( ) . filter_map ( |( name, binding) | {
477+ if binding. get_macro ( self ) . kind ( ) == kind {
478+ Some ( name)
479+ } else {
480+ None
481+ }
482+ } ) ;
483+ find_best_match_for_name ( names, name, None )
484+ }
485+ } ;
486+ if let Some ( suggestion) = suggestion {
470487 if suggestion != name {
471- err. help ( & format ! ( "did you mean `{}!`?" , suggestion) ) ;
488+ if let MacroKind :: Bang = kind {
489+ err. help ( & format ! ( "did you mean `{}!`?" , suggestion) ) ;
490+ } else {
491+ err. help ( & format ! ( "did you mean `{}`?" , suggestion) ) ;
492+ }
472493 } else {
473494 err. help ( & format ! ( "have you added the `#[macro_use]` on the module/import?" ) ) ;
474495 }
0 commit comments