Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions compiler/rustc_attr_parsing/src/attributes/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,42 +237,39 @@ pub fn eval_config_entry(sess: &Session, cfg_entry: &CfgEntry) -> EvalConfigResu
}
EvalConfigResult::True
}
CfgEntry::Any(subs, span) => {
CfgEntry::Any(subs, _) => {
for sub in subs {
let res = eval_config_entry(sess, sub);
if res.as_bool() {
return res;
}
}
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
EvalConfigResult::False { reason: cfg_entry.clone() }
}
CfgEntry::Not(sub, span) => {
CfgEntry::Not(sub, _) => {
if eval_config_entry(sess, sub).as_bool() {
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
EvalConfigResult::False { reason: cfg_entry.clone() }
} else {
EvalConfigResult::True
}
}
CfgEntry::Bool(b, span) => {
CfgEntry::Bool(b, _) => {
if *b {
EvalConfigResult::True
} else {
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
EvalConfigResult::False { reason: cfg_entry.clone() }
}
}
CfgEntry::NameValue { name, value, span } => {
CfgEntry::NameValue { name, value, span: _ } => {
if sess.config.contains(&(*name, *value)) {
EvalConfigResult::True
} else {
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
EvalConfigResult::False { reason: cfg_entry.clone() }
}
}
CfgEntry::Version(min_version, version_span) => {
CfgEntry::Version(min_version, _) => {
let Some(min_version) = min_version else {
return EvalConfigResult::False {
reason: cfg_entry.clone(),
reason_span: *version_span,
};
return EvalConfigResult::False { reason: cfg_entry.clone() };
};
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
let min_version_ok = if sess.opts.unstable_opts.assume_incomplete_release {
Expand All @@ -283,15 +280,15 @@ pub fn eval_config_entry(sess: &Session, cfg_entry: &CfgEntry) -> EvalConfigResu
if min_version_ok {
EvalConfigResult::True
} else {
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *version_span }
EvalConfigResult::False { reason: cfg_entry.clone() }
}
}
}
}

pub enum EvalConfigResult {
True,
False { reason: CfgEntry, reason_span: Span },
False { reason: CfgEntry },
}

impl EvalConfigResult {
Expand Down
16 changes: 11 additions & 5 deletions compiler/rustc_attr_parsing/src/attributes/cfg_select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ use rustc_span::{ErrorGuaranteed, Span, Symbol, sym};
use crate::attributes::AttributeSafety;
use crate::parser::{AllowExprMetavar, MetaItemOrLitParser};
use crate::{
AttributeParser, AttributeTemplate, ParsedDescription, ShouldEmit, diagnostics, parse_cfg_entry,
AttributeParser, AttributeTemplate, EvalConfigResult, ParsedDescription, ShouldEmit,
diagnostics, parse_cfg_entry,
};

#[derive(Clone)]
Expand Down Expand Up @@ -49,11 +50,16 @@ impl CfgSelectBranches {
/// or the wildcard if none of the reachable branches satisfied the predicate.
pub fn pop_first_match<F>(&mut self, predicate: F) -> Option<(CfgEntry, TokenStream, Span)>
where
F: Fn(&CfgEntry) -> bool,
F: Fn(&CfgEntry) -> EvalConfigResult,
{
for (index, (cfg, _, _)) in self.reachable.iter().enumerate() {
if predicate(cfg) {
return Some(self.reachable.remove(index));
for (index, (cfg, _, _)) in self.reachable.iter_mut().enumerate() {
match predicate(cfg) {
EvalConfigResult::True => {
return Some(self.reachable.remove(index));
}
EvalConfigResult::False { reason } => {
*cfg = reason;
}
}
}

Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_builtin_macros/src/cfg_select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AttrKind, Expr, SyntheticAttr, ast};
use rustc_attr_ir::CfgEntry;
use rustc_attr_parsing as attr;
use rustc_attr_parsing::{CfgSelectBranches, EvalConfigResult, parse_cfg_select};
use rustc_attr_parsing::{CfgSelectBranches, parse_cfg_select};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult};
use rustc_expand::expand::DeclaredIdents;
use rustc_span::{Ident, Span, sym};
Expand Down Expand Up @@ -129,9 +129,7 @@ pub(super) fn expand_cfg_select<'cx>(
) {
Ok(mut branches) => {
if let Some((cfg_entry, selected_tts, selected_span)) =
branches.pop_first_match(|cfg| {
matches!(attr::eval_config_entry(ecx.sess, cfg), EvalConfigResult::True)
})
branches.pop_first_match(|cfg| attr::eval_config_entry(ecx.sess, cfg))
{
let mac = CfgSelectResult {
ecx,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2366,13 +2366,13 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
let res = self.expand_cfg_true(&mut node, attr, pos);
match res {
EvalConfigResult::True => continue,
EvalConfigResult::False { reason, reason_span } => {
EvalConfigResult::False { reason } => {
for ident in node.declared_idents() {
self.cx.resolver.append_stripped_cfg_item(
self.cx.current_expansion.lint_node_id,
ident,
reason.clone(),
reason_span,
reason.span(),
)
}
}
Expand Down
29 changes: 29 additions & 0 deletions tests/ui/macros/cfg_select.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//@ compile-flags: --check-cfg 'cfg(feature, values("meow"))'
#![crate_type = "lib"]
#![warn(unreachable_cfg_select_predicates)] // Unused warnings are disabled by default in UI tests.

Expand Down Expand Up @@ -251,3 +252,31 @@ cfg_select! {
debug_assertions => {}
_ => {}
}

cfg_select! {
all(true, false) => {
struct Thing1;
}
_ => {}
}

cfg_select! {
feature = "meow" => {
struct Thing2;
}
_ => {}
}

cfg_select! {
all(true, feature = "meow") => {
struct Thing2;
}
_ => {}
}

fn usages() {
let t1: Thing1;
//~^ ERROR cannot find type `Thing1` in this scope [E0425]
let t2: Thing2;
//~^ ERROR cannot find type `Thing2` in this scope [E0425]
}
Loading
Loading