11use crate :: cfg_eval:: cfg_eval;
22
3- use rustc_ast:: { self as ast, attr, token, ItemKind , MetaItemKind , NestedMetaItem , StmtKind } ;
3+ use rustc_ast as ast;
4+ use rustc_ast:: { attr, token, GenericParamKind , ItemKind , MetaItemKind , NestedMetaItem , StmtKind } ;
45use rustc_errors:: { struct_span_err, Applicability } ;
56use rustc_expand:: base:: { Annotatable , ExpandResult , ExtCtxt , Indeterminate , MultiItemModifier } ;
67use rustc_feature:: AttributeTemplate ;
78use rustc_parse:: validate_attr;
89use rustc_session:: Session ;
9- use rustc_span:: symbol:: sym;
10+ use rustc_span:: symbol:: { sym, Ident } ;
1011use rustc_span:: Span ;
1112
1213crate struct Expander ;
@@ -26,8 +27,7 @@ impl MultiItemModifier for Expander {
2627 return ExpandResult :: Ready ( vec ! [ item] ) ;
2728 }
2829
29- let configured_item = cfg_eval ( ecx, item. clone ( ) ) ;
30-
30+ let ( sess, features) = ( ecx. sess , ecx. ecfg . features ) ;
3131 let result =
3232 ecx. resolver . resolve_derives ( ecx. current_expansion . id , ecx. force_mode , & || {
3333 let template =
@@ -40,7 +40,8 @@ impl MultiItemModifier for Expander {
4040 template,
4141 ) ;
4242
43- attr. meta_item_list ( )
43+ let mut resolutions: Vec < _ > = attr
44+ . meta_item_list ( )
4445 . unwrap_or_default ( )
4546 . into_iter ( )
4647 . filter_map ( |nested_meta| match nested_meta {
@@ -56,8 +57,21 @@ impl MultiItemModifier for Expander {
5657 report_path_args ( sess, & meta) ;
5758 meta. path
5859 } )
59- . map ( |path| ( path, configured_item. clone ( ) , None ) )
60- . collect ( )
60+ . map ( |path| ( path, dummy_annotatable ( ) , None ) )
61+ . collect ( ) ;
62+
63+ // Do not configure or clone items unless necessary.
64+ match & mut resolutions[ ..] {
65+ [ ] => { }
66+ [ ( _, first_item, _) , others @ ..] => {
67+ * first_item = cfg_eval ( sess, features, item. clone ( ) ) ;
68+ for ( _, item, _) in others {
69+ * item = first_item. clone ( ) ;
70+ }
71+ }
72+ }
73+
74+ resolutions
6175 } ) ;
6276
6377 match result {
@@ -67,6 +81,18 @@ impl MultiItemModifier for Expander {
6781 }
6882}
6983
84+ // The cheapest `Annotatable` to construct.
85+ fn dummy_annotatable ( ) -> Annotatable {
86+ Annotatable :: GenericParam ( ast:: GenericParam {
87+ id : ast:: DUMMY_NODE_ID ,
88+ ident : Ident :: invalid ( ) ,
89+ attrs : Default :: default ( ) ,
90+ bounds : Default :: default ( ) ,
91+ is_placeholder : false ,
92+ kind : GenericParamKind :: Lifetime ,
93+ } )
94+ }
95+
7096fn report_bad_target ( sess : & Session , item : & Annotatable , span : Span ) -> bool {
7197 let item_kind = match item {
7298 Annotatable :: Item ( item) => Some ( & item. kind ) ,
0 commit comments