1
Fork 0

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:
Dylan DPC 2022-03-03 01:09:12 +01:00 committed by GitHub
commit 493ed7a6af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 122 additions and 26 deletions

View file

@ -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)
})
}

View file

@ -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)
}