@@ -451,28 +451,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
451451 _ => unreachable ! ( ) ,
452452 } ;
453453 if !item. derive_allowed ( ) {
454- let attr = attr:: find_by_name ( item. attrs ( ) , sym:: derive)
455- . expect ( "`derive` attribute should exist" ) ;
456- let span = attr. span ;
457- let mut err = self . cx . struct_span_err (
458- span,
459- "`derive` may only be applied to structs, enums and unions" ,
460- ) ;
461- if let ast:: AttrStyle :: Inner = attr. style {
462- let trait_list = derives
463- . iter ( )
464- . map ( |t| pprust:: path_to_string ( t) )
465- . collect :: < Vec < _ > > ( ) ;
466- let suggestion = format ! ( "#[derive({})]" , trait_list. join( ", " ) ) ;
467- err. span_suggestion (
468- span,
469- "try an outer attribute" ,
470- suggestion,
471- // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
472- Applicability :: MaybeIncorrect ,
473- ) ;
474- }
475- err. emit ( ) ;
454+ self . error_derive_forbidden_on_non_adt ( & derives, & item) ;
476455 }
477456
478457 let mut item = self . fully_configure ( item) ;
@@ -521,6 +500,27 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
521500 fragment_with_placeholders
522501 }
523502
503+ fn error_derive_forbidden_on_non_adt ( & self , derives : & [ Path ] , item : & Annotatable ) {
504+ let attr =
505+ attr:: find_by_name ( item. attrs ( ) , sym:: derive) . expect ( "`derive` attribute should exist" ) ;
506+ let span = attr. span ;
507+ let mut err = self
508+ . cx
509+ . struct_span_err ( span, "`derive` may only be applied to structs, enums and unions" ) ;
510+ if let ast:: AttrStyle :: Inner = attr. style {
511+ let trait_list = derives. iter ( ) . map ( |t| pprust:: path_to_string ( t) ) . collect :: < Vec < _ > > ( ) ;
512+ let suggestion = format ! ( "#[derive({})]" , trait_list. join( ", " ) ) ;
513+ err. span_suggestion (
514+ span,
515+ "try an outer attribute" ,
516+ suggestion,
517+ // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
518+ Applicability :: MaybeIncorrect ,
519+ ) ;
520+ }
521+ err. emit ( ) ;
522+ }
523+
524524 fn resolve_imports ( & mut self ) {
525525 if self . monotonic {
526526 self . cx . resolver . resolve_imports ( ) ;
@@ -606,21 +606,38 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
606606 }
607607 }
608608
609- fn expand_invoc ( & mut self , invoc : Invocation , ext : & SyntaxExtensionKind ) -> AstFragment {
610- if self . cx . current_expansion . depth > self . cx . ecfg . recursion_limit {
611- let expn_data = self . cx . current_expansion . id . expn_data ( ) ;
612- let suggested_limit = self . cx . ecfg . recursion_limit * 2 ;
613- let mut err = self . cx . struct_span_err (
609+ fn error_recursion_limit_reached ( & mut self ) {
610+ let expn_data = self . cx . current_expansion . id . expn_data ( ) ;
611+ let suggested_limit = self . cx . ecfg . recursion_limit * 2 ;
612+ self . cx
613+ . struct_span_err (
614614 expn_data. call_site ,
615615 & format ! ( "recursion limit reached while expanding `{}`" , expn_data. kind. descr( ) ) ,
616- ) ;
617- err . help ( & format ! (
616+ )
617+ . help ( & format ! (
618618 "consider adding a `#![recursion_limit=\" {}\" ]` attribute to your crate (`{}`)" ,
619619 suggested_limit, self . cx. ecfg. crate_name,
620- ) ) ;
621- err. emit ( ) ;
622- self . cx . trace_macros_diag ( ) ;
623- FatalError . raise ( ) ;
620+ ) )
621+ . emit ( ) ;
622+ self . cx . trace_macros_diag ( ) ;
623+ FatalError . raise ( ) ;
624+ }
625+
626+ /// A macro's expansion does not fit in this fragment kind.
627+ /// For example, a non-type macro in a type position.
628+ fn error_wrong_fragment_kind ( & mut self , kind : AstFragmentKind , mac : & ast:: Mac , span : Span ) {
629+ let msg = format ! (
630+ "non-{kind} macro in {kind} position: {path}" ,
631+ kind = kind. name( ) ,
632+ path = pprust:: path_to_string( & mac. path) ,
633+ ) ;
634+ self . cx . span_err ( span, & msg) ;
635+ self . cx . trace_macros_diag ( ) ;
636+ }
637+
638+ fn expand_invoc ( & mut self , invoc : Invocation , ext : & SyntaxExtensionKind ) -> AstFragment {
639+ if self . cx . current_expansion . depth > self . cx . ecfg . recursion_limit {
640+ self . error_recursion_limit_reached ( ) ;
624641 }
625642
626643 let ( fragment_kind, span) = ( invoc. fragment_kind , invoc. span ( ) ) ;
@@ -638,13 +655,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
638655 let result = if let Some ( result) = fragment_kind. make_from ( tok_result) {
639656 result
640657 } else {
641- let msg = format ! (
642- "non-{kind} macro in {kind} position: {path}" ,
643- kind = fragment_kind. name( ) ,
644- path = pprust:: path_to_string( & mac. path) ,
645- ) ;
646- self . cx . span_err ( span, & msg) ;
647- self . cx . trace_macros_diag ( ) ;
658+ self . error_wrong_fragment_kind ( fragment_kind, & mac, span) ;
648659 fragment_kind. dummy ( span)
649660 } ;
650661 self . cx . current_expansion . prior_type_ascription = prev;
@@ -867,7 +878,7 @@ pub fn parse_ast_fragment<'a>(
867878 AstFragmentKind :: ForeignItems => {
868879 let mut items = SmallVec :: new ( ) ;
869880 while this. token != token:: Eof {
870- items. push ( this. parse_foreign_item ( ) ?) ;
881+ items. push ( this. parse_foreign_item ( & mut false ) ?) ;
871882 }
872883 AstFragment :: ForeignItems ( items)
873884 }
@@ -1030,13 +1041,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10301041 }
10311042
10321043 /// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
1033- fn classify_item < T > (
1044+ fn classify_item (
10341045 & mut self ,
1035- item : & mut T ,
1036- ) -> ( Option < ast:: Attribute > , Vec < Path > , /* after_derive */ bool )
1037- where
1038- T : HasAttrs ,
1039- {
1046+ item : & mut impl HasAttrs ,
1047+ ) -> ( Option < ast:: Attribute > , Vec < Path > , /* after_derive */ bool ) {
10401048 let ( mut attr, mut traits, mut after_derive) = ( None , Vec :: new ( ) , false ) ;
10411049
10421050 item. visit_attrs ( |mut attrs| {
@@ -1050,9 +1058,9 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10501058 /// Alternative to `classify_item()` that ignores `#[derive]` so invocations fallthrough
10511059 /// to the unused-attributes lint (making it an error on statements and expressions
10521060 /// is a breaking change)
1053- fn classify_nonitem < T : HasAttrs > (
1061+ fn classify_nonitem (
10541062 & mut self ,
1055- nonitem : & mut T ,
1063+ nonitem : & mut impl HasAttrs ,
10561064 ) -> ( Option < ast:: Attribute > , /* after_derive */ bool ) {
10571065 let ( mut attr, mut after_derive) = ( None , false ) ;
10581066
@@ -1375,21 +1383,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
13751383 _ => unreachable ! ( ) ,
13761384 } )
13771385 }
1378- ast:: ItemKind :: Mod ( ast:: Mod { inner, .. } ) => {
1379- if item. ident == Ident :: invalid ( ) {
1380- return noop_flat_map_item ( item, self ) ;
1381- }
1382-
1386+ ast:: ItemKind :: Mod ( ast:: Mod { inner, inline, .. } )
1387+ if item. ident != Ident :: invalid ( ) =>
1388+ {
13831389 let orig_directory_ownership = self . cx . current_expansion . directory_ownership ;
13841390 let mut module = ( * self . cx . current_expansion . module ) . clone ( ) ;
13851391 module. mod_path . push ( item. ident ) ;
13861392
1387- // Detect if this is an inline module (`mod m { ... }` as opposed to `mod m;`).
1388- // In the non-inline case, `inner` is never the dummy span (cf. `parse_item_mod`).
1389- // Thus, if `inner` is the dummy span, we know the module is inline.
1390- let inline_module = item. span . contains ( inner) || inner. is_dummy ( ) ;
1391-
1392- if inline_module {
1393+ if inline {
13931394 if let Some ( path) = attr:: first_attr_value_str_by_name ( & item. attrs , sym:: path) {
13941395 self . cx . current_expansion . directory_ownership =
13951396 DirectoryOwnership :: Owned { relative : None } ;
0 commit comments