@@ -321,10 +321,18 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
321321
322322 fn resolve_invoc ( & mut self , invoc : & Invocation , scope : Mark , force : bool )
323323 -> Result < Option < Lrc < SyntaxExtension > > , Determinacy > {
324- let def = match invoc. kind {
325- InvocationKind :: Attr { attr : None , .. } => return Ok ( None ) ,
326- _ => self . resolve_invoc_to_def ( invoc, scope, force) ?,
324+ let ( path, macro_kind, derives_in_scope) = match invoc. kind {
325+ InvocationKind :: Attr { attr : None , .. } =>
326+ return Ok ( None ) ,
327+ InvocationKind :: Attr { attr : Some ( ref attr) , ref traits, .. } =>
328+ ( & attr. path , MacroKind :: Attr , & traits[ ..] ) ,
329+ InvocationKind :: Bang { ref mac, .. } =>
330+ ( & mac. node . path , MacroKind :: Bang , & [ ] [ ..] ) ,
331+ InvocationKind :: Derive { ref path, .. } =>
332+ ( path, MacroKind :: Derive , & [ ] [ ..] ) ,
327333 } ;
334+ let def = self . resolve_macro_to_def ( scope, path, macro_kind, derives_in_scope, force) ?;
335+
328336 if let Def :: Macro ( _, MacroKind :: ProcMacroStub ) = def {
329337 self . report_proc_macro_stub ( invoc. span ( ) ) ;
330338 return Err ( Determinacy :: Determined ) ;
@@ -396,7 +404,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
396404
397405 fn resolve_macro ( & mut self , scope : Mark , path : & ast:: Path , kind : MacroKind , force : bool )
398406 -> Result < Lrc < SyntaxExtension > , Determinacy > {
399- self . resolve_macro_to_def ( scope, path, kind, force) . and_then ( |def| {
407+ self . resolve_macro_to_def ( scope, path, kind, & [ ] , force) . and_then ( |def| {
400408 if let Def :: Macro ( _, MacroKind :: ProcMacroStub ) = def {
401409 self . report_proc_macro_stub ( path. span ) ;
402410 return Err ( Determinacy :: Determined ) ;
@@ -437,60 +445,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
437445 self . session . span_err ( span, & format ! ( "expected a macro, found {}" , def. kind_name( ) ) ) ;
438446 }
439447
440- fn resolve_invoc_to_def ( & mut self , invoc : & Invocation , scope : Mark , force : bool )
448+ fn resolve_macro_to_def ( & mut self , scope : Mark , path : & ast:: Path , kind : MacroKind ,
449+ derives_in_scope : & [ ast:: Path ] , force : bool )
441450 -> Result < Def , Determinacy > {
442- let ( attr, traits) = match invoc. kind {
443- InvocationKind :: Attr { ref attr, ref traits, .. } => ( attr, traits) ,
444- InvocationKind :: Bang { ref mac, .. } => {
445- return self . resolve_macro_to_def ( scope, & mac. node . path , MacroKind :: Bang , force) ;
446- }
447- InvocationKind :: Derive { ref path, .. } => {
448- return self . resolve_macro_to_def ( scope, path, MacroKind :: Derive , force) ;
449- }
450- } ;
451-
452- let path = attr. as_ref ( ) . unwrap ( ) . path . clone ( ) ;
453- let def = self . resolve_macro_to_def ( scope, & path, MacroKind :: Attr , force) ;
454- if let Ok ( Def :: NonMacroAttr ( NonMacroAttrKind :: Custom ) ) = def { } else {
455- return def;
456- }
457-
458- // At this point we've found that the `attr` is determinately unresolved and thus can be
459- // interpreted as a custom attribute. Normally custom attributes are feature gated, but
460- // it may be a custom attribute whitelisted by a derive macro and they do not require
461- // a feature gate.
462- //
463- // So here we look through all of the derive annotations in scope and try to resolve them.
464- // If they themselves successfully resolve *and* one of the resolved derive macros
465- // whitelists this attribute's name, then this is a registered attribute and we can convert
466- // it from a "generic custom attrite" into a "known derive helper attribute".
467- enum ConvertToDeriveHelper { Yes , No , DontKnow }
468- let mut convert_to_derive_helper = ConvertToDeriveHelper :: No ;
469- let attr_name = path. segments [ 0 ] . ident . name ;
470- for path in traits {
471- match self . resolve_macro ( scope, path, MacroKind :: Derive , force) {
472- Ok ( ext) => if let SyntaxExtension :: ProcMacroDerive ( _, ref inert_attrs, _) = * ext {
473- if inert_attrs. contains ( & attr_name) {
474- convert_to_derive_helper = ConvertToDeriveHelper :: Yes ;
475- break
476- }
477- } ,
478- Err ( Determinacy :: Undetermined ) =>
479- convert_to_derive_helper = ConvertToDeriveHelper :: DontKnow ,
480- Err ( Determinacy :: Determined ) => { }
481- }
482- }
483-
484- match convert_to_derive_helper {
485- ConvertToDeriveHelper :: Yes => Ok ( Def :: NonMacroAttr ( NonMacroAttrKind :: DeriveHelper ) ) ,
486- ConvertToDeriveHelper :: No => def,
487- ConvertToDeriveHelper :: DontKnow => Err ( Determinacy :: determined ( force) ) ,
488- }
489- }
490-
491- fn resolve_macro_to_def ( & mut self , scope : Mark , path : & ast:: Path , kind : MacroKind , force : bool )
492- -> Result < Def , Determinacy > {
493- let def = self . resolve_macro_to_def_inner ( scope, path, kind, force) ;
451+ let def = self . resolve_macro_to_def_inner ( scope, path, kind, derives_in_scope, force) ;
494452 if def != Err ( Determinacy :: Undetermined ) {
495453 // Do not report duplicated errors on every undetermined resolution.
496454 path. segments . iter ( ) . find ( |segment| segment. args . is_some ( ) ) . map ( |segment| {
@@ -514,9 +472,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
514472 def
515473 }
516474
517- pub fn resolve_macro_to_def_inner ( & mut self , scope : Mark , path : & ast:: Path ,
518- kind : MacroKind , force : bool )
519- -> Result < Def , Determinacy > {
475+ pub fn resolve_macro_to_def_inner ( & mut self , scope : Mark , path : & ast:: Path , kind : MacroKind ,
476+ derives_in_scope : & [ ast :: Path ] , force : bool )
477+ -> Result < Def , Determinacy > {
520478 let ast:: Path { ref segments, span } = * path;
521479 let mut path: Vec < _ > = segments. iter ( ) . map ( |seg| seg. ident ) . collect ( ) ;
522480 let invocation = self . invocations [ & scope] ;
@@ -575,7 +533,41 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
575533 self . current_module . nearest_item_scope ( ) . legacy_macro_resolutions . borrow_mut ( )
576534 . push ( ( scope, path[ 0 ] , kind, result. ok ( ) ) ) ;
577535
578- result
536+ if let Ok ( Def :: NonMacroAttr ( NonMacroAttrKind :: Custom ) ) = result { } else {
537+ return result;
538+ }
539+
540+ // At this point we've found that the `attr` is determinately unresolved and thus can be
541+ // interpreted as a custom attribute. Normally custom attributes are feature gated, but
542+ // it may be a custom attribute whitelisted by a derive macro and they do not require
543+ // a feature gate.
544+ //
545+ // So here we look through all of the derive annotations in scope and try to resolve them.
546+ // If they themselves successfully resolve *and* one of the resolved derive macros
547+ // whitelists this attribute's name, then this is a registered attribute and we can convert
548+ // it from a "generic custom attrite" into a "known derive helper attribute".
549+ assert ! ( kind == MacroKind :: Attr ) ;
550+ enum ConvertToDeriveHelper { Yes , No , DontKnow }
551+ let mut convert_to_derive_helper = ConvertToDeriveHelper :: No ;
552+ for derive in derives_in_scope {
553+ match self . resolve_macro ( scope, derive, MacroKind :: Derive , force) {
554+ Ok ( ext) => if let SyntaxExtension :: ProcMacroDerive ( _, ref inert_attrs, _) = * ext {
555+ if inert_attrs. contains ( & path[ 0 ] . name ) {
556+ convert_to_derive_helper = ConvertToDeriveHelper :: Yes ;
557+ break
558+ }
559+ } ,
560+ Err ( Determinacy :: Undetermined ) =>
561+ convert_to_derive_helper = ConvertToDeriveHelper :: DontKnow ,
562+ Err ( Determinacy :: Determined ) => { }
563+ }
564+ }
565+
566+ match convert_to_derive_helper {
567+ ConvertToDeriveHelper :: Yes => Ok ( Def :: NonMacroAttr ( NonMacroAttrKind :: DeriveHelper ) ) ,
568+ ConvertToDeriveHelper :: No => result,
569+ ConvertToDeriveHelper :: DontKnow => Err ( Determinacy :: determined ( force) ) ,
570+ }
579571 }
580572
581573 // Resolve the initial segment of a non-global macro path
0 commit comments