Skip to content

Commit 402e176

Browse files
committed
Auto merge of rust-lang#17657 - Veykril:cfg-slim, r=lnicola
internal: Make `CfgExpr` slimmer
2 parents 9e3482b + 272e595 commit 402e176

File tree

6 files changed

+77
-64
lines changed

6 files changed

+77
-64
lines changed

src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ impl fmt::Display for CfgAtom {
3232
pub enum CfgExpr {
3333
Invalid,
3434
Atom(CfgAtom),
35-
All(Vec<CfgExpr>),
36-
Any(Vec<CfgExpr>),
35+
All(Box<[CfgExpr]>),
36+
Any(Box<[CfgExpr]>),
3737
Not(Box<CfgExpr>),
3838
}
3939

@@ -90,12 +90,12 @@ fn next_cfg_expr<S>(it: &mut std::slice::Iter<'_, tt::TokenTree<S>>) -> Option<C
9090
Some(tt::TokenTree::Subtree(subtree)) => {
9191
it.next();
9292
let mut sub_it = subtree.token_trees.iter();
93-
let mut subs = std::iter::from_fn(|| next_cfg_expr(&mut sub_it)).collect();
94-
match &name {
95-
s if *s == sym::all => CfgExpr::All(subs),
96-
s if *s == sym::any => CfgExpr::Any(subs),
97-
s if *s == sym::not => {
98-
CfgExpr::Not(Box::new(subs.pop().unwrap_or(CfgExpr::Invalid)))
93+
let mut subs = std::iter::from_fn(|| next_cfg_expr(&mut sub_it));
94+
match name {
95+
s if s == sym::all => CfgExpr::All(subs.collect()),
96+
s if s == sym::any => CfgExpr::Any(subs.collect()),
97+
s if s == sym::not => {
98+
CfgExpr::Not(Box::new(subs.next().unwrap_or(CfgExpr::Invalid)))
9999
}
100100
_ => CfgExpr::Invalid,
101101
}

src/tools/rust-analyzer/crates/cfg/src/dnf.rs

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct Literal {
2727
}
2828

2929
impl DnfExpr {
30-
pub fn new(expr: CfgExpr) -> Self {
30+
pub fn new(expr: &CfgExpr) -> Self {
3131
let builder = Builder { expr: DnfExpr { conjunctions: Vec::new() } };
3232

3333
builder.lower(expr)
@@ -154,9 +154,9 @@ impl fmt::Display for DnfExpr {
154154
}
155155

156156
impl Conjunction {
157-
fn new(parts: Vec<CfgExpr>) -> Self {
157+
fn new(parts: Box<[CfgExpr]>) -> Self {
158158
let mut literals = Vec::new();
159-
for part in parts {
159+
for part in parts.into_vec() {
160160
match part {
161161
CfgExpr::Invalid | CfgExpr::Atom(_) | CfgExpr::Not(_) => {
162162
literals.push(Literal::new(part));
@@ -232,27 +232,28 @@ struct Builder {
232232
}
233233

234234
impl Builder {
235-
fn lower(mut self, expr: CfgExpr) -> DnfExpr {
235+
fn lower(mut self, expr: &CfgExpr) -> DnfExpr {
236236
let expr = make_nnf(expr);
237237
let expr = make_dnf(expr);
238238

239239
match expr {
240240
CfgExpr::Invalid | CfgExpr::Atom(_) | CfgExpr::Not(_) => {
241-
self.expr.conjunctions.push(Conjunction::new(vec![expr]));
241+
self.expr.conjunctions.push(Conjunction::new(Box::new([expr])));
242242
}
243243
CfgExpr::All(conj) => {
244244
self.expr.conjunctions.push(Conjunction::new(conj));
245245
}
246-
CfgExpr::Any(mut disj) => {
246+
CfgExpr::Any(disj) => {
247+
let mut disj = disj.into_vec();
247248
disj.reverse();
248249
while let Some(conj) = disj.pop() {
249250
match conj {
250251
CfgExpr::Invalid | CfgExpr::Atom(_) | CfgExpr::All(_) | CfgExpr::Not(_) => {
251-
self.expr.conjunctions.push(Conjunction::new(vec![conj]));
252+
self.expr.conjunctions.push(Conjunction::new(Box::new([conj])));
252253
}
253254
CfgExpr::Any(inner_disj) => {
254255
// Flatten.
255-
disj.extend(inner_disj.into_iter().rev());
256+
disj.extend(inner_disj.into_vec().into_iter().rev());
256257
}
257258
}
258259
}
@@ -266,11 +267,11 @@ impl Builder {
266267
fn make_dnf(expr: CfgExpr) -> CfgExpr {
267268
match expr {
268269
CfgExpr::Invalid | CfgExpr::Atom(_) | CfgExpr::Not(_) => expr,
269-
CfgExpr::Any(e) => flatten(CfgExpr::Any(e.into_iter().map(make_dnf).collect())),
270+
CfgExpr::Any(e) => flatten(CfgExpr::Any(e.into_vec().into_iter().map(make_dnf).collect())),
270271
CfgExpr::All(e) => {
271-
let e = e.into_iter().map(make_dnf).collect::<Vec<_>>();
272+
let e = e.into_vec().into_iter().map(make_dnf).collect::<Vec<_>>();
272273

273-
flatten(CfgExpr::Any(distribute_conj(&e)))
274+
flatten(CfgExpr::Any(distribute_conj(&e).into_boxed_slice()))
274275
}
275276
}
276277
}
@@ -281,7 +282,7 @@ fn distribute_conj(conj: &[CfgExpr]) -> Vec<CfgExpr> {
281282
match rest {
282283
[head, tail @ ..] => match head {
283284
CfgExpr::Any(disj) => {
284-
for part in disj {
285+
for part in disj.iter() {
285286
with.push(part.clone());
286287
go(out, with, tail);
287288
with.pop();
@@ -295,7 +296,7 @@ fn distribute_conj(conj: &[CfgExpr]) -> Vec<CfgExpr> {
295296
},
296297
_ => {
297298
// Turn accumulated parts into a new conjunction.
298-
out.push(CfgExpr::All(with.clone()));
299+
out.push(CfgExpr::All(with.clone().into_boxed_slice()));
299300
}
300301
}
301302
}
@@ -308,25 +309,27 @@ fn distribute_conj(conj: &[CfgExpr]) -> Vec<CfgExpr> {
308309
out
309310
}
310311

311-
fn make_nnf(expr: CfgExpr) -> CfgExpr {
312+
fn make_nnf(expr: &CfgExpr) -> CfgExpr {
312313
match expr {
313-
CfgExpr::Invalid | CfgExpr::Atom(_) => expr,
314-
CfgExpr::Any(expr) => CfgExpr::Any(expr.into_iter().map(make_nnf).collect()),
315-
CfgExpr::All(expr) => CfgExpr::All(expr.into_iter().map(make_nnf).collect()),
316-
CfgExpr::Not(operand) => match *operand {
317-
CfgExpr::Invalid | CfgExpr::Atom(_) => CfgExpr::Not(operand.clone()), // Original negated expr
318-
CfgExpr::Not(expr) => {
319-
// Remove double negation.
320-
make_nnf(*expr)
321-
}
322-
// Convert negated conjunction/disjunction using DeMorgan's Law.
323-
CfgExpr::Any(inner) => CfgExpr::All(
324-
inner.into_iter().map(|expr| make_nnf(CfgExpr::Not(Box::new(expr)))).collect(),
325-
),
326-
CfgExpr::All(inner) => CfgExpr::Any(
327-
inner.into_iter().map(|expr| make_nnf(CfgExpr::Not(Box::new(expr)))).collect(),
328-
),
329-
},
314+
CfgExpr::Invalid | CfgExpr::Atom(_) => expr.clone(),
315+
CfgExpr::Any(expr) => CfgExpr::Any(expr.iter().map(make_nnf).collect()),
316+
CfgExpr::All(expr) => CfgExpr::All(expr.iter().map(make_nnf).collect()),
317+
CfgExpr::Not(operand) => make_nnf_neg(operand),
318+
}
319+
}
320+
321+
fn make_nnf_neg(operand: &CfgExpr) -> CfgExpr {
322+
match operand {
323+
// Original negated expr
324+
CfgExpr::Invalid => CfgExpr::Not(Box::new(CfgExpr::Invalid)), // Original negated expr
325+
// Original negated expr
326+
CfgExpr::Atom(atom) => CfgExpr::Not(Box::new(CfgExpr::Atom(atom.clone()))),
327+
// Remove double negation.
328+
CfgExpr::Not(expr) => make_nnf(expr),
329+
// Convert negated conjunction/disjunction using DeMorgan's Law.
330+
CfgExpr::Any(inner) => CfgExpr::All(inner.iter().map(make_nnf_neg).collect()),
331+
// Convert negated conjunction/disjunction using DeMorgan's Law.
332+
CfgExpr::All(inner) => CfgExpr::Any(inner.iter().map(make_nnf_neg).collect()),
330333
}
331334
}
332335

@@ -335,20 +338,22 @@ fn flatten(expr: CfgExpr) -> CfgExpr {
335338
match expr {
336339
CfgExpr::All(inner) => CfgExpr::All(
337340
inner
338-
.into_iter()
341+
.iter()
339342
.flat_map(|e| match e {
340-
CfgExpr::All(inner) => inner,
341-
_ => vec![e],
343+
CfgExpr::All(inner) => inner.as_ref(),
344+
_ => std::slice::from_ref(e),
342345
})
346+
.cloned()
343347
.collect(),
344348
),
345349
CfgExpr::Any(inner) => CfgExpr::Any(
346350
inner
347-
.into_iter()
351+
.iter()
348352
.flat_map(|e| match e {
349-
CfgExpr::Any(inner) => inner,
350-
_ => vec![e],
353+
CfgExpr::Any(inner) => inner.as_ref(),
354+
_ => std::slice::from_ref(e),
351355
})
356+
.cloned()
352357
.collect(),
353358
),
354359
_ => expr,

src/tools/rust-analyzer/crates/cfg/src/tests.rs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ fn check_dnf(input: &str, expect: Expect) {
2929
DocCommentDesugarMode::ProcMacro,
3030
);
3131
let cfg = CfgExpr::parse(&tt);
32-
let actual = format!("#![cfg({})]", DnfExpr::new(cfg));
32+
let actual = format!("#![cfg({})]", DnfExpr::new(&cfg));
3333
expect.assert_eq(&actual);
3434
}
3535

@@ -43,7 +43,7 @@ fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) {
4343
DocCommentDesugarMode::ProcMacro,
4444
);
4545
let cfg = CfgExpr::parse(&tt);
46-
let dnf = DnfExpr::new(cfg);
46+
let dnf = DnfExpr::new(&cfg);
4747
let why_inactive = dnf.why_inactive(opts).unwrap().to_string();
4848
expect.assert_eq(&why_inactive);
4949
}
@@ -59,7 +59,7 @@ fn check_enable_hints(input: &str, opts: &CfgOptions, expected_hints: &[&str]) {
5959
DocCommentDesugarMode::ProcMacro,
6060
);
6161
let cfg = CfgExpr::parse(&tt);
62-
let dnf = DnfExpr::new(cfg);
62+
let dnf = DnfExpr::new(&cfg);
6363
let hints = dnf.compute_enable_hints(opts).map(|diff| diff.to_string()).collect::<Vec<_>>();
6464
assert_eq!(hints, expected_hints);
6565
}
@@ -82,20 +82,28 @@ fn test_cfg_expr_parser() {
8282

8383
assert_parse_result(
8484
r#"#![cfg(all(foo, bar = "baz"))]"#,
85-
CfgExpr::All(vec![
86-
CfgAtom::Flag(Symbol::intern("foo")).into(),
87-
CfgAtom::KeyValue { key: Symbol::intern("bar"), value: Symbol::intern("baz") }.into(),
88-
]),
85+
CfgExpr::All(
86+
vec![
87+
CfgAtom::Flag(Symbol::intern("foo")).into(),
88+
CfgAtom::KeyValue { key: Symbol::intern("bar"), value: Symbol::intern("baz") }
89+
.into(),
90+
]
91+
.into_boxed_slice(),
92+
),
8993
);
9094

9195
assert_parse_result(
9296
r#"#![cfg(any(not(), all(), , bar = "baz",))]"#,
93-
CfgExpr::Any(vec![
94-
CfgExpr::Not(Box::new(CfgExpr::Invalid)),
95-
CfgExpr::All(vec![]),
96-
CfgExpr::Invalid,
97-
CfgAtom::KeyValue { key: Symbol::intern("bar"), value: Symbol::intern("baz") }.into(),
98-
]),
97+
CfgExpr::Any(
98+
vec![
99+
CfgExpr::Not(Box::new(CfgExpr::Invalid)),
100+
CfgExpr::All(Box::new([])),
101+
CfgExpr::Invalid,
102+
CfgAtom::KeyValue { key: Symbol::intern("bar"), value: Symbol::intern("baz") }
103+
.into(),
104+
]
105+
.into_boxed_slice(),
106+
),
99107
);
100108
}
101109

@@ -235,6 +243,6 @@ fn proptest() {
235243

236244
let mut u = Unstructured::new(&buf);
237245
let cfg = CfgExpr::arbitrary(&mut u).unwrap();
238-
DnfExpr::new(cfg);
246+
DnfExpr::new(&cfg);
239247
}
240248
}

src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,8 @@ where
287287
}
288288
}
289289
let group = match &name {
290-
s if *s == sym::all => CfgExpr::All(preds),
291-
s if *s == sym::any => CfgExpr::Any(preds),
290+
s if *s == sym::all => CfgExpr::All(preds.into_boxed_slice()),
291+
s if *s == sym::any => CfgExpr::Any(preds.into_boxed_slice()),
292292
s if *s == sym::not => {
293293
CfgExpr::Not(Box::new(preds.pop().unwrap_or(CfgExpr::Invalid)))
294294
}
@@ -343,7 +343,7 @@ mod tests {
343343
assert_eq!(node.syntax().text_range().start(), 0.into());
344344

345345
let cfg = parse_from_attr_meta(node.meta().unwrap()).unwrap();
346-
let actual = format!("#![cfg({})]", DnfExpr::new(cfg));
346+
let actual = format!("#![cfg({})]", DnfExpr::new(&cfg));
347347
expect.assert_eq(&actual);
348348
}
349349
#[test]

src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub(crate) fn inactive_code(
1515
return None;
1616
}
1717

18-
let inactive = DnfExpr::new(d.cfg.clone()).why_inactive(&d.opts);
18+
let inactive = DnfExpr::new(&d.cfg).why_inactive(&d.opts);
1919
let mut message = "code is inactive due to #[cfg] directives".to_owned();
2020

2121
if let Some(inactive) = inactive {

src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ fn required_features(cfg_expr: &CfgExpr, features: &mut Vec<String>) {
246246
preds.iter().for_each(|cfg| required_features(cfg, features));
247247
}
248248
CfgExpr::Any(preds) => {
249-
for cfg in preds {
249+
for cfg in preds.iter() {
250250
let len_features = features.len();
251251
required_features(cfg, features);
252252
if len_features != features.len() {

0 commit comments

Comments
 (0)