From c99f29b29fa4115436c352a921f9963b173b5608 Mon Sep 17 00:00:00 2001 From: Urgau Date: Thu, 19 Sep 2024 10:13:14 +0200 Subject: [PATCH] Implement boolean lit support in cfg predicates --- compiler/rustc_ast/src/attr/mod.rs | 10 +++++++ compiler/rustc_attr/src/builtin.rs | 3 +- compiler/rustc_expand/src/config.rs | 6 ++-- compiler/rustc_metadata/src/native_libs.rs | 2 +- .../traits/on_unimplemented.rs | 4 ++- tests/ui/cfg/true-false.rs | 29 +++++++++++++++++++ 6 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 tests/ui/cfg/true-false.rs diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 124d0acfa49..338d50cb394 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -527,6 +527,16 @@ impl NestedMetaItem { } } + /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem` or if it's + /// `NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Bool(_), .. })`. + pub fn meta_item_or_bool(&self) -> Option<&NestedMetaItem> { + match self { + NestedMetaItem::MetaItem(_item) => Some(self), + NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Bool(_), .. }) => Some(self), + _ => None, + } + } + /// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`. pub fn meta_item(&self) -> Option<&MetaItem> { match self { diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 37f70c21869..930fdeb975d 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -603,6 +603,7 @@ pub fn eval_condition( let cfg = match cfg { ast::NestedMetaItem::MetaItem(meta_item) => meta_item, + ast::NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => return *b, _ => { dcx.emit_err(session_diagnostics::UnsupportedLiteral { span: cfg.span(), @@ -649,7 +650,7 @@ pub fn eval_condition( } ast::MetaItemKind::List(mis) => { for mi in mis.iter() { - if !mi.is_meta_item() { + if mi.meta_item_or_bool().is_none() { dcx.emit_err(session_diagnostics::UnsupportedLiteral { span: mi.span(), reason: UnsupportedLiteralReason::Generic, diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 8ea4f901368..af56169fd60 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -466,9 +466,9 @@ pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a Nest sess.dcx().emit_err(InvalidCfg::MultiplePredicates { span: l.span() }); None } - Some([single]) => match single.is_meta_item() { - true => Some(single), - false => { + Some([single]) => match single.meta_item_or_bool() { + Some(meta_item) => Some(meta_item), + None => { sess.dcx().emit_err(InvalidCfg::PredicateLiteral { span: single.span() }); None } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 373b109189e..c7953d50406 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -309,7 +309,7 @@ impl<'tcx> Collector<'tcx> { .emit_err(errors::LinkCfgSinglePredicate { span: item.span() }); continue; }; - if !link_cfg.is_meta_item() { + let Some(link_cfg) = link_cfg.meta_item_or_bool() else { sess.dcx() .emit_err(errors::LinkCfgSinglePredicate { span: item.span() }); continue; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index f2efc5ee47d..e9a2c5b8d8e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -413,7 +413,9 @@ impl<'tcx> OnUnimplementedDirective { } else { let cond = item_iter .next() - .ok_or_else(|| tcx.dcx().emit_err(EmptyOnClauseInOnUnimplemented { span }))?; + .ok_or_else(|| tcx.dcx().emit_err(EmptyOnClauseInOnUnimplemented { span }))? + .meta_item_or_bool() + .ok_or_else(|| tcx.dcx().emit_err(InvalidOnClauseInOnUnimplemented { span }))?; attr::eval_condition(cond, &tcx.sess, Some(tcx.features()), &mut |cfg| { if let Some(value) = cfg.value && let Err(guar) = parse_value(value, cfg.span) diff --git a/tests/ui/cfg/true-false.rs b/tests/ui/cfg/true-false.rs new file mode 100644 index 00000000000..0bd1cf427fa --- /dev/null +++ b/tests/ui/cfg/true-false.rs @@ -0,0 +1,29 @@ +//@ run-pass + +#![feature(link_cfg)] + +#[cfg(true)] +fn foo() -> bool { + cfg!(true) +} + +#[cfg(false)] +fn foo() -> bool { + cfg!(false) +} + +#[cfg_attr(true, cfg(false))] +fn foo() {} + +#[link(name = "foo", cfg(false))] +extern "C" {} + +fn main() { + assert!(foo()); + assert!(cfg!(true)); + assert!(!cfg!(false)); + assert!(cfg!(not(false))); + assert!(cfg!(all(true))); + assert!(cfg!(any(true))); + assert!(!cfg!(not(true))); +}