@@ -302,7 +302,7 @@ fn expand_mac_invoc<T>(mac: ast::Mac, ident: Option<Ident>, attrs: Vec<ast::Attr
302302 None
303303 }
304304
305- MultiDecorator ( ..) | MultiModifier ( ..) => {
305+ Renovator ( .. ) | MultiDecorator ( ..) | MultiModifier ( ..) => {
306306 fld. cx . span_err ( path. span ,
307307 & format ! ( "`{}` can only be used in attributes" , extname) ) ;
308308 None
@@ -718,14 +718,23 @@ impl<'a> Folder for PatIdentRenamer<'a> {
718718 }
719719}
720720
721- fn expand_annotatable ( a : Annotatable ,
721+ fn expand_annotatable ( original_item : Annotatable ,
722722 fld : & mut MacroExpander )
723723 -> 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+ } ;
725734
726735 let mut decorator_items = SmallVector :: zero ( ) ;
727736 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) ;
729738
730739 let mut new_items: SmallVector < Annotatable > = match a {
731740 Annotatable :: Item ( it) => match it. node {
@@ -789,7 +798,9 @@ fn expand_annotatable(a: Annotatable,
789798 }
790799 } ;
791800
801+ new_items. extend ( renovated_items. into_iter ( ) ) ;
792802 new_items. push_all ( decorator_items) ;
803+
793804 new_items
794805}
795806
@@ -816,63 +827,131 @@ macro_rules! partition {
816827partition ! ( multi_modifiers, MultiModifier ) ;
817828
818829
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 > )
823834{
824- let attrs: Vec < _ > = item. attrs ( ) . iter ( ) . cloned ( ) . collect ( ) ;
825-
826- for attr in attrs {
835+ for attr in a. attrs ( ) {
827836 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-
844837 match fld. cx . syntax_env . find ( mname) {
845838 Some ( rc) => match * rc {
846839 MultiDecorator ( ref dec) => {
847840 attr:: mark_used ( & attr) ;
848841
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 ( ) ;
849856 dec. expand ( fld. cx ,
850857 attr. span ,
851858 & attr. node . value ,
852- & item ,
859+ & a ,
853860 & 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 ( ) ) ) ;
857863
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 ( ) ) ,
865867 } ,
866- _ => new_attrs. push ( attr) ,
868+ _ => new_attrs. push ( ( * attr) . clone ( ) ) ,
867869 }
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 ( ) ;
868884
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 ) ) ;
871887
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+ }
873952 }
874953
875- item
954+ items
876955}
877956
878957fn expand_item_multi_modifier ( mut it : Annotatable ,
0 commit comments