@@ -8,6 +8,7 @@ use std::mem;
8
8
use std:: ops;
9
9
10
10
use rustc_ast:: { LitKind , MetaItem , MetaItemKind , NestedMetaItem } ;
11
+ use rustc_data_structures:: fx:: FxHashSet ;
11
12
use rustc_feature:: Features ;
12
13
use rustc_session:: parse:: ParseSess ;
13
14
use rustc_span:: symbol:: { sym, Symbol } ;
@@ -43,23 +44,22 @@ crate struct InvalidCfgError {
43
44
44
45
impl Cfg {
45
46
/// Parses a `NestedMetaItem` into a `Cfg`.
46
- fn parse_nested ( nested_cfg : & NestedMetaItem ) -> Result < Cfg , InvalidCfgError > {
47
+ fn parse_nested (
48
+ nested_cfg : & NestedMetaItem ,
49
+ exclude : & FxHashSet < Cfg > ,
50
+ ) -> Result < Option < Cfg > , InvalidCfgError > {
47
51
match nested_cfg {
48
- NestedMetaItem :: MetaItem ( ref cfg) => Cfg :: parse ( cfg) ,
52
+ NestedMetaItem :: MetaItem ( ref cfg) => Cfg :: parse_without ( cfg, exclude ) ,
49
53
NestedMetaItem :: Literal ( ref lit) => {
50
54
Err ( InvalidCfgError { msg : "unexpected literal" , span : lit. span } )
51
55
}
52
56
}
53
57
}
54
58
55
- /// Parses a `MetaItem` into a `Cfg`.
56
- ///
57
- /// The `MetaItem` should be the content of the `#[cfg(...)]`, e.g., `unix` or
58
- /// `target_os = "redox"`.
59
- ///
60
- /// If the content is not properly formatted, it will return an error indicating what and where
61
- /// the error is.
62
- crate fn parse ( cfg : & MetaItem ) -> Result < Cfg , InvalidCfgError > {
59
+ crate fn parse_without (
60
+ cfg : & MetaItem ,
61
+ exclude : & FxHashSet < Cfg > ,
62
+ ) -> Result < Option < Cfg > , InvalidCfgError > {
63
63
let name = match cfg. ident ( ) {
64
64
Some ( ident) => ident. name ,
65
65
None => {
@@ -70,9 +70,15 @@ impl Cfg {
70
70
}
71
71
} ;
72
72
match cfg. kind {
73
- MetaItemKind :: Word => Ok ( Cfg :: Cfg ( name, None ) ) ,
73
+ MetaItemKind :: Word => {
74
+ let cfg = Cfg :: Cfg ( name, None ) ;
75
+ if exclude. contains ( & cfg) { Ok ( None ) } else { Ok ( Some ( cfg) ) }
76
+ }
74
77
MetaItemKind :: NameValue ( ref lit) => match lit. kind {
75
- LitKind :: Str ( value, _) => Ok ( Cfg :: Cfg ( name, Some ( value) ) ) ,
78
+ LitKind :: Str ( value, _) => {
79
+ let cfg = Cfg :: Cfg ( name, Some ( value) ) ;
80
+ if exclude. contains ( & cfg) { Ok ( None ) } else { Ok ( Some ( cfg) ) }
81
+ }
76
82
_ => Err ( InvalidCfgError {
77
83
// FIXME: if the main #[cfg] syntax decided to support non-string literals,
78
84
// this should be changed as well.
@@ -81,23 +87,40 @@ impl Cfg {
81
87
} ) ,
82
88
} ,
83
89
MetaItemKind :: List ( ref items) => {
84
- let mut sub_cfgs = items. iter ( ) . map ( Cfg :: parse_nested) ;
85
- match name {
90
+ let sub_cfgs =
91
+ items. iter ( ) . filter_map ( |i| Cfg :: parse_nested ( i, exclude) . transpose ( ) ) ;
92
+ let ret = match name {
86
93
sym:: all => sub_cfgs. fold ( Ok ( Cfg :: True ) , |x, y| Ok ( x? & y?) ) ,
87
94
sym:: any => sub_cfgs. fold ( Ok ( Cfg :: False ) , |x, y| Ok ( x? | y?) ) ,
88
95
sym:: not => {
96
+ let mut sub_cfgs = sub_cfgs. collect :: < Vec < _ > > ( ) ;
89
97
if sub_cfgs. len ( ) == 1 {
90
- Ok ( !sub_cfgs. next ( ) . unwrap ( ) ?)
98
+ Ok ( !sub_cfgs. pop ( ) . unwrap ( ) ?)
91
99
} else {
92
100
Err ( InvalidCfgError { msg : "expected 1 cfg-pattern" , span : cfg. span } )
93
101
}
94
102
}
95
103
_ => Err ( InvalidCfgError { msg : "invalid predicate" , span : cfg. span } ) ,
104
+ } ;
105
+ match ret {
106
+ Ok ( c) => Ok ( Some ( c) ) ,
107
+ Err ( e) => Err ( e) ,
96
108
}
97
109
}
98
110
}
99
111
}
100
112
113
+ /// Parses a `MetaItem` into a `Cfg`.
114
+ ///
115
+ /// The `MetaItem` should be the content of the `#[cfg(...)]`, e.g., `unix` or
116
+ /// `target_os = "redox"`.
117
+ ///
118
+ /// If the content is not properly formatted, it will return an error indicating what and where
119
+ /// the error is.
120
+ crate fn parse ( cfg : & MetaItem ) -> Result < Cfg , InvalidCfgError > {
121
+ Self :: parse_without ( cfg, & FxHashSet :: default ( ) ) . map ( |ret| ret. unwrap ( ) )
122
+ }
123
+
101
124
/// Checks whether the given configuration can be matched in the current session.
102
125
///
103
126
/// Equivalent to `attr::cfg_matches`.
0 commit comments