@@ -43,23 +43,22 @@ crate struct InvalidCfgError {
4343
4444impl Cfg {
4545 /// Parses a `NestedMetaItem` into a `Cfg`.
46- fn parse_nested ( nested_cfg : & NestedMetaItem ) -> Result < Cfg , InvalidCfgError > {
46+ fn parse_nested (
47+ nested_cfg : & NestedMetaItem ,
48+ exclude : & [ Symbol ] ,
49+ ) -> Result < Option < Cfg > , InvalidCfgError > {
4750 match nested_cfg {
48- NestedMetaItem :: MetaItem ( ref cfg) => Cfg :: parse ( cfg) ,
51+ NestedMetaItem :: MetaItem ( ref cfg) => Cfg :: parse_without ( cfg, exclude ) ,
4952 NestedMetaItem :: Literal ( ref lit) => {
5053 Err ( InvalidCfgError { msg : "unexpected literal" , span : lit. span } )
5154 }
5255 }
5356 }
5457
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 > {
58+ crate fn parse_without (
59+ cfg : & MetaItem ,
60+ exclude : & [ Symbol ] ,
61+ ) -> Result < Option < Cfg > , InvalidCfgError > {
6362 let name = match cfg. ident ( ) {
6463 Some ( ident) => ident. name ,
6564 None => {
@@ -70,9 +69,21 @@ impl Cfg {
7069 }
7170 } ;
7271 match cfg. kind {
73- MetaItemKind :: Word => Ok ( Cfg :: Cfg ( name, None ) ) ,
72+ MetaItemKind :: Word => {
73+ if exclude. contains ( & name) {
74+ Ok ( None )
75+ } else {
76+ Ok ( Some ( Cfg :: Cfg ( name, None ) ) )
77+ }
78+ }
7479 MetaItemKind :: NameValue ( ref lit) => match lit. kind {
75- LitKind :: Str ( value, _) => Ok ( Cfg :: Cfg ( name, Some ( value) ) ) ,
80+ LitKind :: Str ( value, _) => {
81+ if exclude. contains ( & name) {
82+ Ok ( None )
83+ } else {
84+ Ok ( Some ( Cfg :: Cfg ( name, Some ( value) ) ) )
85+ }
86+ }
7687 _ => Err ( InvalidCfgError {
7788 // FIXME: if the main #[cfg] syntax decided to support non-string literals,
7889 // this should be changed as well.
@@ -81,23 +92,43 @@ impl Cfg {
8192 } ) ,
8293 } ,
8394 MetaItemKind :: List ( ref items) => {
84- let mut sub_cfgs = items. iter ( ) . map ( Cfg :: parse_nested) ;
85- match name {
95+ let sub_cfgs = items. iter ( ) . filter_map ( |i| match Cfg :: parse_nested ( i, exclude) {
96+ Ok ( Some ( c) ) => Some ( Ok ( c) ) ,
97+ Err ( e) => Some ( Err ( e) ) ,
98+ _ => None ,
99+ } ) ;
100+ let ret = match name {
86101 sym:: all => sub_cfgs. fold ( Ok ( Cfg :: True ) , |x, y| Ok ( x? & y?) ) ,
87102 sym:: any => sub_cfgs. fold ( Ok ( Cfg :: False ) , |x, y| Ok ( x? | y?) ) ,
88103 sym:: not => {
104+ let mut sub_cfgs = sub_cfgs. collect :: < Vec < _ > > ( ) ;
89105 if sub_cfgs. len ( ) == 1 {
90- Ok ( !sub_cfgs. next ( ) . unwrap ( ) ?)
106+ Ok ( !sub_cfgs. pop ( ) . unwrap ( ) ?)
91107 } else {
92108 Err ( InvalidCfgError { msg : "expected 1 cfg-pattern" , span : cfg. span } )
93109 }
94110 }
95111 _ => Err ( InvalidCfgError { msg : "invalid predicate" , span : cfg. span } ) ,
112+ } ;
113+ match ret {
114+ Ok ( c) => Ok ( Some ( c) ) ,
115+ Err ( e) => Err ( e) ,
96116 }
97117 }
98118 }
99119 }
100120
121+ /// Parses a `MetaItem` into a `Cfg`.
122+ ///
123+ /// The `MetaItem` should be the content of the `#[cfg(...)]`, e.g., `unix` or
124+ /// `target_os = "redox"`.
125+ ///
126+ /// If the content is not properly formatted, it will return an error indicating what and where
127+ /// the error is.
128+ crate fn parse ( cfg : & MetaItem ) -> Result < Cfg , InvalidCfgError > {
129+ Self :: parse_without ( cfg, & [ ] ) . map ( |ret| ret. unwrap ( ) )
130+ }
131+
101132 /// Checks whether the given configuration can be matched in the current session.
102133 ///
103134 /// Equivalent to `attr::cfg_matches`.
0 commit comments