about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-03-03 01:09:12 +0100
committerGitHub <noreply@github.com>2022-03-03 01:09:12 +0100
commit493ed7a6af1dbd8fe06f70add0a6814f79f35f5c (patch)
tree07ad9807526b07b6cb2ae84b740edc6863c6017d
parent7537b2036a472e80fce4295eb799a53f61f959c0 (diff)
parent765205b9b8274f6437d3fee291bc80e7e61a0af0 (diff)
downloadrust-493ed7a6af1dbd8fe06f70add0a6814f79f35f5c.tar.gz
rust-493ed7a6af1dbd8fe06f70add0a6814f79f35f5c.zip
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````````
-rw-r--r--compiler/rustc_attr/src/builtin.rs14
-rw-r--r--compiler/rustc_builtin_macros/src/cfg.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_eval.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/derive.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs3
-rw-r--r--compiler/rustc_expand/src/config.rs20
-rw-r--r--compiler/rustc_expand/src/expand.rs23
-rw-r--r--compiler/rustc_interface/src/passes.rs3
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs3
-rw-r--r--src/test/ui/check-cfg/allow-macro-cfg.rs14
-rw-r--r--src/test/ui/check-cfg/allow-same-level.rs11
-rw-r--r--src/test/ui/check-cfg/allow-same-level.stderr10
-rw-r--r--src/test/ui/check-cfg/allow-top-level.rs15
-rw-r--r--src/test/ui/check-cfg/allow-upper-level.rs12
14 files changed, 122 insertions, 26 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 68b536da9f7..846abce9d6a 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -1,8 +1,7 @@
 //! Parsing and validation of builtin attributes
 
 use rustc_ast as ast;
-use rustc_ast::node_id::CRATE_NODE_ID;
-use rustc_ast::{Attribute, Lit, LitKind, MetaItem, MetaItemKind, NestedMetaItem};
+use rustc_ast::{Attribute, Lit, LitKind, MetaItem, MetaItemKind, NestedMetaItem, NodeId};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability};
 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> {
 }
 
 /// Tests if a cfg-pattern matches the cfg set
-pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool {
+pub fn cfg_matches(
+    cfg: &ast::MetaItem,
+    sess: &ParseSess,
+    lint_node_id: NodeId,
+    features: Option<&Features>,
+) -> bool {
     eval_condition(cfg, sess, features, &mut |cfg| {
         try_gate_cfg(cfg, sess, features);
         let error = |span, msg| {
@@ -470,7 +474,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
                         sess.buffer_lint_with_diagnostic(
                             UNEXPECTED_CFGS,
                             cfg.span,
-                            CRATE_NODE_ID,
+                            lint_node_id,
                             "unexpected `cfg` condition name",
                             BuiltinLintDiagnostics::UnexpectedCfg(ident.span, name, None),
                         );
@@ -482,7 +486,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
                             sess.buffer_lint_with_diagnostic(
                                 UNEXPECTED_CFGS,
                                 cfg.span,
-                                CRATE_NODE_ID,
+                                lint_node_id,
                                 "unexpected `cfg` condition value",
                                 BuiltinLintDiagnostics::UnexpectedCfg(
                                     cfg.name_value_literal_span().unwrap(),
diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs
index 1e1cf917c60..f5ef4765df6 100644
--- a/compiler/rustc_builtin_macros/src/cfg.rs
+++ b/compiler/rustc_builtin_macros/src/cfg.rs
@@ -19,7 +19,12 @@ pub fn expand_cfg(
 
     match parse_cfg(cx, sp, tts) {
         Ok(cfg) => {
-            let matches_cfg = attr::cfg_matches(&cfg, &cx.sess.parse_sess, cx.ecfg.features);
+            let matches_cfg = attr::cfg_matches(
+                &cfg,
+                &cx.sess.parse_sess,
+                cx.current_expansion.lint_node_id,
+                cx.ecfg.features,
+            );
             MacEager::expr(cx.expr_bool(sp, matches_cfg))
         }
         Err(mut err) => {
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index 8574cfae860..3c8f8f1854b 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -5,6 +5,7 @@ use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::CanSynthesizeMissingTokens;
 use rustc_ast::visit::Visitor;
+use rustc_ast::NodeId;
 use rustc_ast::{mut_visit, visit};
 use rustc_ast::{AstLike, Attribute};
 use rustc_expand::base::{Annotatable, ExtCtxt};
@@ -26,15 +27,16 @@ crate fn expand(
 ) -> Vec<Annotatable> {
     check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
     warn_on_duplicate_attribute(&ecx, &annotatable, sym::cfg_eval);
-    vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable)]
+    vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable, ecx.current_expansion.lint_node_id)]
 }
 
 crate fn cfg_eval(
     sess: &Session,
     features: Option<&Features>,
     annotatable: Annotatable,
+    lint_node_id: NodeId,
 ) -> Annotatable {
-    CfgEval { cfg: &mut StripUnconfigured { sess, features, config_tokens: true } }
+    CfgEval { cfg: &mut StripUnconfigured { sess, features, config_tokens: true, lint_node_id } }
         .configure_annotatable(annotatable)
         // Since the item itself has already been configured by the `InvocationCollector`,
         // we know that fold result vector will contain exactly one element.
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index 47d7b6c259e..61681ec66a4 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -64,7 +64,12 @@ impl MultiItemModifier for Expander {
                 match &mut resolutions[..] {
                     [] => {}
                     [(_, first_item, _), others @ ..] => {
-                        *first_item = cfg_eval(sess, features, item.clone());
+                        *first_item = cfg_eval(
+                            sess,
+                            features,
+                            item.clone(),
+                            ecx.current_expansion.lint_node_id,
+                        );
                         for (_, item, _) in others {
                             *item = first_item.clone();
                         }
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 9e252c0d9b7..9cc06ac0319 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1,4 +1,5 @@
 use rustc_arena::TypedArena;
+use rustc_ast::CRATE_NODE_ID;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::temp_dir::MaybeTempDir;
@@ -2434,7 +2435,7 @@ fn add_upstream_native_libraries(
 
 fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
     match lib.cfg {
-        Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, None),
+        Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None),
         None => true,
     }
 }
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index c0d7bc359bf..d43c6fec7d5 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -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)
         })
     }
 
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index ab3951d7683..1b976180509 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -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)
     }
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 2cdcf0b11d1..3b51f8eb61c 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -2,6 +2,7 @@ use crate::interface::{Compiler, Result};
 use crate::proc_macro_decls;
 use crate::util;
 
+use ast::CRATE_NODE_ID;
 use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast::{self as ast, visit};
 use rustc_borrowck as mir_borrowck;
@@ -188,7 +189,7 @@ pub fn register_plugins<'a>(
         )
     });
 
-    let (krate, features) = rustc_expand::config::features(sess, krate);
+    let (krate, features) = rustc_expand::config::features(sess, krate, CRATE_NODE_ID);
     // these need to be set "early" so that expansion sees `quote` if enabled.
     sess.init_features(features);
 
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index dce1b35c6b8..7cdcb6a4ab3 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -1,3 +1,4 @@
+use rustc_ast::CRATE_NODE_ID;
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
@@ -21,7 +22,7 @@ crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLib> {
 
 crate fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
     match lib.cfg {
-        Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, None),
+        Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None),
         None => true,
     }
 }
diff --git a/src/test/ui/check-cfg/allow-macro-cfg.rs b/src/test/ui/check-cfg/allow-macro-cfg.rs
new file mode 100644
index 00000000000..8016a4d190c
--- /dev/null
+++ b/src/test/ui/check-cfg/allow-macro-cfg.rs
@@ -0,0 +1,14 @@
+// This test check that local #[allow(unexpected_cfgs)] works
+//
+// check-pass
+// compile-flags:--check-cfg=names() -Z unstable-options
+
+#[allow(unexpected_cfgs)]
+fn foo() {
+    if cfg!(FALSE) {}
+}
+
+fn main() {
+    #[allow(unexpected_cfgs)]
+    if cfg!(FALSE) {}
+}
diff --git a/src/test/ui/check-cfg/allow-same-level.rs b/src/test/ui/check-cfg/allow-same-level.rs
new file mode 100644
index 00000000000..6c869dc4202
--- /dev/null
+++ b/src/test/ui/check-cfg/allow-same-level.rs
@@ -0,0 +1,11 @@
+// This test check that #[allow(unexpected_cfgs)] doesn't work if put on the same level
+//
+// check-pass
+// compile-flags:--check-cfg=names() -Z unstable-options
+
+#[allow(unexpected_cfgs)]
+#[cfg(FALSE)]
+//~^ WARNING unexpected `cfg` condition name
+fn bar() {}
+
+fn main() {}
diff --git a/src/test/ui/check-cfg/allow-same-level.stderr b/src/test/ui/check-cfg/allow-same-level.stderr
new file mode 100644
index 00000000000..7797de584b9
--- /dev/null
+++ b/src/test/ui/check-cfg/allow-same-level.stderr
@@ -0,0 +1,10 @@
+warning: unexpected `cfg` condition name
+  --> $DIR/allow-same-level.rs:7:7
+   |
+LL | #[cfg(FALSE)]
+   |       ^^^^^
+   |
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/check-cfg/allow-top-level.rs b/src/test/ui/check-cfg/allow-top-level.rs
new file mode 100644
index 00000000000..d14b0eae5cc
--- /dev/null
+++ b/src/test/ui/check-cfg/allow-top-level.rs
@@ -0,0 +1,15 @@
+// This test check that a top-level #![allow(unexpected_cfgs)] works
+//
+// check-pass
+// compile-flags:--check-cfg=names() -Z unstable-options
+
+#![allow(unexpected_cfgs)]
+
+#[cfg(FALSE)]
+fn bar() {}
+
+fn foo() {
+    if cfg!(FALSE) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/check-cfg/allow-upper-level.rs b/src/test/ui/check-cfg/allow-upper-level.rs
new file mode 100644
index 00000000000..04340694d9c
--- /dev/null
+++ b/src/test/ui/check-cfg/allow-upper-level.rs
@@ -0,0 +1,12 @@
+// This test check that #[allow(unexpected_cfgs)] work if put on an upper level
+//
+// check-pass
+// compile-flags:--check-cfg=names() -Z unstable-options
+
+#[allow(unexpected_cfgs)]
+mod aa {
+    #[cfg(FALSE)]
+    fn bar() {}
+}
+
+fn main() {}