3 use rustc_ast::{LitKind, MetaItemLit, Path, StrStyle};
4 use rustc_span::create_default_session_globals_then;
5 use rustc_span::symbol::{kw, Ident, Symbol};
6 use rustc_span::DUMMY_SP;
8 fn word_cfg(s: &str) -> Cfg {
9 Cfg::Cfg(Symbol::intern(s), None)
12 fn name_value_cfg(name: &str, value: &str) -> Cfg {
13 Cfg::Cfg(Symbol::intern(name), Some(Symbol::intern(value)))
16 fn dummy_meta_item_word(name: &str) -> MetaItem {
18 path: Path::from_ident(Ident::from_str(name)),
19 kind: MetaItemKind::Word,
24 fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> MetaItem {
25 let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP };
27 path: Path::from_ident(Ident::from_str(name)),
28 kind: MetaItemKind::NameValue(lit),
33 macro_rules! dummy_meta_item_list {
34 ($name:ident, [$($list:ident),* $(,)?]) => {
36 path: Path::from_ident(Ident::from_str(stringify!($name))),
37 kind: MetaItemKind::List(vec![
39 NestedMetaItem::MetaItem(
40 dummy_meta_item_word(stringify!($list)),
48 ($name:ident, [$($list:expr),* $(,)?]) => {
50 path: Path::from_ident(Ident::from_str(stringify!($name))),
51 kind: MetaItemKind::List(vec![
53 NestedMetaItem::MetaItem($list),
63 create_default_session_globals_then(|| {
64 assert_eq!(!Cfg::False, Cfg::True);
65 assert_eq!(!Cfg::True, Cfg::False);
66 assert_eq!(!word_cfg("test"), Cfg::Not(Box::new(word_cfg("test"))));
68 !Cfg::All(vec![word_cfg("a"), word_cfg("b")]),
69 Cfg::Not(Box::new(Cfg::All(vec![word_cfg("a"), word_cfg("b")])))
72 !Cfg::Any(vec![word_cfg("a"), word_cfg("b")]),
73 Cfg::Not(Box::new(Cfg::Any(vec![word_cfg("a"), word_cfg("b")])))
75 assert_eq!(!Cfg::Not(Box::new(word_cfg("test"))), word_cfg("test"));
81 create_default_session_globals_then(|| {
82 let mut x = Cfg::False;
84 assert_eq!(x, Cfg::False);
88 assert_eq!(x, Cfg::False);
90 x = word_cfg("test2");
92 assert_eq!(x, word_cfg("test2"));
95 x &= word_cfg("test3");
96 assert_eq!(x, word_cfg("test3"));
98 x &= word_cfg("test3");
99 assert_eq!(x, word_cfg("test3"));
101 x &= word_cfg("test4");
102 assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4")]));
104 x &= word_cfg("test4");
105 assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4")]));
107 x &= word_cfg("test5");
108 assert_eq!(x, Cfg::All(vec![word_cfg("test3"), word_cfg("test4"), word_cfg("test5")]));
110 x &= Cfg::All(vec![word_cfg("test6"), word_cfg("test7")]);
122 x &= Cfg::All(vec![word_cfg("test6"), word_cfg("test7")]);
134 let mut y = Cfg::Any(vec![word_cfg("a"), word_cfg("b")]);
144 Cfg::Any(vec![word_cfg("a"), word_cfg("b")]),
148 let mut z = word_cfg("test8");
149 z &= Cfg::All(vec![word_cfg("test9"), word_cfg("test10")]);
150 assert_eq!(z, Cfg::All(vec![word_cfg("test9"), word_cfg("test10"), word_cfg("test8")]));
152 let mut z = word_cfg("test11");
153 z &= Cfg::All(vec![word_cfg("test11"), word_cfg("test12")]);
154 assert_eq!(z, Cfg::All(vec![word_cfg("test11"), word_cfg("test12")]));
157 word_cfg("a") & word_cfg("b") & word_cfg("c"),
158 Cfg::All(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")])
165 create_default_session_globals_then(|| {
166 let mut x = Cfg::True;
168 assert_eq!(x, Cfg::True);
170 x = word_cfg("test");
172 assert_eq!(x, word_cfg("test"));
174 x = word_cfg("test2");
176 assert_eq!(x, word_cfg("test2"));
179 x |= word_cfg("test3");
180 assert_eq!(x, word_cfg("test3"));
182 x |= word_cfg("test3");
183 assert_eq!(x, word_cfg("test3"));
185 x |= word_cfg("test4");
186 assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4")]));
188 x |= word_cfg("test4");
189 assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4")]));
191 x |= word_cfg("test5");
192 assert_eq!(x, Cfg::Any(vec![word_cfg("test3"), word_cfg("test4"), word_cfg("test5")]));
194 x |= Cfg::Any(vec![word_cfg("test6"), word_cfg("test7")]);
206 x |= Cfg::Any(vec![word_cfg("test6"), word_cfg("test7")]);
218 let mut y = Cfg::All(vec![word_cfg("a"), word_cfg("b")]);
228 Cfg::All(vec![word_cfg("a"), word_cfg("b")]),
232 let mut z = word_cfg("test8");
233 z |= Cfg::Any(vec![word_cfg("test9"), word_cfg("test10")]);
234 assert_eq!(z, Cfg::Any(vec![word_cfg("test9"), word_cfg("test10"), word_cfg("test8")]));
236 let mut z = word_cfg("test11");
237 z |= Cfg::Any(vec![word_cfg("test11"), word_cfg("test12")]);
238 assert_eq!(z, Cfg::Any(vec![word_cfg("test11"), word_cfg("test12")]));
241 word_cfg("a") | word_cfg("b") | word_cfg("c"),
242 Cfg::Any(vec![word_cfg("a"), word_cfg("b"), word_cfg("c")])
249 create_default_session_globals_then(|| {
250 let mi = dummy_meta_item_word("all");
251 assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
253 let done = Symbol::intern("done");
254 let mi = dummy_meta_item_name_value("all", done, LitKind::Str(done, StrStyle::Cooked));
255 assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done")));
257 let mi = dummy_meta_item_list!(all, [a, b]);
258 assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b")));
260 let mi = dummy_meta_item_list!(any, [a, b]);
261 assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") | word_cfg("b")));
263 let mi = dummy_meta_item_list!(not, [a]);
264 assert_eq!(Cfg::parse(&mi), Ok(!word_cfg("a")));
266 let mi = dummy_meta_item_list!(
268 [dummy_meta_item_list!(
270 [dummy_meta_item_word("a"), dummy_meta_item_list!(all, [b, c]),]
273 assert_eq!(Cfg::parse(&mi), Ok(!(word_cfg("a") | (word_cfg("b") & word_cfg("c")))));
275 let mi = dummy_meta_item_list!(all, [a, b, c]);
276 assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b") & word_cfg("c")));
281 fn test_parse_err() {
282 create_default_session_globals_then(|| {
283 let mi = dummy_meta_item_name_value("foo", kw::False, LitKind::Bool(false));
284 assert!(Cfg::parse(&mi).is_err());
286 let mi = dummy_meta_item_list!(not, [a, b]);
287 assert!(Cfg::parse(&mi).is_err());
289 let mi = dummy_meta_item_list!(not, []);
290 assert!(Cfg::parse(&mi).is_err());
292 let mi = dummy_meta_item_list!(foo, []);
293 assert!(Cfg::parse(&mi).is_err());
295 let mi = dummy_meta_item_list!(
297 [dummy_meta_item_list!(foo, []), dummy_meta_item_word("b"),]
299 assert!(Cfg::parse(&mi).is_err());
301 let mi = dummy_meta_item_list!(
303 [dummy_meta_item_word("a"), dummy_meta_item_list!(foo, []),]
305 assert!(Cfg::parse(&mi).is_err());
307 let mi = dummy_meta_item_list!(not, [dummy_meta_item_list!(foo, []),]);
308 assert!(Cfg::parse(&mi).is_err());
313 fn test_render_short_html() {
314 create_default_session_globals_then(|| {
315 assert_eq!(word_cfg("unix").render_short_html(), "Unix");
316 assert_eq!(name_value_cfg("target_os", "macos").render_short_html(), "macOS");
317 assert_eq!(name_value_cfg("target_pointer_width", "16").render_short_html(), "16-bit");
318 assert_eq!(name_value_cfg("target_endian", "little").render_short_html(), "Little-endian");
319 assert_eq!((!word_cfg("windows")).render_short_html(), "Non-Windows");
321 (word_cfg("unix") & word_cfg("windows")).render_short_html(),
324 assert_eq!((word_cfg("unix") | word_cfg("windows")).render_short_html(), "Unix or Windows");
326 (word_cfg("unix") & word_cfg("windows") & word_cfg("debug_assertions"))
327 .render_short_html(),
328 "Unix and Windows and debug-assertions enabled"
331 (word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions"))
332 .render_short_html(),
333 "Unix or Windows or debug-assertions enabled"
336 (!(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions")))
337 .render_short_html(),
338 "Neither Unix nor Windows nor debug-assertions enabled"
341 ((word_cfg("unix") & name_value_cfg("target_arch", "x86_64"))
342 | (word_cfg("windows") & name_value_cfg("target_pointer_width", "64")))
343 .render_short_html(),
344 "Unix and x86-64, or Windows and 64-bit"
347 (!(word_cfg("unix") & word_cfg("windows"))).render_short_html(),
348 "Not (Unix and Windows)"
351 ((word_cfg("debug_assertions") | word_cfg("windows")) & word_cfg("unix"))
352 .render_short_html(),
353 "(Debug-assertions enabled or Windows) and Unix"
356 name_value_cfg("target_feature", "sse2").render_short_html(),
360 (name_value_cfg("target_arch", "x86_64") & name_value_cfg("target_feature", "sse2"))
361 .render_short_html(),
362 "x86-64 and <code>sse2</code>"
368 fn test_render_long_html() {
369 create_default_session_globals_then(|| {
370 assert_eq!(word_cfg("unix").render_long_html(), "Available on <strong>Unix</strong> only.");
372 name_value_cfg("target_os", "macos").render_long_html(),
373 "Available on <strong>macOS</strong> only."
376 name_value_cfg("target_os", "wasi").render_long_html(),
377 "Available on <strong>WASI</strong> only."
380 name_value_cfg("target_pointer_width", "16").render_long_html(),
381 "Available on <strong>16-bit</strong> only."
384 name_value_cfg("target_endian", "little").render_long_html(),
385 "Available on <strong>little-endian</strong> only."
388 (!word_cfg("windows")).render_long_html(),
389 "Available on <strong>non-Windows</strong> only."
392 (word_cfg("unix") & word_cfg("windows")).render_long_html(),
393 "Available on <strong>Unix and Windows</strong> only."
396 (word_cfg("unix") | word_cfg("windows")).render_long_html(),
397 "Available on <strong>Unix or Windows</strong> only."
400 (word_cfg("unix") & word_cfg("windows") & word_cfg("debug_assertions"))
402 "Available on <strong>Unix and Windows and debug-assertions enabled</strong> only."
405 (word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions"))
407 "Available on <strong>Unix or Windows or debug-assertions enabled</strong> only."
410 (!(word_cfg("unix") | word_cfg("windows") | word_cfg("debug_assertions")))
412 "Available on <strong>neither Unix nor Windows nor debug-assertions enabled</strong>."
415 ((word_cfg("unix") & name_value_cfg("target_arch", "x86_64"))
416 | (word_cfg("windows") & name_value_cfg("target_pointer_width", "64")))
418 "Available on <strong>Unix and x86-64, or Windows and 64-bit</strong> only."
421 (!(word_cfg("unix") & word_cfg("windows"))).render_long_html(),
422 "Available on <strong>not (Unix and Windows)</strong>."
425 ((word_cfg("debug_assertions") | word_cfg("windows")) & word_cfg("unix"))
427 "Available on <strong>(debug-assertions enabled or Windows) and Unix</strong> only."
430 name_value_cfg("target_feature", "sse2").render_long_html(),
431 "Available with <strong>target feature <code>sse2</code></strong> only."
434 (name_value_cfg("target_arch", "x86_64") & name_value_cfg("target_feature", "sse2"))
436 "Available on <strong>x86-64 and target feature <code>sse2</code></strong> only."
442 fn test_simplify_with() {
443 // This is a tiny subset of things that could be simplified, but it likely covers 90% of
444 // real world usecases well.
445 create_default_session_globals_then(|| {
446 let foo = word_cfg("foo");
447 let bar = word_cfg("bar");
448 let baz = word_cfg("baz");
449 let quux = word_cfg("quux");
451 let foobar = Cfg::All(vec![foo.clone(), bar.clone()]);
452 let barbaz = Cfg::All(vec![bar.clone(), baz.clone()]);
453 let foobarbaz = Cfg::All(vec![foo.clone(), bar.clone(), baz.clone()]);
454 let bazquux = Cfg::All(vec![baz.clone(), quux.clone()]);
456 // Unrelated cfgs don't affect each other
457 assert_eq!(foo.simplify_with(&bar).as_ref(), Some(&foo));
458 assert_eq!(foobar.simplify_with(&bazquux).as_ref(), Some(&foobar));
460 // Identical cfgs are eliminated
461 assert_eq!(foo.simplify_with(&foo), None);
462 assert_eq!(foobar.simplify_with(&foobar), None);
464 // Multiple cfgs eliminate a single assumed cfg
465 assert_eq!(foobar.simplify_with(&foo).as_ref(), Some(&bar));
466 assert_eq!(foobar.simplify_with(&bar).as_ref(), Some(&foo));
468 // A single cfg is eliminated by multiple assumed cfg containing it
469 assert_eq!(foo.simplify_with(&foobar), None);
471 // Multiple cfgs eliminate the matching subset of multiple assumed cfg
472 assert_eq!(foobar.simplify_with(&barbaz).as_ref(), Some(&foo));
473 assert_eq!(foobar.simplify_with(&foobarbaz), None);