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 https://github.com/rust-lang/rust/pull/94298. r? ````````@petrochenkov````````
This commit is contained in:
commit
493ed7a6af
14 changed files with 122 additions and 26 deletions
|
@ -5,6 +5,7 @@ use rustc_ast::token::{DelimToken, Token, TokenKind};
|
|||
use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
|
||||
use rustc_ast::tokenstream::{DelimSpan, Spacing};
|
||||
use rustc_ast::tokenstream::{LazyTokenStream, TokenTree};
|
||||
use rustc_ast::NodeId;
|
||||
use rustc_ast::{self as ast, AstLike, AttrStyle, Attribute, MetaItem};
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
@ -29,6 +30,7 @@ pub struct StripUnconfigured<'a> {
|
|||
/// This is only used for the input to derive macros,
|
||||
/// which needs eager expansion of `cfg` and `cfg_attr`
|
||||
pub config_tokens: bool,
|
||||
pub lint_node_id: NodeId,
|
||||
}
|
||||
|
||||
fn get_features(
|
||||
|
@ -196,8 +198,13 @@ fn get_features(
|
|||
}
|
||||
|
||||
// `cfg_attr`-process the crate's attributes and compute the crate's features.
|
||||
pub fn features(sess: &Session, mut krate: ast::Crate) -> (ast::Crate, Features) {
|
||||
let mut strip_unconfigured = StripUnconfigured { sess, features: None, config_tokens: false };
|
||||
pub fn features(
|
||||
sess: &Session,
|
||||
mut krate: ast::Crate,
|
||||
lint_node_id: NodeId,
|
||||
) -> (ast::Crate, Features) {
|
||||
let mut strip_unconfigured =
|
||||
StripUnconfigured { sess, features: None, config_tokens: false, lint_node_id };
|
||||
|
||||
let unconfigured_attrs = krate.attrs.clone();
|
||||
let diag = &sess.parse_sess.span_diagnostic;
|
||||
|
@ -353,7 +360,12 @@ impl<'a> StripUnconfigured<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
if !attr::cfg_matches(&cfg_predicate, &self.sess.parse_sess, self.features) {
|
||||
if !attr::cfg_matches(
|
||||
&cfg_predicate,
|
||||
&self.sess.parse_sess,
|
||||
self.lint_node_id,
|
||||
self.features,
|
||||
) {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
|
@ -445,7 +457,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
}
|
||||
};
|
||||
parse_cfg(&meta_item, &self.sess).map_or(true, |meta_item| {
|
||||
attr::cfg_matches(&meta_item, &self.sess.parse_sess, self.features)
|
||||
attr::cfg_matches(&meta_item, &self.sess.parse_sess, self.lint_node_id, self.features)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -551,11 +551,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
// attribute is expanded. Therefore, we don't need to configure the tokens
|
||||
// Derive macros *can* see the results of cfg-expansion - they are handled
|
||||
// specially in `fully_expand_fragment`
|
||||
cfg: StripUnconfigured {
|
||||
sess: &self.cx.sess,
|
||||
features: self.cx.ecfg.features,
|
||||
config_tokens: false,
|
||||
},
|
||||
cx: self.cx,
|
||||
invocations: Vec::new(),
|
||||
monotonic: self.monotonic,
|
||||
|
@ -1538,12 +1533,20 @@ impl InvocationCollectorNode for AstLikeWrapper<P<ast::Expr>, OptExprTag> {
|
|||
|
||||
struct InvocationCollector<'a, 'b> {
|
||||
cx: &'a mut ExtCtxt<'b>,
|
||||
cfg: StripUnconfigured<'a>,
|
||||
invocations: Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>,
|
||||
monotonic: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||
fn cfg(&self) -> StripUnconfigured<'_> {
|
||||
StripUnconfigured {
|
||||
sess: &self.cx.sess,
|
||||
features: self.cx.ecfg.features,
|
||||
config_tokens: false,
|
||||
lint_node_id: self.cx.current_expansion.lint_node_id,
|
||||
}
|
||||
}
|
||||
|
||||
fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
|
||||
let expn_id = LocalExpnId::fresh_empty();
|
||||
let vis = kind.placeholder_visibility();
|
||||
|
@ -1683,7 +1686,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
attr: ast::Attribute,
|
||||
pos: usize,
|
||||
) -> bool {
|
||||
let res = self.cfg.cfg_true(&attr);
|
||||
let res = self.cfg().cfg_true(&attr);
|
||||
if res {
|
||||
// FIXME: `cfg(TRUE)` attributes do not currently remove themselves during expansion,
|
||||
// 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> {
|
|||
|
||||
fn expand_cfg_attr(&self, node: &mut impl AstLike, attr: ast::Attribute, pos: usize) {
|
||||
node.visit_attrs(|attrs| {
|
||||
attrs.splice(pos..pos, self.cfg.expand_cfg_attr(attr, false));
|
||||
attrs.splice(pos..pos, self.cfg().expand_cfg_attr(attr, false));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1718,7 +1721,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
continue;
|
||||
}
|
||||
_ => {
|
||||
Node::pre_flat_map_node_collect_attr(&self.cfg, &attr);
|
||||
Node::pre_flat_map_node_collect_attr(&self.cfg(), &attr);
|
||||
self.collect_attr((attr, pos, derives), node.to_annotatable(), Node::KIND)
|
||||
.make_ast::<Node>()
|
||||
}
|
||||
|
@ -1882,7 +1885,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
|||
fn visit_expr(&mut self, node: &mut P<ast::Expr>) {
|
||||
// FIXME: Feature gating is performed inconsistently between `Expr` and `OptExpr`.
|
||||
if let Some(attr) = node.attrs.first() {
|
||||
self.cfg.maybe_emit_expr_attr_err(attr);
|
||||
self.cfg().maybe_emit_expr_attr_err(attr);
|
||||
}
|
||||
self.visit_node(node)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue