diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index e9ace7088d8f0..8102208ec519d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -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 { @@ -283,7 +280,7 @@ 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() } } } } @@ -291,7 +288,7 @@ pub fn eval_config_entry(sess: &Session, cfg_entry: &CfgEntry) -> EvalConfigResu pub enum EvalConfigResult { True, - False { reason: CfgEntry, reason_span: Span }, + False { reason: CfgEntry }, } impl EvalConfigResult { diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index 68de0a53e918b..4333559afb1c0 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -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)] @@ -49,11 +50,16 @@ impl CfgSelectBranches { /// or the wildcard if none of the reachable branches satisfied the predicate. pub fn pop_first_match(&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; + } } } diff --git a/compiler/rustc_builtin_macros/src/cfg_select.rs b/compiler/rustc_builtin_macros/src/cfg_select.rs index 7202c56efed4e..69c3802ceafae 100644 --- a/compiler/rustc_builtin_macros/src/cfg_select.rs +++ b/compiler/rustc_builtin_macros/src/cfg_select.rs @@ -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}; @@ -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, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 024ee2871b125..268011a50eb14 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -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(), ) } } diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 0f03a8a99c4fb..0d5fcec971550 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -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. @@ -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] +} diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index 8e09aa4da93f3..9af74456367f2 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -1,5 +1,5 @@ error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:161:1 + --> $DIR/cfg_select.rs:162:1 | LL | / cfg_select! { LL | | @@ -8,73 +8,73 @@ LL | | } | |_^ error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:166:1 + --> $DIR/cfg_select.rs:167:1 | LL | cfg_select! {} | ^^^^^^^^^^^^^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>` - --> $DIR/cfg_select.rs:170:5 + --> $DIR/cfg_select.rs:171:5 | LL | => {} | ^^ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression - --> $DIR/cfg_select.rs:175:5 + --> $DIR/cfg_select.rs:176:5 | LL | () => {} | ^^ expressions are not allowed here error[E0565]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:180:5 + --> $DIR/cfg_select.rs:181:5 | LL | "str" => {} | ^^^^^ expected a valid identifier here error[E0565]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:185:5 + --> $DIR/cfg_select.rs:186:5 | LL | a::b => {} | ^^^^ expected a valid identifier here error[E0539]: malformed `cfg_select` macro input - --> $DIR/cfg_select.rs:190:5 + --> $DIR/cfg_select.rs:191:5 | LL | a() => {} | ^^^ valid arguments are `any`, `all`, `not` or `target` error: expected one of `(`, `::`, `=>`, or `=`, found `+` - --> $DIR/cfg_select.rs:195:7 + --> $DIR/cfg_select.rs:196:7 | LL | a + 1 => {} | ^ expected one of `(`, `::`, `=>`, or `=` error: expected one of `(`, `::`, `=>`, or `=`, found `!` - --> $DIR/cfg_select.rs:201:8 + --> $DIR/cfg_select.rs:202:8 | LL | cfg!() => {} | ^ expected one of `(`, `::`, `=>`, or `=` error: doc comments are not allowed on `cfg_select` branches - --> $DIR/cfg_select.rs:208:5 + --> $DIR/cfg_select.rs:209:5 | LL | /// doc comment | ^^^^^^^^^^^^^^^ error: doc comments are not allowed on `cfg_select` branches - --> $DIR/cfg_select.rs:211:5 + --> $DIR/cfg_select.rs:212:5 | LL | /// doc comment | ^^^^^^^^^^^^^^^ error: attributes are not allowed on `cfg_select` branches - --> $DIR/cfg_select.rs:217:5 + --> $DIR/cfg_select.rs:218:5 | LL | #[cfg(false)] | ^^^^^^^^^^^^^ error: an inner attribute is not permitted in this context - --> $DIR/cfg_select.rs:224:5 + --> $DIR/cfg_select.rs:225:5 | LL | #![cfg(false)] | ^^^^^^^^^^^^^^ @@ -83,7 +83,7 @@ LL | #![cfg(false)] = note: outer attributes, like `#[test]`, annotate the item following them error[E0753]: expected outer doc comment - --> $DIR/cfg_select.rs:231:5 + --> $DIR/cfg_select.rs:232:5 | LL | //! inner doc comment | ^^^^^^^^^^^^^^^^^^^^^ @@ -96,7 +96,7 @@ LL + // inner doc comment | error: doc comments are not allowed on `cfg_select` branches - --> $DIR/cfg_select.rs:239:5 + --> $DIR/cfg_select.rs:240:5 | LL | /// line1 | ^^^^^^^^^ @@ -105,7 +105,7 @@ LL | /// line3 | ^^^^^^^^^ error[E0753]: expected outer doc comment - --> $DIR/cfg_select.rs:249:5 + --> $DIR/cfg_select.rs:250:5 | LL | //! inner doc comment | ^^^^^^^^^^^^^^^^^^^^^ @@ -118,13 +118,48 @@ LL + // inner doc comment | error: doc comments are not allowed on `cfg_select` branches - --> $DIR/cfg_select.rs:247:5 + --> $DIR/cfg_select.rs:248:5 | LL | /// outer doc comment | ^^^^^^^^^^^^^^^^^^^^^ +error[E0425]: cannot find type `Thing1` in this scope + --> $DIR/cfg_select.rs:278:13 + | +LL | let t1: Thing1; + | ^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/cfg_select.rs:258:16 + | +LL | all(true, false) => { + | ----- the item is gated here +LL | struct Thing1; + | ^^^^^^ + +error[E0425]: cannot find type `Thing2` in this scope + --> $DIR/cfg_select.rs:280:13 + | +LL | let t2: Thing2; + | ^^^^^^ not found in this scope + | +note: found an item that was configured out + --> $DIR/cfg_select.rs:265:16 + | +LL | feature = "meow" => { + | ---------------- the item is gated behind the `meow` feature +LL | struct Thing2; + | ^^^^^^ +note: found an item that was configured out + --> $DIR/cfg_select.rs:272:16 + | +LL | all(true, feature = "meow") => { + | ---------------- the item is gated behind the `meow` feature +LL | struct Thing2; + | ^^^^^^ + warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:136:5 + --> $DIR/cfg_select.rs:137:5 | LL | _ => {} | - always matches @@ -132,13 +167,13 @@ LL | true => {} | ^^^^ this configuration predicate is never reached | note: the lint level is defined here - --> $DIR/cfg_select.rs:2:9 + --> $DIR/cfg_select.rs:3:9 | LL | #![warn(unreachable_cfg_select_predicates)] // Unused warnings are disabled by default in UI tests. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:142:5 + --> $DIR/cfg_select.rs:143:5 | LL | true => {} | ---- always matches @@ -146,36 +181,36 @@ LL | _ => {} | ^ this configuration predicate is never reached warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:149:5 + --> $DIR/cfg_select.rs:150:5 | LL | _ => {} | ^ this configuration predicate is never reached warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:155:5 + --> $DIR/cfg_select.rs:156:5 | LL | test => {} | ^^^^ this configuration predicate is never reached warning: unreachable configuration predicate - --> $DIR/cfg_select.rs:157:5 + --> $DIR/cfg_select.rs:158:5 | LL | _ => {} | ^ this configuration predicate is never reached warning: unexpected `cfg` condition name: `a` - --> $DIR/cfg_select.rs:195:5 + --> $DIR/cfg_select.rs:196:5 | LL | a + 1 => {} | ^ help: found config with similar value: `target_feature = "a"` | - = help: expected names are: `FALSE` and `test` and 34 more + = help: expected names are: `FALSE`, `feature`, and `test` and 34 more = help: to expect this configuration use `--check-cfg=cfg(a)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `cfg` - --> $DIR/cfg_select.rs:201:5 + --> $DIR/cfg_select.rs:202:5 | LL | cfg!() => {} | ^^^ @@ -183,7 +218,7 @@ LL | cfg!() => {} = help: to expect this configuration use `--check-cfg=cfg(cfg)` = note: see for more information about checking conditional configuration -error: aborting due to 17 previous errors; 7 warnings emitted +error: aborting due to 19 previous errors; 7 warnings emitted -Some errors have detailed explanations: E0539, E0565, E0753. -For more information about an error, try `rustc --explain E0539`. +Some errors have detailed explanations: E0425, E0539, E0565, E0753. +For more information about an error, try `rustc --explain E0425`.