@@ -8,6 +8,7 @@ use std::mem;
88use std:: ops;
99
1010use rustc_ast:: { LitKind , MetaItem , MetaItemKind , NestedMetaItem } ;
11+ use rustc_data_structures:: fx:: FxHashSet ;
1112use rustc_feature:: Features ;
1213use rustc_session:: parse:: ParseSess ;
1314use rustc_span:: symbol:: { sym, Symbol } ;
@@ -43,23 +44,22 @@ crate struct InvalidCfgError {
4344
4445impl Cfg {
4546 /// 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 > {
4751 match nested_cfg {
48- NestedMetaItem :: MetaItem ( ref cfg) => Cfg :: parse ( cfg) ,
52+ NestedMetaItem :: MetaItem ( ref cfg) => Cfg :: parse_without ( cfg, exclude ) ,
4953 NestedMetaItem :: Literal ( ref lit) => {
5054 Err ( InvalidCfgError { msg : "unexpected literal" , span : lit. span } )
5155 }
5256 }
5357 }
5458
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 > {
6363 let name = match cfg. ident ( ) {
6464 Some ( ident) => ident. name ,
6565 None => {
@@ -70,9 +70,15 @@ impl Cfg {
7070 }
7171 } ;
7272 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+ }
7477 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+ }
7682 _ => Err ( InvalidCfgError {
7783 // FIXME: if the main #[cfg] syntax decided to support non-string literals,
7884 // this should be changed as well.
@@ -81,23 +87,40 @@ impl Cfg {
8187 } ) ,
8288 } ,
8389 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 {
8693 sym:: all => sub_cfgs. fold ( Ok ( Cfg :: True ) , |x, y| Ok ( x? & y?) ) ,
8794 sym:: any => sub_cfgs. fold ( Ok ( Cfg :: False ) , |x, y| Ok ( x? | y?) ) ,
8895 sym:: not => {
96+ let mut sub_cfgs = sub_cfgs. collect :: < Vec < _ > > ( ) ;
8997 if sub_cfgs. len ( ) == 1 {
90- Ok ( !sub_cfgs. next ( ) . unwrap ( ) ?)
98+ Ok ( !sub_cfgs. pop ( ) . unwrap ( ) ?)
9199 } else {
92100 Err ( InvalidCfgError { msg : "expected 1 cfg-pattern" , span : cfg. span } )
93101 }
94102 }
95103 _ => Err ( InvalidCfgError { msg : "invalid predicate" , span : cfg. span } ) ,
104+ } ;
105+ match ret {
106+ Ok ( c) => Ok ( Some ( c) ) ,
107+ Err ( e) => Err ( e) ,
96108 }
97109 }
98110 }
99111 }
100112
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+
101124 /// Checks whether the given configuration can be matched in the current session.
102125 ///
103126 /// Equivalent to `attr::cfg_matches`.
0 commit comments