@@ -302,7 +302,7 @@ fn expand_mac_invoc<T>(mac: ast::Mac, ident: Option<Ident>, attrs: Vec<ast::Attr
302
302
None
303
303
}
304
304
305
- MultiDecorator ( ..) | MultiModifier ( ..) => {
305
+ Renovator ( .. ) | MultiDecorator ( ..) | MultiModifier ( ..) => {
306
306
fld. cx . span_err ( path. span ,
307
307
& format ! ( "`{}` can only be used in attributes" , extname) ) ;
308
308
None
@@ -718,14 +718,23 @@ impl<'a> Folder for PatIdentRenamer<'a> {
718
718
}
719
719
}
720
720
721
- fn expand_annotatable ( a : Annotatable ,
721
+ fn expand_annotatable ( original_item : Annotatable ,
722
722
fld : & mut MacroExpander )
723
723
-> SmallVector < Annotatable > {
724
- let a = expand_item_multi_modifier ( a, fld) ;
724
+ let a = expand_item_multi_modifier ( original_item, fld) ;
725
+
726
+ let mut renovated_items = expand_renovators ( a. clone ( ) , fld) ;
727
+
728
+ // Take the original item out (if any).
729
+ let a = if let Some ( index) = renovated_items. iter ( ) . position ( |i| is_original_item ( i, & a) ) {
730
+ renovated_items. remove ( index)
731
+ } else {
732
+ return SmallVector :: zero ( ) ; // The renovator ate the item.
733
+ } ;
725
734
726
735
let mut decorator_items = SmallVector :: zero ( ) ;
727
736
let mut new_attrs = Vec :: new ( ) ;
728
- let a = expand_renovators_and_decorators ( a , fld, & mut decorator_items, & mut new_attrs) ;
737
+ expand_decorators ( a . clone ( ) , fld, & mut decorator_items, & mut new_attrs) ;
729
738
730
739
let mut new_items: SmallVector < Annotatable > = match a {
731
740
Annotatable :: Item ( it) => match it. node {
@@ -789,7 +798,9 @@ fn expand_annotatable(a: Annotatable,
789
798
}
790
799
} ;
791
800
801
+ new_items. extend ( renovated_items. into_iter ( ) ) ;
792
802
new_items. push_all ( decorator_items) ;
803
+
793
804
new_items
794
805
}
795
806
@@ -816,63 +827,131 @@ macro_rules! partition {
816
827
partition ! ( multi_modifiers, MultiModifier ) ;
817
828
818
829
819
- fn expand_renovators_and_decorators ( mut item : Annotatable ,
820
- fld : & mut MacroExpander ,
821
- decorator_items : & mut SmallVector < Annotatable > ,
822
- new_attrs : & mut Vec < ast:: Attribute > ) -> Annotatable
830
+ fn expand_decorators ( a : Annotatable ,
831
+ fld : & mut MacroExpander ,
832
+ decorator_items : & mut SmallVector < Annotatable > ,
833
+ new_attrs : & mut Vec < ast:: Attribute > )
823
834
{
824
- let attrs: Vec < _ > = item. attrs ( ) . iter ( ) . cloned ( ) . collect ( ) ;
825
-
826
- for attr in attrs {
835
+ for attr in a. attrs ( ) {
827
836
let mname = intern ( & attr. name ( ) ) ;
828
-
829
- fld. cx . bt_push ( ExpnInfo {
830
- call_site : attr. span ,
831
- callee : NameAndSpan {
832
- format : MacroAttribute ( mname) ,
833
- span : Some ( attr. span ) ,
834
- // attributes can do whatever they like,
835
- // for now.
836
- allow_internal_unstable : true ,
837
- }
838
- } ) ;
839
-
840
- // we'd ideally decorator_items.push_all(expand_annotatable(ann, fld)),
841
- // but that double-mut-borrows fld
842
- let mut items: SmallVector < Annotatable > = SmallVector :: zero ( ) ;
843
-
844
837
match fld. cx . syntax_env . find ( mname) {
845
838
Some ( rc) => match * rc {
846
839
MultiDecorator ( ref dec) => {
847
840
attr:: mark_used ( & attr) ;
848
841
842
+ fld. cx . bt_push ( ExpnInfo {
843
+ call_site : attr. span ,
844
+ callee : NameAndSpan {
845
+ format : MacroAttribute ( mname) ,
846
+ span : Some ( attr. span ) ,
847
+ // attributes can do whatever they like,
848
+ // for now.
849
+ allow_internal_unstable : true ,
850
+ }
851
+ } ) ;
852
+
853
+ // we'd ideally decorator_items.push_all(expand_annotatable(ann, fld)),
854
+ // but that double-mut-borrows fld
855
+ let mut items: SmallVector < Annotatable > = SmallVector :: zero ( ) ;
849
856
dec. expand ( fld. cx ,
850
857
attr. span ,
851
858
& attr. node . value ,
852
- & item ,
859
+ & a ,
853
860
& mut |ann| items. push ( ann) ) ;
854
- } ,
855
- Renovator ( ref ren) => {
856
- attr:: mark_used ( & attr) ;
861
+ decorator_items. extend ( items. into_iter ( )
862
+ . flat_map ( |ann| expand_annotatable ( ann, fld) . into_iter ( ) ) ) ;
857
863
858
- item = ren. expand ( fld. cx ,
859
- attr. span ,
860
- & attr. node . value ,
861
- item,
862
- & mut |ann| items. push ( ann) ) ;
863
- } ,
864
- _ => new_attrs. push ( attr) ,
864
+ fld. cx . bt_pop ( ) ;
865
+ }
866
+ _ => new_attrs. push ( ( * attr) . clone ( ) ) ,
865
867
} ,
866
- _ => new_attrs. push ( attr) ,
868
+ _ => new_attrs. push ( ( * attr) . clone ( ) ) ,
867
869
}
870
+ }
871
+ }
872
+
873
+ fn is_original_item ( item : & Annotatable , original : & Annotatable ) -> bool {
874
+ item. node_id ( ) == original. node_id ( )
875
+ }
876
+
877
+ fn expand_renovators ( original_item : Annotatable ,
878
+ fld : & mut MacroExpander ) -> Vec < Annotatable >
879
+ {
880
+ let mut items = Vec :: new ( ) ;
881
+ items. push ( original_item. clone ( ) ) ;
882
+
883
+ let mut processed_attributes: Vec < ast:: Attribute > = Vec :: new ( ) ;
868
884
869
- decorator_items . extend ( items . into_iter ( )
870
- . flat_map ( |ann| expand_annotatable ( ann , fld ) . into_iter ( ) ) ) ;
885
+ ' main_loop : loop {
886
+ let item_idx = items . iter ( ) . position ( |i| is_original_item ( i , & original_item ) ) ;
871
887
872
- fld. cx . bt_pop ( ) ;
888
+ let item = if let Some ( idx) = item_idx {
889
+ items. remove ( idx)
890
+ } else {
891
+ break ' main_loop;
892
+ } ;
893
+
894
+ // Find the first unprocessed attribute.
895
+ let attr = if let Some ( attr) = item. attrs ( ) . iter ( ) . cloned ( ) .
896
+ find ( |i| !processed_attributes. iter ( ) . any ( |pi| i == pi) ) {
897
+ attr
898
+ } else {
899
+ items. push ( item) ; // put the item back.
900
+ break ' main_loop;
901
+ } ;
902
+
903
+ processed_attributes. push ( attr. clone ( ) ) ;
904
+
905
+ let macro_name = intern ( & attr. name ( ) ) ;
906
+
907
+ match fld. cx . syntax_env . find ( macro_name) {
908
+ Some ( rc) => match * rc {
909
+ Renovator ( ref dec) => {
910
+ attr:: mark_used ( & attr) ;
911
+
912
+ fld. cx . bt_push ( ExpnInfo {
913
+ call_site : attr. span ,
914
+ callee : NameAndSpan {
915
+ format : MacroAttribute ( macro_name) ,
916
+ span : Some ( attr. span ) ,
917
+ // attributes can do whatever they like,
918
+ // for now.
919
+ allow_internal_unstable : true ,
920
+ }
921
+ } ) ;
922
+
923
+ let mut new_items: SmallVector < Annotatable > = SmallVector :: zero ( ) ;
924
+ dec. expand ( fld. cx ,
925
+ attr. span ,
926
+ & attr. node . value ,
927
+ item,
928
+ & mut |ann| new_items. push ( ann) ) ;
929
+
930
+ let new_items = new_items. into_iter ( ) . map ( |item| {
931
+ // Remove all attributes that are already processed.
932
+ let attrs: Vec < _ > = item. attrs ( ) . iter ( ) . cloned ( ) .
933
+ filter ( |a| processed_attributes. iter ( ) . any ( |pa| pa == a) ) . collect ( ) ;
934
+
935
+ item. fold_attrs ( attrs)
936
+ } ) ;
937
+
938
+ for new_item in new_items {
939
+ if is_original_item ( & new_item, & original_item) {
940
+ items. push ( new_item) ;
941
+ } else {
942
+ items. extend ( expand_annotatable ( new_item, fld) . into_iter ( ) ) ;
943
+ }
944
+ }
945
+
946
+ fld. cx . bt_pop ( ) ;
947
+ } ,
948
+ _ => items. push ( item. clone ( ) ) ,
949
+ } ,
950
+ _ => items. push ( item. clone ( ) ) ,
951
+ }
873
952
}
874
953
875
- item
954
+ items
876
955
}
877
956
878
957
fn expand_item_multi_modifier ( mut it : Annotatable ,
0 commit comments