1
1
use crate :: cfg_eval:: cfg_eval;
2
2
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 } ;
4
5
use rustc_errors:: { struct_span_err, Applicability } ;
5
6
use rustc_expand:: base:: { Annotatable , ExpandResult , ExtCtxt , Indeterminate , MultiItemModifier } ;
6
7
use rustc_feature:: AttributeTemplate ;
7
8
use rustc_parse:: validate_attr;
8
9
use rustc_session:: Session ;
9
- use rustc_span:: symbol:: sym;
10
+ use rustc_span:: symbol:: { sym, Ident } ;
10
11
use rustc_span:: Span ;
11
12
12
13
crate struct Expander ;
@@ -26,8 +27,7 @@ impl MultiItemModifier for Expander {
26
27
return ExpandResult :: Ready ( vec ! [ item] ) ;
27
28
}
28
29
29
- let configured_item = cfg_eval ( ecx, item. clone ( ) ) ;
30
-
30
+ let ( sess, features) = ( ecx. sess , ecx. ecfg . features ) ;
31
31
let result =
32
32
ecx. resolver . resolve_derives ( ecx. current_expansion . id , ecx. force_mode , & || {
33
33
let template =
@@ -40,7 +40,8 @@ impl MultiItemModifier for Expander {
40
40
template,
41
41
) ;
42
42
43
- attr. meta_item_list ( )
43
+ let mut resolutions: Vec < _ > = attr
44
+ . meta_item_list ( )
44
45
. unwrap_or_default ( )
45
46
. into_iter ( )
46
47
. filter_map ( |nested_meta| match nested_meta {
@@ -56,8 +57,21 @@ impl MultiItemModifier for Expander {
56
57
report_path_args ( sess, & meta) ;
57
58
meta. path
58
59
} )
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
61
75
} ) ;
62
76
63
77
match result {
@@ -67,6 +81,18 @@ impl MultiItemModifier for Expander {
67
81
}
68
82
}
69
83
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
+
70
96
fn report_bad_target ( sess : & Session , item : & Annotatable , span : Span ) -> bool {
71
97
let item_kind = match item {
72
98
Annotatable :: Item ( item) => Some ( & item. kind ) ,
0 commit comments