Skip to content

Commit 493ed7a

Browse files
authored
Rollup merge of #94433 - Urgau:check-cfg-allowness, r=petrochenkov
Improve allowness of the unexpected_cfgs lint This pull-request improve the allowness (`#[allow(...)]`) of the `unexpected_cfgs` lint. Before this PR only crate level `#![allow(unexpected_cfgs)]` worked, now with this PR it also work when put around `cfg!` or if it is in a upper level. Making it work ~for the attributes `cfg`, `cfg_attr`, ...~ for the same level is awkward as the current code is design to give "Some parent node that is close to this macro call" (cf. https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/base/struct.ExpansionData.html) meaning that allow on the same line as an attribute won't work. I'm note even sure if this would be possible. Found while working on #94298. r? ````````@petrochenkov````````
2 parents 7537b20 + 765205b commit 493ed7a

File tree

14 files changed

+122
-26
lines changed

14 files changed

+122
-26
lines changed

compiler/rustc_attr/src/builtin.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
//! Parsing and validation of builtin attributes
22
33
use rustc_ast as ast;
4-
use rustc_ast::node_id::CRATE_NODE_ID;
5-
use rustc_ast::{Attribute, Lit, LitKind, MetaItem, MetaItemKind, NestedMetaItem};
4+
use rustc_ast::{Attribute, Lit, LitKind, MetaItem, MetaItemKind, NestedMetaItem, NodeId};
65
use rustc_ast_pretty::pprust;
76
use rustc_errors::{struct_span_err, Applicability};
87
use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
@@ -436,7 +435,12 @@ pub fn find_crate_name(sess: &Session, attrs: &[Attribute]) -> Option<Symbol> {
436435
}
437436

438437
/// Tests if a cfg-pattern matches the cfg set
439-
pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool {
438+
pub fn cfg_matches(
439+
cfg: &ast::MetaItem,
440+
sess: &ParseSess,
441+
lint_node_id: NodeId,
442+
features: Option<&Features>,
443+
) -> bool {
440444
eval_condition(cfg, sess, features, &mut |cfg| {
441445
try_gate_cfg(cfg, sess, features);
442446
let error = |span, msg| {
@@ -470,7 +474,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
470474
sess.buffer_lint_with_diagnostic(
471475
UNEXPECTED_CFGS,
472476
cfg.span,
473-
CRATE_NODE_ID,
477+
lint_node_id,
474478
"unexpected `cfg` condition name",
475479
BuiltinLintDiagnostics::UnexpectedCfg(ident.span, name, None),
476480
);
@@ -482,7 +486,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
482486
sess.buffer_lint_with_diagnostic(
483487
UNEXPECTED_CFGS,
484488
cfg.span,
485-
CRATE_NODE_ID,
489+
lint_node_id,
486490
"unexpected `cfg` condition value",
487491
BuiltinLintDiagnostics::UnexpectedCfg(
488492
cfg.name_value_literal_span().unwrap(),

compiler/rustc_builtin_macros/src/cfg.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@ pub fn expand_cfg(
1919

2020
match parse_cfg(cx, sp, tts) {
2121
Ok(cfg) => {
22-
let matches_cfg = attr::cfg_matches(&cfg, &cx.sess.parse_sess, cx.ecfg.features);
22+
let matches_cfg = attr::cfg_matches(
23+
&cfg,
24+
&cx.sess.parse_sess,
25+
cx.current_expansion.lint_node_id,
26+
cx.ecfg.features,
27+
);
2328
MacEager::expr(cx.expr_bool(sp, matches_cfg))
2429
}
2530
Err(mut err) => {

compiler/rustc_builtin_macros/src/cfg_eval.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_ast::mut_visit::MutVisitor;
55
use rustc_ast::ptr::P;
66
use rustc_ast::tokenstream::CanSynthesizeMissingTokens;
77
use rustc_ast::visit::Visitor;
8+
use rustc_ast::NodeId;
89
use rustc_ast::{mut_visit, visit};
910
use rustc_ast::{AstLike, Attribute};
1011
use rustc_expand::base::{Annotatable, ExtCtxt};
@@ -26,15 +27,16 @@ crate fn expand(
2627
) -> Vec<Annotatable> {
2728
check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
2829
warn_on_duplicate_attribute(&ecx, &annotatable, sym::cfg_eval);
29-
vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable)]
30+
vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable, ecx.current_expansion.lint_node_id)]
3031
}
3132

3233
crate fn cfg_eval(
3334
sess: &Session,
3435
features: Option<&Features>,
3536
annotatable: Annotatable,
37+
lint_node_id: NodeId,
3638
) -> Annotatable {
37-
CfgEval { cfg: &mut StripUnconfigured { sess, features, config_tokens: true } }
39+
CfgEval { cfg: &mut StripUnconfigured { sess, features, config_tokens: true, lint_node_id } }
3840
.configure_annotatable(annotatable)
3941
// Since the item itself has already been configured by the `InvocationCollector`,
4042
// we know that fold result vector will contain exactly one element.

compiler/rustc_builtin_macros/src/derive.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,12 @@ impl MultiItemModifier for Expander {
6464
match &mut resolutions[..] {
6565
[] => {}
6666
[(_, first_item, _), others @ ..] => {
67-
*first_item = cfg_eval(sess, features, item.clone());
67+
*first_item = cfg_eval(
68+
sess,
69+
features,
70+
item.clone(),
71+
ecx.current_expansion.lint_node_id,
72+
);
6873
for (_, item, _) in others {
6974
*item = first_item.clone();
7075
}

compiler/rustc_codegen_ssa/src/back/link.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_arena::TypedArena;
2+
use rustc_ast::CRATE_NODE_ID;
23
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
34
use rustc_data_structures::memmap::Mmap;
45
use rustc_data_structures::temp_dir::MaybeTempDir;
@@ -2434,7 +2435,7 @@ fn add_upstream_native_libraries(
24342435

24352436
fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
24362437
match lib.cfg {
2437-
Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, None),
2438+
Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None),
24382439
None => true,
24392440
}
24402441
}

compiler/rustc_expand/src/config.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_ast::token::{DelimToken, Token, TokenKind};
55
use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
66
use rustc_ast::tokenstream::{DelimSpan, Spacing};
77
use rustc_ast::tokenstream::{LazyTokenStream, TokenTree};
8+
use rustc_ast::NodeId;
89
use rustc_ast::{self as ast, AstLike, AttrStyle, Attribute, MetaItem};
910
use rustc_attr as attr;
1011
use rustc_data_structures::fx::FxHashMap;
@@ -29,6 +30,7 @@ pub struct StripUnconfigured<'a> {
2930
/// This is only used for the input to derive macros,
3031
/// which needs eager expansion of `cfg` and `cfg_attr`
3132
pub config_tokens: bool,
33+
pub lint_node_id: NodeId,
3234
}
3335

3436
fn get_features(
@@ -196,8 +198,13 @@ fn get_features(
196198
}
197199

198200
// `cfg_attr`-process the crate's attributes and compute the crate's features.
199-
pub fn features(sess: &Session, mut krate: ast::Crate) -> (ast::Crate, Features) {
200-
let mut strip_unconfigured = StripUnconfigured { sess, features: None, config_tokens: false };
201+
pub fn features(
202+
sess: &Session,
203+
mut krate: ast::Crate,
204+
lint_node_id: NodeId,
205+
) -> (ast::Crate, Features) {
206+
let mut strip_unconfigured =
207+
StripUnconfigured { sess, features: None, config_tokens: false, lint_node_id };
201208

202209
let unconfigured_attrs = krate.attrs.clone();
203210
let diag = &sess.parse_sess.span_diagnostic;
@@ -353,7 +360,12 @@ impl<'a> StripUnconfigured<'a> {
353360
);
354361
}
355362

356-
if !attr::cfg_matches(&cfg_predicate, &self.sess.parse_sess, self.features) {
363+
if !attr::cfg_matches(
364+
&cfg_predicate,
365+
&self.sess.parse_sess,
366+
self.lint_node_id,
367+
self.features,
368+
) {
357369
return vec![];
358370
}
359371

@@ -445,7 +457,7 @@ impl<'a> StripUnconfigured<'a> {
445457
}
446458
};
447459
parse_cfg(&meta_item, &self.sess).map_or(true, |meta_item| {
448-
attr::cfg_matches(&meta_item, &self.sess.parse_sess, self.features)
460+
attr::cfg_matches(&meta_item, &self.sess.parse_sess, self.lint_node_id, self.features)
449461
})
450462
}
451463

compiler/rustc_expand/src/expand.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -551,11 +551,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
551551
// attribute is expanded. Therefore, we don't need to configure the tokens
552552
// Derive macros *can* see the results of cfg-expansion - they are handled
553553
// specially in `fully_expand_fragment`
554-
cfg: StripUnconfigured {
555-
sess: &self.cx.sess,
556-
features: self.cx.ecfg.features,
557-
config_tokens: false,
558-
},
559554
cx: self.cx,
560555
invocations: Vec::new(),
561556
monotonic: self.monotonic,
@@ -1538,12 +1533,20 @@ impl InvocationCollectorNode for AstLikeWrapper<P<ast::Expr>, OptExprTag> {
15381533

15391534
struct InvocationCollector<'a, 'b> {
15401535
cx: &'a mut ExtCtxt<'b>,
1541-
cfg: StripUnconfigured<'a>,
15421536
invocations: Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>,
15431537
monotonic: bool,
15441538
}
15451539

15461540
impl<'a, 'b> InvocationCollector<'a, 'b> {
1541+
fn cfg(&self) -> StripUnconfigured<'_> {
1542+
StripUnconfigured {
1543+
sess: &self.cx.sess,
1544+
features: self.cx.ecfg.features,
1545+
config_tokens: false,
1546+
lint_node_id: self.cx.current_expansion.lint_node_id,
1547+
}
1548+
}
1549+
15471550
fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
15481551
let expn_id = LocalExpnId::fresh_empty();
15491552
let vis = kind.placeholder_visibility();
@@ -1683,7 +1686,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
16831686
attr: ast::Attribute,
16841687
pos: usize,
16851688
) -> bool {
1686-
let res = self.cfg.cfg_true(&attr);
1689+
let res = self.cfg().cfg_true(&attr);
16871690
if res {
16881691
// FIXME: `cfg(TRUE)` attributes do not currently remove themselves during expansion,
16891692
// and some tools like rustdoc and clippy rely on that. Find a way to remove them
@@ -1696,7 +1699,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
16961699

16971700
fn expand_cfg_attr(&self, node: &mut impl AstLike, attr: ast::Attribute, pos: usize) {
16981701
node.visit_attrs(|attrs| {
1699-
attrs.splice(pos..pos, self.cfg.expand_cfg_attr(attr, false));
1702+
attrs.splice(pos..pos, self.cfg().expand_cfg_attr(attr, false));
17001703
});
17011704
}
17021705

@@ -1718,7 +1721,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
17181721
continue;
17191722
}
17201723
_ => {
1721-
Node::pre_flat_map_node_collect_attr(&self.cfg, &attr);
1724+
Node::pre_flat_map_node_collect_attr(&self.cfg(), &attr);
17221725
self.collect_attr((attr, pos, derives), node.to_annotatable(), Node::KIND)
17231726
.make_ast::<Node>()
17241727
}
@@ -1882,7 +1885,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
18821885
fn visit_expr(&mut self, node: &mut P<ast::Expr>) {
18831886
// FIXME: Feature gating is performed inconsistently between `Expr` and `OptExpr`.
18841887
if let Some(attr) = node.attrs.first() {
1885-
self.cfg.maybe_emit_expr_attr_err(attr);
1888+
self.cfg().maybe_emit_expr_attr_err(attr);
18861889
}
18871890
self.visit_node(node)
18881891
}

compiler/rustc_interface/src/passes.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::interface::{Compiler, Result};
22
use crate::proc_macro_decls;
33
use crate::util;
44

5+
use ast::CRATE_NODE_ID;
56
use rustc_ast::mut_visit::MutVisitor;
67
use rustc_ast::{self as ast, visit};
78
use rustc_borrowck as mir_borrowck;
@@ -188,7 +189,7 @@ pub fn register_plugins<'a>(
188189
)
189190
});
190191

191-
let (krate, features) = rustc_expand::config::features(sess, krate);
192+
let (krate, features) = rustc_expand::config::features(sess, krate, CRATE_NODE_ID);
192193
// these need to be set "early" so that expansion sees `quote` if enabled.
193194
sess.init_features(features);
194195

compiler/rustc_metadata/src/native_libs.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_ast::CRATE_NODE_ID;
12
use rustc_attr as attr;
23
use rustc_data_structures::fx::FxHashSet;
34
use rustc_errors::struct_span_err;
@@ -21,7 +22,7 @@ crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
2122

2223
crate fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
2324
match lib.cfg {
24-
Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, None),
25+
Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None),
2526
None => true,
2627
}
2728
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// This test check that local #[allow(unexpected_cfgs)] works
2+
//
3+
// check-pass
4+
// compile-flags:--check-cfg=names() -Z unstable-options
5+
6+
#[allow(unexpected_cfgs)]
7+
fn foo() {
8+
if cfg!(FALSE) {}
9+
}
10+
11+
fn main() {
12+
#[allow(unexpected_cfgs)]
13+
if cfg!(FALSE) {}
14+
}
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// This test check that #[allow(unexpected_cfgs)] doesn't work if put on the same level
2+
//
3+
// check-pass
4+
// compile-flags:--check-cfg=names() -Z unstable-options
5+
6+
#[allow(unexpected_cfgs)]
7+
#[cfg(FALSE)]
8+
//~^ WARNING unexpected `cfg` condition name
9+
fn bar() {}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
warning: unexpected `cfg` condition name
2+
--> $DIR/allow-same-level.rs:7:7
3+
|
4+
LL | #[cfg(FALSE)]
5+
| ^^^^^
6+
|
7+
= note: `#[warn(unexpected_cfgs)]` on by default
8+
9+
warning: 1 warning emitted
10+
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// This test check that a top-level #![allow(unexpected_cfgs)] works
2+
//
3+
// check-pass
4+
// compile-flags:--check-cfg=names() -Z unstable-options
5+
6+
#![allow(unexpected_cfgs)]
7+
8+
#[cfg(FALSE)]
9+
fn bar() {}
10+
11+
fn foo() {
12+
if cfg!(FALSE) {}
13+
}
14+
15+
fn main() {}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// This test check that #[allow(unexpected_cfgs)] work if put on an upper level
2+
//
3+
// check-pass
4+
// compile-flags:--check-cfg=names() -Z unstable-options
5+
6+
#[allow(unexpected_cfgs)]
7+
mod aa {
8+
#[cfg(FALSE)]
9+
fn bar() {}
10+
}
11+
12+
fn main() {}

0 commit comments

Comments
 (0)