@@ -451,28 +451,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
451
451
_ => unreachable ! ( ) ,
452
452
} ;
453
453
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) ;
476
455
}
477
456
478
457
let mut item = self . fully_configure ( item) ;
@@ -521,6 +500,27 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
521
500
fragment_with_placeholders
522
501
}
523
502
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
+
524
524
fn resolve_imports ( & mut self ) {
525
525
if self . monotonic {
526
526
self . cx . resolver . resolve_imports ( ) ;
@@ -606,21 +606,38 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
606
606
}
607
607
}
608
608
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 (
614
614
expn_data. call_site ,
615
615
& format ! ( "recursion limit reached while expanding `{}`" , expn_data. kind. descr( ) ) ,
616
- ) ;
617
- err . help ( & format ! (
616
+ )
617
+ . help ( & format ! (
618
618
"consider adding a `#![recursion_limit=\" {}\" ]` attribute to your crate (`{}`)" ,
619
619
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 ( ) ;
624
641
}
625
642
626
643
let ( fragment_kind, span) = ( invoc. fragment_kind , invoc. span ( ) ) ;
@@ -638,13 +655,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
638
655
let result = if let Some ( result) = fragment_kind. make_from ( tok_result) {
639
656
result
640
657
} 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) ;
648
659
fragment_kind. dummy ( span)
649
660
} ;
650
661
self . cx . current_expansion . prior_type_ascription = prev;
@@ -867,7 +878,7 @@ pub fn parse_ast_fragment<'a>(
867
878
AstFragmentKind :: ForeignItems => {
868
879
let mut items = SmallVec :: new ( ) ;
869
880
while this. token != token:: Eof {
870
- items. push ( this. parse_foreign_item ( ) ?) ;
881
+ items. push ( this. parse_foreign_item ( & mut false ) ?) ;
871
882
}
872
883
AstFragment :: ForeignItems ( items)
873
884
}
@@ -1030,13 +1041,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
1030
1041
}
1031
1042
1032
1043
/// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
1033
- fn classify_item < T > (
1044
+ fn classify_item (
1034
1045
& 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 ) {
1040
1048
let ( mut attr, mut traits, mut after_derive) = ( None , Vec :: new ( ) , false ) ;
1041
1049
1042
1050
item. visit_attrs ( |mut attrs| {
@@ -1050,9 +1058,9 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
1050
1058
/// Alternative to `classify_item()` that ignores `#[derive]` so invocations fallthrough
1051
1059
/// to the unused-attributes lint (making it an error on statements and expressions
1052
1060
/// is a breaking change)
1053
- fn classify_nonitem < T : HasAttrs > (
1061
+ fn classify_nonitem (
1054
1062
& mut self ,
1055
- nonitem : & mut T ,
1063
+ nonitem : & mut impl HasAttrs ,
1056
1064
) -> ( Option < ast:: Attribute > , /* after_derive */ bool ) {
1057
1065
let ( mut attr, mut after_derive) = ( None , false ) ;
1058
1066
@@ -1375,21 +1383,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1375
1383
_ => unreachable ! ( ) ,
1376
1384
} )
1377
1385
}
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
+ {
1383
1389
let orig_directory_ownership = self . cx . current_expansion . directory_ownership ;
1384
1390
let mut module = ( * self . cx . current_expansion . module ) . clone ( ) ;
1385
1391
module. mod_path . push ( item. ident ) ;
1386
1392
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 {
1393
1394
if let Some ( path) = attr:: first_attr_value_str_by_name ( & item. attrs , sym:: path) {
1394
1395
self . cx . current_expansion . directory_ownership =
1395
1396
DirectoryOwnership :: Owned { relative : None } ;
0 commit comments