From af46699f8104ba5257d0da56d3d817bf8fc751cf Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 29 Jul 2021 12:00:41 -0500 Subject: [PATCH] Remove `Session.used_attrs` and move logic to `CheckAttrVisitor` Instead of updating global state to mark attributes as used, we now explicitly emit a warning when an attribute is used in an unsupported position. As a side effect, we are to emit more detailed warning messages (instead of just a generic "unused" message). `Session.check_name` is removed, since its only purpose was to mark the attribute as used. All of the callers are modified to use `Attribute.has_name` Additionally, `AttributeType::AssumedUsed` is removed - an 'assumed used' attribute is implemented by simply not performing any checks in `CheckAttrVisitor` for a particular attribute. We no longer emit unused attribute warnings for the `#[rustc_dummy]` attribute - it's an internal attribute used for tests, so it doesn't mark sense to treat it as 'unused'. With this commit, a large source of global untracked state is removed. --- Cargo.lock | 2 + compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_ast_passes/src/feature_gate.rs | 6 +- compiler/rustc_attr/src/builtin.rs | 25 +- .../src/deriving/generic/mod.rs | 2 - .../src/proc_macro_harness.rs | 6 +- .../rustc_builtin_macros/src/test_harness.rs | 3 +- compiler/rustc_expand/src/config.rs | 69 +----- compiler/rustc_expand/src/expand.rs | 5 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 2 +- compiler/rustc_feature/src/builtin_attrs.rs | 163 +++++++------ .../rustc_incremental/src/assert_dep_graph.rs | 4 +- .../src/assert_module_sources.rs | 39 ++- .../src/persist/dirty_clean.rs | 4 +- compiler/rustc_interface/src/queries.rs | 2 +- compiler/rustc_interface/src/util.rs | 6 +- compiler/rustc_lint/src/builtin.rs | 23 +- compiler/rustc_lint/src/levels.rs | 2 - compiler/rustc_lint/src/lib.rs | 2 - compiler/rustc_lint/src/types.rs | 4 +- compiler/rustc_lint/src/unused.rs | 63 +---- compiler/rustc_lint_defs/src/builtin.rs | 1 + compiler/rustc_metadata/src/native_libs.rs | 3 +- compiler/rustc_middle/src/middle/limits.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 2 +- .../src/dataflow/framework/engine.rs | 2 +- compiler/rustc_mir/src/dataflow/mod.rs | 4 +- .../src/monomorphize/polymorphize.rs | 6 +- compiler/rustc_parse/src/lib.rs | 44 +++- compiler/rustc_passes/Cargo.toml | 2 + compiler/rustc_passes/src/check_attr.rs | 161 ++++++++++++- compiler/rustc_passes/src/diagnostic_items.rs | 9 +- compiler/rustc_passes/src/lang_items.rs | 3 +- compiler/rustc_passes/src/layout_test.rs | 2 +- compiler/rustc_passes/src/lib.rs | 1 + compiler/rustc_passes/src/lib_features.rs | 4 +- compiler/rustc_passes/src/stability.rs | 3 +- compiler/rustc_passes/src/weak_lang_items.rs | 3 +- compiler/rustc_plugin_impl/src/load.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 4 +- .../rustc_resolve/src/build_reduced_graph.rs | 6 +- compiler/rustc_resolve/src/late/lifetimes.rs | 10 +- compiler/rustc_resolve/src/lib.rs | 5 +- compiler/rustc_session/src/session.rs | 38 +-- compiler/rustc_symbol_mangling/src/test.rs | 4 +- compiler/rustc_typeck/src/check/demand.rs | 2 +- compiler/rustc_typeck/src/collect.rs | 58 +++-- compiler/rustc_typeck/src/lib.rs | 4 +- .../attributes/register-attr-tool-unused.rs | 2 - .../register-attr-tool-unused.stderr | 18 +- .../cfg-attr-empty-is-unused.rs | 4 +- .../cfg-attr-empty-is-unused.stderr | 4 +- .../defaults/default-annotation.rs | 1 - .../issue-43106-gating-of-builtin-attrs.rs | 223 +++++++----------- src/test/ui/invalid/invalid-plugin-attr.rs | 3 +- .../ui/invalid/invalid-plugin-attr.stderr | 10 +- src/test/ui/lint/lint-misplaced-attr.rs | 6 +- src/test/ui/lint/lint-misplaced-attr.stderr | 18 +- .../ui/lint/unused/unused-attr-macro-rules.rs | 7 +- .../unused/unused-attr-macro-rules.stderr | 12 +- src/test/ui/lint/unused/unused-attr.rs | 49 ---- src/test/ui/lint/unused/unused-attr.stderr | 98 -------- 62 files changed, 535 insertions(+), 739 deletions(-) delete mode 100644 src/test/ui/lint/unused/unused-attr.rs delete mode 100644 src/test/ui/lint/unused/unused-attr.stderr diff --git a/Cargo.lock b/Cargo.lock index 9e0624c57ae94..e4612d8a95420 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4115,10 +4115,12 @@ dependencies = [ "rustc_attr", "rustc_data_structures", "rustc_errors", + "rustc_feature", "rustc_hir", "rustc_index", "rustc_lexer", "rustc_middle", + "rustc_parse", "rustc_serialize", "rustc_session", "rustc_span", diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d41b3b8146624..b6aef1543ff1d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2281,7 +2281,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { synthetic: param .attrs .iter() - .filter(|attr| self.sess.check_name(attr, sym::rustc_synthetic)) + .filter(|attr| attr.has_name(sym::rustc_synthetic)) .map(|_| hir::SyntheticTyParamKind::FromAttr) .next(), }; diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index feece517cebf4..0be26b6f8e9de 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -268,7 +268,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_fn!(self, has_feature, attr.span, name, descr); } // Check unstable flavors of the `#[doc]` attribute. - if self.sess.check_name(attr, sym::doc) { + if attr.has_name(sym::doc) { for nested_meta in attr.meta_item_list().unwrap_or_default() { macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => { $(if nested_meta.has_name(sym::$name) { @@ -287,7 +287,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } // Check for unstable modifiers on `#[link(..)]` attribute - if self.sess.check_name(attr, sym::link) { + if attr.has_name(sym::link) { for nested_meta in attr.meta_item_list().unwrap_or_default() { if nested_meta.has_name(sym::modifiers) { gate_feature_post!( @@ -709,7 +709,7 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) { if !sess.opts.unstable_features.is_nightly_build() { let lang_features = &sess.features_untracked().declared_lang_features; - for attr in krate.attrs.iter().filter(|attr| sess.check_name(attr, sym::feature)) { + for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) { let mut err = struct_span_err!( sess.parse_sess.span_diagnostic, attr.span, diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index a50fc698850c6..0ab452fb42dc6 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -166,8 +166,6 @@ where continue; // not a stability level } - sess.mark_attr_used(attr); - let meta = attr.meta(); if attr.has_name(sym::rustc_promotable) { @@ -636,8 +634,7 @@ where let diagnostic = &sess.parse_sess.span_diagnostic; 'outer: for attr in attrs_iter { - if !(sess.check_name(attr, sym::deprecated) || sess.check_name(attr, sym::rustc_deprecated)) - { + if !(attr.has_name(sym::deprecated) || attr.has_name(sym::rustc_deprecated)) { continue; } @@ -700,17 +697,17 @@ where continue 'outer; } } - sym::note if sess.check_name(attr, sym::deprecated) => { + sym::note if attr.has_name(sym::deprecated) => { if !get(mi, &mut note) { continue 'outer; } } - sym::reason if sess.check_name(attr, sym::rustc_deprecated) => { + sym::reason if attr.has_name(sym::rustc_deprecated) => { if !get(mi, &mut note) { continue 'outer; } } - sym::suggestion if sess.check_name(attr, sym::rustc_deprecated) => { + sym::suggestion if attr.has_name(sym::rustc_deprecated) => { if !get(mi, &mut suggestion) { continue 'outer; } @@ -721,7 +718,7 @@ where meta.span(), AttrError::UnknownMetaItem( pprust::path_to_string(&mi.path), - if sess.check_name(attr, sym::deprecated) { + if attr.has_name(sym::deprecated) { &["since", "note"] } else { &["since", "reason", "suggestion"] @@ -747,11 +744,11 @@ where } } - if suggestion.is_some() && sess.check_name(attr, sym::deprecated) { + if suggestion.is_some() && attr.has_name(sym::deprecated) { unreachable!("only allowed on rustc_deprecated") } - if sess.check_name(attr, sym::rustc_deprecated) { + if attr.has_name(sym::rustc_deprecated) { if since.is_none() { handle_errors(&sess.parse_sess, attr.span, AttrError::MissingSince); continue; @@ -763,9 +760,7 @@ where } } - sess.mark_attr_used(&attr); - - let is_since_rustc_version = sess.check_name(attr, sym::rustc_deprecated); + let is_since_rustc_version = attr.has_name(sym::rustc_deprecated); depr = Some((Deprecation { since, note, suggestion, is_since_rustc_version }, attr.span)); } @@ -816,7 +811,6 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec { let diagnostic = &sess.parse_sess.span_diagnostic; if attr.has_name(sym::repr) { if let Some(items) = attr.meta_item_list() { - sess.mark_attr_used(attr); for item in items { let mut recognised = false; if item.is_word() { @@ -1015,14 +1009,13 @@ pub enum TransparencyError { } pub fn find_transparency( - sess: &Session, attrs: &[Attribute], macro_rules: bool, ) -> (Transparency, Option) { let mut transparency = None; let mut error = None; for attr in attrs { - if sess.check_name(attr, sym::rustc_macro_transparency) { + if attr.has_name(sym::rustc_macro_transparency) { if let Some((_, old_span)) = transparency { error = Some(TransparencyError::MultipleTransparencyAttrs(old_span, attr.span)); break; diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 61af4979e7014..85499623f4135 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -677,8 +677,6 @@ impl<'a> TraitDef<'a> { let self_type = cx.ty_path(path); let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived)); - // Just mark it now since we know that it'll end up used downstream - cx.sess.mark_attr_used(&attr); let opt_trait_ref = Some(trait_ref); let unused_qual = { let word = rustc_ast::attr::mk_nested_word_item(Ident::new( diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index f83329ecba824..7971c1fff428c 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -260,11 +260,11 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { return; } - if self.sess.check_name(attr, sym::proc_macro_derive) { + if attr.has_name(sym::proc_macro_derive) { self.collect_custom_derive(item, attr); - } else if self.sess.check_name(attr, sym::proc_macro_attribute) { + } else if attr.has_name(sym::proc_macro_attribute) { self.collect_attr_proc_macro(item); - } else if self.sess.check_name(attr, sym::proc_macro) { + } else if attr.has_name(sym::proc_macro) { self.collect_bang_proc_macro(item); }; diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index be24b60294bfe..d791677cb8ee1 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -188,8 +188,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> { let attrs = attrs .into_iter() .filter(|attr| { - !self.sess.check_name(attr, sym::rustc_main) - && !self.sess.check_name(attr, sym::start) + !attr.has_name(sym::rustc_main) && !attr.has_name(sym::start) }) .chain(iter::once(allow_dead_code)) .collect(); diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index f9140609c0f3c..e09893f7f3884 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -5,7 +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::{self as ast, AstLike, AttrItem, AttrStyle, Attribute, MetaItem}; +use rustc_ast::{self as ast, AstLike, AttrStyle, Attribute, MetaItem}; use rustc_attr as attr; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::map_in_place::MapInPlace; @@ -14,7 +14,7 @@ use rustc_feature::{Feature, Features, State as FeatureState}; use rustc_feature::{ ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES, }; -use rustc_parse::{parse_in, validate_attr}; +use rustc_parse::validate_attr; use rustc_session::parse::feature_err; use rustc_session::Session; use rustc_span::edition::{Edition, ALL_EDITIONS}; @@ -75,7 +75,7 @@ fn get_features( // Process the edition umbrella feature-gates first, to ensure // `edition_enabled_features` is completed before it's queried. for attr in krate_attrs { - if !sess.check_name(attr, sym::feature) { + if !attr.has_name(sym::feature) { continue; } @@ -108,7 +108,7 @@ fn get_features( } for attr in krate_attrs { - if !sess.check_name(attr, sym::feature) { + if !attr.has_name(sym::feature) { continue; } @@ -237,11 +237,6 @@ macro_rules! configure { }; } -const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]"; -const CFG_ATTR_NOTE_REF: &str = "for more information, visit \ - "; - impl<'a> StripUnconfigured<'a> { pub fn configure(&mut self, mut node: T) -> Option { self.process_cfg_attrs(&mut node); @@ -349,19 +344,17 @@ impl<'a> StripUnconfigured<'a> { return vec![attr]; } - let (cfg_predicate, expanded_attrs) = match self.parse_cfg_attr(&attr) { - None => return vec![], - Some(r) => r, - }; + let (cfg_predicate, expanded_attrs) = + match rustc_parse::parse_cfg_attr(&attr, &self.sess.parse_sess) { + None => return vec![], + Some(r) => r, + }; // Lint on zero attributes in source. if expanded_attrs.is_empty() { return vec![attr]; } - // At this point we know the attribute is considered used. - self.sess.mark_attr_used(&attr); - if !attr::cfg_matches(&cfg_predicate, &self.sess.parse_sess, self.features) { return vec![]; } @@ -415,46 +408,10 @@ impl<'a> StripUnconfigured<'a> { .collect() } - fn parse_cfg_attr(&self, attr: &Attribute) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> { - match attr.get_normal_item().args { - ast::MacArgs::Delimited(dspan, delim, ref tts) if !tts.is_empty() => { - let msg = "wrong `cfg_attr` delimiters"; - validate_attr::check_meta_bad_delim(&self.sess.parse_sess, dspan, delim, msg); - match parse_in(&self.sess.parse_sess, tts.clone(), "`cfg_attr` input", |p| { - p.parse_cfg_attr() - }) { - Ok(r) => return Some(r), - Err(mut e) => { - e.help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP)) - .note(CFG_ATTR_NOTE_REF) - .emit(); - } - } - } - _ => self.error_malformed_cfg_attr_missing(attr.span), - } - None - } - - fn error_malformed_cfg_attr_missing(&self, span: Span) { - self.sess - .parse_sess - .span_diagnostic - .struct_span_err(span, "malformed `cfg_attr` attribute input") - .span_suggestion( - span, - "missing condition and attribute", - CFG_ATTR_GRAMMAR_HELP.to_string(), - Applicability::HasPlaceholders, - ) - .note(CFG_ATTR_NOTE_REF) - .emit(); - } - /// Determines if a node with the given attributes should be included in this configuration. fn in_cfg(&self, attrs: &[Attribute]) -> bool { attrs.iter().all(|attr| { - if !is_cfg(self.sess, attr) { + if !is_cfg(attr) { return true; } let meta_item = match validate_attr::parse_meta(&self.sess.parse_sess, attr) { @@ -500,7 +457,7 @@ impl<'a> StripUnconfigured<'a> { // // N.B., this is intentionally not part of the visit_expr() function // in order for filter_map_expr() to be able to avoid this check - if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(self.sess, a)) { + if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(*a)) { let msg = "removing an expression is not supported in this position"; self.sess.parse_sess.span_diagnostic.span_err(attr.span, msg); } @@ -536,6 +493,6 @@ pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a Meta } } -fn is_cfg(sess: &Session, attr: &Attribute) -> bool { - sess.check_name(attr, sym::cfg) +fn is_cfg(attr: &Attribute) -> bool { + attr.has_name(sym::cfg) } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 09beda3348374..abe81ec978f0d 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -753,11 +753,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } } - SyntaxExtensionKind::NonMacroAttr { mark_used } => { + SyntaxExtensionKind::NonMacroAttr { mark_used: _ } => { self.cx.expanded_inert_attrs.mark(&attr); - if *mark_used { - self.cx.sess.mark_attr_used(&attr); - } item.visit_attrs(|attrs| attrs.insert(pos, attr)); fragment_kind.expect_from_annotatables(iter::once(item)) } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 9aee86c9e57dd..e0c62388fe0ce 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -535,7 +535,7 @@ pub fn compile_declarative_macro( valid &= macro_check::check_meta_variables(&sess.parse_sess, def.id, def.span, &lhses, &rhses); - let (transparency, transparency_error) = attr::find_transparency(sess, &def.attrs, macro_rules); + let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules); match transparency_error { Some(TransparencyError::UnknownTransparency(value, span)) => { diag.span_err(span, &format!("unknown macro transparency: `{}`", value)) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 5729384c0da25..45db4c7f1186f 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -52,11 +52,6 @@ pub enum AttributeType { /// by the compiler before the unused_attribute check Normal, - /// Builtin attribute that may not be consumed by the compiler - /// before the unused_attribute check. These attributes - /// will be ignored by the unused_attribute lint - AssumedUsed, - /// Builtin attribute that is only allowed at the crate level CrateLevel, } @@ -186,7 +181,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), ), // FIXME(Centril): This can be used on stable but shouldn't. - ungated!(reexport_test_harness_main, Normal, template!(NameValueStr: "name")), + ungated!(reexport_test_harness_main, CrateLevel, template!(NameValueStr: "name")), // Macros: ungated!(automatically_derived, Normal, template!(Word)), @@ -206,7 +201,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), ungated!(forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), ungated!(deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), - ungated!(must_use, AssumedUsed, template!(Word, NameValueStr: "reason")), + ungated!(must_use, Normal, template!(Word, NameValueStr: "reason")), // FIXME(#14407) ungated!( deprecated, Normal, @@ -224,16 +219,16 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ABI, linking, symbols, and FFI ungated!( - link, AssumedUsed, + link, Normal, template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...""#), ), - ungated!(link_name, AssumedUsed, template!(NameValueStr: "name")), - ungated!(no_link, AssumedUsed, template!(Word)), - ungated!(repr, AssumedUsed, template!(List: "C")), - ungated!(export_name, AssumedUsed, template!(NameValueStr: "name")), - ungated!(link_section, AssumedUsed, template!(NameValueStr: "name")), - ungated!(no_mangle, AssumedUsed, template!(Word)), - ungated!(used, AssumedUsed, template!(Word)), + ungated!(link_name, Normal, template!(NameValueStr: "name")), + ungated!(no_link, Normal, template!(Word)), + ungated!(repr, Normal, template!(List: "C")), + ungated!(export_name, Normal, template!(NameValueStr: "name")), + ungated!(link_section, Normal, template!(NameValueStr: "name")), + ungated!(no_mangle, Normal, template!(Word)), + ungated!(used, Normal, template!(Word)), // Limits: ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")), @@ -256,37 +251,37 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Modules, prelude, and resolution: ungated!(path, Normal, template!(NameValueStr: "file")), ungated!(no_std, CrateLevel, template!(Word)), - ungated!(no_implicit_prelude, Normal, template!(Word)), - ungated!(non_exhaustive, AssumedUsed, template!(Word)), + ungated!(no_implicit_prelude, CrateLevel, template!(Word)), + ungated!(non_exhaustive, Normal, template!(Word)), // Runtime - ungated!(windows_subsystem, AssumedUsed, template!(NameValueStr: "windows|console")), + ungated!(windows_subsystem, Normal, template!(NameValueStr: "windows|console")), ungated!(panic_handler, Normal, template!(Word)), // RFC 2070 // Code generation: - ungated!(inline, AssumedUsed, template!(Word, List: "always|never")), - ungated!(cold, AssumedUsed, template!(Word)), - ungated!(no_builtins, AssumedUsed, template!(Word)), - ungated!(target_feature, AssumedUsed, template!(List: r#"enable = "name""#)), - ungated!(track_caller, AssumedUsed, template!(Word)), + ungated!(inline, Normal, template!(Word, List: "always|never")), + ungated!(cold, Normal, template!(Word)), + ungated!(no_builtins, Normal, template!(Word)), + ungated!(target_feature, Normal, template!(List: r#"enable = "name""#)), + ungated!(track_caller, Normal, template!(Word)), gated!( - no_sanitize, AssumedUsed, + no_sanitize, Normal, template!(List: "address, memory, thread"), experimental!(no_sanitize) ), - gated!(no_coverage, AssumedUsed, template!(Word), experimental!(no_coverage)), + gated!(no_coverage, Normal, template!(Word), experimental!(no_coverage)), // FIXME: #14408 assume docs are used since rustdoc looks at them. - ungated!(doc, AssumedUsed, template!(List: "hidden|inline|...", NameValueStr: "string")), + ungated!(doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string")), // ========================================================================== // Unstable attributes: // ========================================================================== // Linking: - gated!(naked, AssumedUsed, template!(Word), naked_functions, experimental!(naked)), + gated!(naked, Normal, template!(Word), naked_functions, experimental!(naked)), gated!( - link_ordinal, AssumedUsed, template!(List: "ordinal"), raw_dylib, + link_ordinal, Normal, template!(List: "ordinal"), raw_dylib, experimental!(link_ordinal) ), @@ -311,23 +306,23 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "custom test frameworks are an unstable feature", ), // RFC #1268 - gated!(marker, AssumedUsed, template!(Word), marker_trait_attr, experimental!(marker)), + gated!(marker, Normal, template!(Word), marker_trait_attr, experimental!(marker)), gated!( - thread_local, AssumedUsed, template!(Word), + thread_local, Normal, template!(Word), "`#[thread_local]` is an experimental feature, and does not currently handle destructors", ), gated!(no_core, CrateLevel, template!(Word), experimental!(no_core)), // RFC 2412 gated!( - optimize, AssumedUsed, template!(List: "size|speed"), optimize_attribute, + optimize, Normal, template!(List: "size|speed"), optimize_attribute, experimental!(optimize), ), // RFC 2867 - gated!(instruction_set, AssumedUsed, template!(List: "set"), isa_attribute, experimental!(instruction_set)), + gated!(instruction_set, Normal, template!(List: "set"), isa_attribute, experimental!(instruction_set)), - gated!(ffi_returns_twice, AssumedUsed, template!(Word), experimental!(ffi_returns_twice)), - gated!(ffi_pure, AssumedUsed, template!(Word), experimental!(ffi_pure)), - gated!(ffi_const, AssumedUsed, template!(Word), experimental!(ffi_const)), + gated!(ffi_returns_twice, Normal, template!(Word), experimental!(ffi_returns_twice)), + gated!(ffi_pure, Normal, template!(Word), experimental!(ffi_pure)), + gated!(ffi_const, Normal, template!(Word), experimental!(ffi_const)), gated!( register_attr, CrateLevel, template!(List: "attr1, attr2, ..."), experimental!(register_attr), @@ -337,10 +332,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ experimental!(register_tool), ), - gated!(cmse_nonsecure_entry, AssumedUsed, template!(Word), experimental!(cmse_nonsecure_entry)), + gated!(cmse_nonsecure_entry, Normal, template!(Word), experimental!(cmse_nonsecure_entry)), // RFC 2632 gated!( - default_method_body_is_const, AssumedUsed, template!(Word), const_trait_impl, + default_method_body_is_const, Normal, template!(Word), const_trait_impl, "`default_method_body_is_const` is a temporary placeholder for declaring default bodies \ as `const`, which may be removed or renamed in the future." ), @@ -353,26 +348,26 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // FIXME(#14407) -- only looked at on-demand so we can't // guarantee they'll have already been checked. ungated!( - rustc_deprecated, AssumedUsed, + rustc_deprecated, Normal, template!(List: r#"since = "version", reason = "...""#) ), // FIXME(#14407) - ungated!(stable, AssumedUsed, template!(List: r#"feature = "name", since = "version""#)), + ungated!(stable, Normal, template!(List: r#"feature = "name", since = "version""#)), // FIXME(#14407) ungated!( - unstable, AssumedUsed, + unstable, Normal, template!(List: r#"feature = "name", reason = "...", issue = "N""#), ), // FIXME(#14407) - ungated!(rustc_const_unstable, AssumedUsed, template!(List: r#"feature = "name""#)), + ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#)), // FIXME(#14407) - ungated!(rustc_const_stable, AssumedUsed, template!(List: r#"feature = "name""#)), + ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#)), gated!( - allow_internal_unstable, AssumedUsed, template!(Word, List: "feat1, feat2, ..."), + allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), "allow_internal_unstable side-steps feature gating and stability checks", ), gated!( - rustc_allow_const_fn_unstable, AssumedUsed, template!(Word, List: "feat1, feat2, ..."), + rustc_allow_const_fn_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), "rustc_allow_const_fn_unstable side-steps feature gating and stability checks" ), gated!( @@ -384,7 +379,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes: Type system related: // ========================================================================== - gated!(fundamental, AssumedUsed, template!(Word), experimental!(fundamental)), + gated!(fundamental, Normal, template!(Word), experimental!(fundamental)), gated!( may_dangle, Normal, template!(Word), dropck_eyepatch, "`may_dangle` has unstable semantics and may be removed in the future", @@ -394,26 +389,26 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes: Runtime related: // ========================================================================== - rustc_attr!(rustc_allocator, AssumedUsed, template!(Word), IMPL_DETAIL), - rustc_attr!(rustc_allocator_nounwind, AssumedUsed, template!(Word), IMPL_DETAIL), + rustc_attr!(rustc_allocator, Normal, template!(Word), IMPL_DETAIL), + rustc_attr!(rustc_allocator_nounwind, Normal, template!(Word), IMPL_DETAIL), gated!(alloc_error_handler, Normal, template!(Word), experimental!(alloc_error_handler)), gated!( - default_lib_allocator, AssumedUsed, template!(Word), allocator_internals, + default_lib_allocator, Normal, template!(Word), allocator_internals, experimental!(default_lib_allocator), ), gated!( needs_allocator, Normal, template!(Word), allocator_internals, experimental!(needs_allocator), ), - gated!(panic_runtime, AssumedUsed, template!(Word), experimental!(panic_runtime)), - gated!(needs_panic_runtime, AssumedUsed, template!(Word), experimental!(needs_panic_runtime)), + gated!(panic_runtime, Normal, template!(Word), experimental!(panic_runtime)), + gated!(needs_panic_runtime, Normal, template!(Word), experimental!(needs_panic_runtime)), gated!( - compiler_builtins, AssumedUsed, template!(Word), + compiler_builtins, Normal, template!(Word), "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ which contains compiler-rt intrinsics and will never be stable", ), gated!( - profiler_runtime, AssumedUsed, template!(Word), + profiler_runtime, Normal, template!(Word), "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ which contains the profiler runtime and will never be stable", ), @@ -423,23 +418,23 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== gated!( - linkage, AssumedUsed, template!(NameValueStr: "external|internal|..."), + linkage, Normal, template!(NameValueStr: "external|internal|..."), "the `linkage` attribute is experimental and not portable across platforms", ), - rustc_attr!(rustc_std_internal_symbol, AssumedUsed, template!(Word), INTERNAL_UNSTABLE), + rustc_attr!(rustc_std_internal_symbol, Normal, template!(Word), INTERNAL_UNSTABLE), // ========================================================================== // Internal attributes, Macro related: // ========================================================================== rustc_attr!( - rustc_builtin_macro, AssumedUsed, + rustc_builtin_macro, Normal, template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), IMPL_DETAIL, ), rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE), rustc_attr!( - rustc_macro_transparency, AssumedUsed, + rustc_macro_transparency, Normal, template!(NameValueStr: "transparent|semitransparent|opaque"), "used internally for testing macro hygiene", ), @@ -449,7 +444,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== rustc_attr!( - rustc_on_unimplemented, AssumedUsed, + rustc_on_unimplemented, Normal, template!( List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, NameValueStr: "message" @@ -457,31 +452,31 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ INTERNAL_UNSTABLE ), // Enumerates "identity-like" conversion methods to suggest on type mismatch. - rustc_attr!(rustc_conversion_suggestion, AssumedUsed, template!(Word), INTERNAL_UNSTABLE), + rustc_attr!(rustc_conversion_suggestion, Normal, template!(Word), INTERNAL_UNSTABLE), // ========================================================================== // Internal attributes, Const related: // ========================================================================== - rustc_attr!(rustc_promotable, AssumedUsed, template!(Word), IMPL_DETAIL), - rustc_attr!(rustc_legacy_const_generics, AssumedUsed, template!(List: "N"), INTERNAL_UNSTABLE), + rustc_attr!(rustc_promotable, Normal, template!(Word), IMPL_DETAIL), + rustc_attr!(rustc_legacy_const_generics, Normal, template!(List: "N"), INTERNAL_UNSTABLE), // ========================================================================== // Internal attributes, Layout related: // ========================================================================== rustc_attr!( - rustc_layout_scalar_valid_range_start, AssumedUsed, template!(List: "value"), + rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ niche optimizations in libcore and will never be stable", ), rustc_attr!( - rustc_layout_scalar_valid_range_end, AssumedUsed, template!(List: "value"), + rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ niche optimizations in libcore and will never be stable", ), rustc_attr!( - rustc_nonnull_optimization_guaranteed, AssumedUsed, template!(Word), + rustc_nonnull_optimization_guaranteed, Normal, template!(Word), "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \ niche optimizations in libcore and will never be stable", ), @@ -506,7 +501,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), gated!( // Used in resolve: - prelude_import, AssumedUsed, template!(Word), + prelude_import, Normal, template!(Word), "`#[prelude_import]` is for use by rustc only", ), gated!( @@ -514,7 +509,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "unboxed_closures are still evolving", ), rustc_attr!( - rustc_inherit_overflow_checks, AssumedUsed, template!(Word), + rustc_inherit_overflow_checks, Normal, template!(Word), "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ overflow checking behavior of several libcore functions that are inlined \ across crates and will never be stable", @@ -556,41 +551,41 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), rustc_attr!(TEST, rustc_regions, Normal, template!(Word)), rustc_attr!( - TEST, rustc_error, AssumedUsed, + TEST, rustc_error, Normal, template!(Word, List: "delay_span_bug_from_inside_query") ), - rustc_attr!(TEST, rustc_dump_user_substs, AssumedUsed, template!(Word)), - rustc_attr!(TEST, rustc_evaluate_where_clauses, AssumedUsed, template!(Word)), - rustc_attr!(TEST, rustc_if_this_changed, AssumedUsed, template!(Word, List: "DepNode")), - rustc_attr!(TEST, rustc_then_this_would_need, AssumedUsed, template!(List: "DepNode")), + rustc_attr!(TEST, rustc_dump_user_substs, Normal, template!(Word)), + rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word)), + rustc_attr!(TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode")), + rustc_attr!(TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode")), rustc_attr!( - TEST, rustc_clean, AssumedUsed, + TEST, rustc_clean, Normal, template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), ), rustc_attr!( - TEST, rustc_partition_reused, AssumedUsed, + TEST, rustc_partition_reused, Normal, template!(List: r#"cfg = "...", module = "...""#), ), rustc_attr!( - TEST, rustc_partition_codegened, AssumedUsed, + TEST, rustc_partition_codegened, Normal, template!(List: r#"cfg = "...", module = "...""#), ), rustc_attr!( - TEST, rustc_expected_cgu_reuse, AssumedUsed, + TEST, rustc_expected_cgu_reuse, Normal, template!(List: r#"cfg = "...", module = "...", kind = "...""#), ), - rustc_attr!(TEST, rustc_synthetic, AssumedUsed, template!(Word)), - rustc_attr!(TEST, rustc_symbol_name, AssumedUsed, template!(Word)), - rustc_attr!(TEST, rustc_polymorphize_error, AssumedUsed, template!(Word)), - rustc_attr!(TEST, rustc_def_path, AssumedUsed, template!(Word)), - rustc_attr!(TEST, rustc_mir, AssumedUsed, template!(List: "arg1, arg2, ...")), - rustc_attr!(TEST, rustc_dump_program_clauses, AssumedUsed, template!(Word)), - rustc_attr!(TEST, rustc_dump_env_program_clauses, AssumedUsed, template!(Word)), - rustc_attr!(TEST, rustc_object_lifetime_default, AssumedUsed, template!(Word)), - rustc_attr!(TEST, rustc_dump_vtable, AssumedUsed, template!(Word)), + rustc_attr!(TEST, rustc_synthetic, Normal, template!(Word)), + rustc_attr!(TEST, rustc_symbol_name, Normal, template!(Word)), + rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word)), + rustc_attr!(TEST, rustc_def_path, Normal, template!(Word)), + rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ...")), + rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word)), + rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word)), + rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word)), + rustc_attr!(TEST, rustc_dump_vtable, Normal, template!(Word)), rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/)), gated!( - omit_gdb_pretty_printer_section, AssumedUsed, template!(Word), + omit_gdb_pretty_printer_section, Normal, template!(Word), "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite", ), ]; diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index b5680beae142d..0a558eb0555de 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -123,7 +123,7 @@ impl IfThisChanged<'tcx> { let def_path_hash = self.tcx.def_path_hash(def_id.to_def_id()); let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { - if self.tcx.sess.check_name(attr, sym::rustc_if_this_changed) { + if attr.has_name(sym::rustc_if_this_changed) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { None => DepNode::from_def_path_hash(def_path_hash, DepKind::hir_owner), @@ -138,7 +138,7 @@ impl IfThisChanged<'tcx> { }, }; self.if_this_changed.push((attr.span, def_id.to_def_id(), dep_node)); - } else if self.tcx.sess.check_name(attr, sym::rustc_then_this_would_need) { + } else if attr.has_name(sym::rustc_then_this_would_need) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) { diff --git a/compiler/rustc_incremental/src/assert_module_sources.rs b/compiler/rustc_incremental/src/assert_module_sources.rs index 8220eb6c6570f..a5f3e4553ce56 100644 --- a/compiler/rustc_incremental/src/assert_module_sources.rs +++ b/compiler/rustc_incremental/src/assert_module_sources.rs @@ -57,27 +57,26 @@ struct AssertModuleSource<'tcx> { impl AssertModuleSource<'tcx> { fn check_attr(&self, attr: &ast::Attribute) { - let (expected_reuse, comp_kind) = - if self.tcx.sess.check_name(attr, sym::rustc_partition_reused) { - (CguReuse::PreLto, ComparisonKind::AtLeast) - } else if self.tcx.sess.check_name(attr, sym::rustc_partition_codegened) { - (CguReuse::No, ComparisonKind::Exact) - } else if self.tcx.sess.check_name(attr, sym::rustc_expected_cgu_reuse) { - match self.field(attr, sym::kind) { - sym::no => (CguReuse::No, ComparisonKind::Exact), - sym::pre_dash_lto => (CguReuse::PreLto, ComparisonKind::Exact), - sym::post_dash_lto => (CguReuse::PostLto, ComparisonKind::Exact), - sym::any => (CguReuse::PreLto, ComparisonKind::AtLeast), - other => { - self.tcx.sess.span_fatal( - attr.span, - &format!("unknown cgu-reuse-kind `{}` specified", other), - ); - } + let (expected_reuse, comp_kind) = if attr.has_name(sym::rustc_partition_reused) { + (CguReuse::PreLto, ComparisonKind::AtLeast) + } else if attr.has_name(sym::rustc_partition_codegened) { + (CguReuse::No, ComparisonKind::Exact) + } else if attr.has_name(sym::rustc_expected_cgu_reuse) { + match self.field(attr, sym::kind) { + sym::no => (CguReuse::No, ComparisonKind::Exact), + sym::pre_dash_lto => (CguReuse::PreLto, ComparisonKind::Exact), + sym::post_dash_lto => (CguReuse::PostLto, ComparisonKind::Exact), + sym::any => (CguReuse::PreLto, ComparisonKind::AtLeast), + other => { + self.tcx.sess.span_fatal( + attr.span, + &format!("unknown cgu-reuse-kind `{}` specified", other), + ); } - } else { - return; - }; + } + } else { + return; + }; if !self.tcx.sess.opts.debugging_opts.query_dep_graph { self.tcx.sess.span_fatal( diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 9abd4eae914b3..c4dc0fbadc813 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -159,7 +159,7 @@ pub struct DirtyCleanVisitor<'tcx> { impl DirtyCleanVisitor<'tcx> { /// Possibly "deserialize" the attribute into a clean/dirty assertion fn assertion_maybe(&mut self, item_id: LocalDefId, attr: &Attribute) -> Option { - if !self.tcx.sess.check_name(attr, sym::rustc_clean) { + if !attr.has_name(sym::rustc_clean) { // skip: not rustc_clean/dirty return None; } @@ -427,7 +427,7 @@ pub struct FindAllAttrs<'tcx> { impl FindAllAttrs<'tcx> { fn is_active_attr(&mut self, attr: &Attribute) -> bool { - if self.tcx.sess.check_name(attr, sym::rustc_clean) && check_config(self.tcx, attr) { + if attr.has_name(sym::rustc_clean) && check_config(self.tcx, attr) { return true; } diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 8a0964e6b9f92..2f540395b2d79 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -266,7 +266,7 @@ impl<'tcx> Queries<'tcx> { }; let attrs = &*tcx.get_attrs(def_id); - let attrs = attrs.iter().filter(|attr| tcx.sess.check_name(attr, sym::rustc_error)); + let attrs = attrs.iter().filter(|attr| attr.has_name(sym::rustc_error)); for attr in attrs { match attr.meta_item_list() { // Check if there is a `#[rustc_error(delay_span_bug_from_inside_query)]`. diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 8b41a0ff17693..6b64614363f18 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -488,13 +488,13 @@ pub fn get_codegen_sysroot( } pub(crate) fn check_attr_crate_type( - sess: &Session, + _sess: &Session, attrs: &[ast::Attribute], lint_buffer: &mut LintBuffer, ) { // Unconditionally collect crate types from attributes to make them used for a in attrs.iter() { - if sess.check_name(a, sym::crate_type) { + if a.has_name(sym::crate_type) { if let Some(n) = a.value_str() { if categorize_crate_type(n).is_some() { return; @@ -552,7 +552,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec = attrs .iter() .filter_map(|a| { - if session.check_name(a, sym::crate_type) { + if a.has_name(sym::crate_type) { match a.value_str() { Some(s) => categorize_crate_type(s), _ => None, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 5a72db7752d63..afa2cfca1880f 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -46,7 +46,6 @@ use rustc_middle::ty::subst::{GenericArgKind, Subst}; use rustc_middle::ty::Instance; use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt}; use rustc_session::lint::FutureIncompatibilityReason; -use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -344,7 +343,7 @@ impl UnsafeCode { impl EarlyLintPass for UnsafeCode { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { - if cx.sess().check_name(attr, sym::allow_internal_unsafe) { + if attr.has_name(sym::allow_internal_unsafe) { self.report_unsafe(cx, attr.span, |lint| { lint.build( "`allow_internal_unsafe` allows defining \ @@ -492,12 +491,12 @@ pub struct MissingDoc { impl_lint_pass!(MissingDoc => [MISSING_DOCS]); -fn has_doc(sess: &Session, attr: &ast::Attribute) -> bool { +fn has_doc(attr: &ast::Attribute) -> bool { if attr.is_doc_comment() { return true; } - if !sess.check_name(attr, sym::doc) { + if !attr.has_name(sym::doc) { return false; } @@ -554,7 +553,7 @@ impl MissingDoc { } let attrs = cx.tcx.get_attrs(def_id.to_def_id()); - let has_doc = attrs.iter().any(|a| has_doc(cx.sess(), a)); + let has_doc = attrs.iter().any(has_doc); if !has_doc { cx.struct_span_lint( MISSING_DOCS, @@ -568,10 +567,10 @@ impl MissingDoc { } impl<'tcx> LateLintPass<'tcx> for MissingDoc { - fn enter_lint_attrs(&mut self, cx: &LateContext<'_>, attrs: &[ast::Attribute]) { + fn enter_lint_attrs(&mut self, _cx: &LateContext<'_>, attrs: &[ast::Attribute]) { let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { - cx.sess().check_name(attr, sym::doc) + attr.has_name(sym::doc) && match attr.meta_item_list() { None => false, Some(l) => attr::list_contains_name(&l, sym::hidden), @@ -595,7 +594,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { } let attrs = cx.tcx.hir().attrs(macro_def.hir_id()); - let has_doc = attrs.iter().any(|a| has_doc(cx.sess(), a)); + let has_doc = attrs.iter().any(has_doc); if !has_doc { cx.struct_span_lint( MISSING_DOCS, @@ -999,7 +998,7 @@ impl EarlyLintPass for DeprecatedAttr { return; } } - if cx.sess().check_name(attr, sym::no_start) || cx.sess().check_name(attr, sym::crate_id) { + if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) { let path_str = pprust::path_to_string(&attr.get_normal_item().path); let msg = format!("use of deprecated attribute `{}`: no longer used.", path_str); lint_deprecated_attr(cx, attr, &msg, None); @@ -1028,7 +1027,7 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: & let span = sugared_span.take().unwrap_or(attr.span); - if is_doc_comment || cx.sess().check_name(attr, sym::doc) { + if is_doc_comment || attr.has_name(sym::doc) { cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| { let mut err = lint.build("unused doc comment"); err.span_label( @@ -1301,7 +1300,7 @@ declare_lint_pass!( impl<'tcx> LateLintPass<'tcx> for UnstableFeatures { fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) { - if cx.sess().check_name(attr, sym::feature) { + if attr.has_name(sym::feature) { if let Some(items) = attr.meta_item_list() { for item in items { cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| { @@ -2771,7 +2770,7 @@ impl ClashingExternDeclarations { overridden_link_name, tcx.get_attrs(fi.def_id.to_def_id()) .iter() - .find(|at| tcx.sess.check_name(at, sym::link_name)) + .find(|at| at.has_name(sym::link_name)) .unwrap() .span, ) diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index bca3023664ab1..e6cbfa0c9e29d 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -236,8 +236,6 @@ impl<'s> LintLevelsBuilder<'s> { Some(lvl) => lvl, }; - self.sess.mark_attr_used(attr); - let mut metas = unwrap_or!(attr.meta_item_list(), continue); if metas.is_empty() { diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 0ffcd0154de92..c4008e77bab7c 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -151,8 +151,6 @@ macro_rules! late_lint_passes { // FIXME: Look into regression when this is used as a module lint // May Depend on constants elsewhere UnusedBrokenConst: UnusedBrokenConst, - // Uses attr::is_used which is untracked, can't be an incremental module pass. - UnusedAttributes: UnusedAttributes::new(), // Needs to run after UnusedAttributes as it marks all `feature` attributes as used. UnstableFeatures: UnstableFeatures, // Tracks state across modules diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 34d342e66945e..b8f8d5983a295 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -669,9 +669,7 @@ enum FfiResult<'tcx> { } crate fn nonnull_optimization_guaranteed<'tcx>(tcx: TyCtxt<'tcx>, def: &ty::AdtDef) -> bool { - tcx.get_attrs(def.did) - .iter() - .any(|a| tcx.sess.check_name(a, sym::rustc_nonnull_optimization_guaranteed)) + tcx.get_attrs(def.did).iter().any(|a| a.has_name(sym::rustc_nonnull_optimization_guaranteed)) } /// `repr(transparent)` structs can have a single non-ZST field, this function returns that diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index f59ad0ac82d80..be137884b4b27 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -4,21 +4,16 @@ use rustc_ast as ast; use rustc_ast::util::parser; use rustc_ast::{ExprKind, StmtKind}; use rustc_ast_pretty::pprust; -use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, Applicability}; -use rustc_feature::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_middle::ty::adjustment; use rustc_middle::ty::{self, Ty}; -use rustc_session::lint::builtin::UNUSED_ATTRIBUTES; use rustc_span::symbol::Symbol; use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span, DUMMY_SP}; -use tracing::debug; - declare_lint! { /// The `unused_must_use` lint detects unused result of a type flagged as /// `#[must_use]`. @@ -308,7 +303,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { descr_post_path: &str, ) -> bool { for attr in cx.tcx.get_attrs(def_id).iter() { - if cx.sess().check_name(attr, sym::must_use) { + if attr.has_name(sym::must_use) { cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| { let msg = format!( "unused {}`{}`{} that must be used", @@ -382,62 +377,6 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements { } } -#[derive(Copy, Clone)] -pub struct UnusedAttributes { - builtin_attributes: &'static FxHashMap, -} - -impl UnusedAttributes { - pub fn new() -> Self { - UnusedAttributes { builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP } - } -} - -impl_lint_pass!(UnusedAttributes => [UNUSED_ATTRIBUTES]); - -impl<'tcx> LateLintPass<'tcx> for UnusedAttributes { - fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) { - debug!("checking attribute: {:?}", attr); - - if attr.is_doc_comment() { - return; - } - - let attr_info = attr.ident().and_then(|ident| self.builtin_attributes.get(&ident.name)); - - if let Some(&&(name, ty, ..)) = attr_info { - if let AttributeType::AssumedUsed = ty { - debug!("{:?} is AssumedUsed", name); - return; - } - } - - if !cx.sess().is_attr_used(attr) { - debug!("emitting warning for: {:?}", attr); - cx.struct_span_lint(UNUSED_ATTRIBUTES, attr.span, |lint| { - // Mark as used to avoid duplicate warnings. - cx.sess().mark_attr_used(attr); - lint.build("unused attribute").emit() - }); - // Is it a builtin attribute that must be used at the crate level? - if attr_info.map_or(false, |(_, ty, ..)| ty == &AttributeType::CrateLevel) { - cx.struct_span_lint(UNUSED_ATTRIBUTES, attr.span, |lint| { - let msg = match attr.style { - ast::AttrStyle::Outer => { - "crate-level attribute should be an inner attribute: add an exclamation \ - mark: `#![foo]`" - } - ast::AttrStyle::Inner => "crate-level attribute should be in the root module", - }; - lint.build(msg).emit() - }); - } - } else { - debug!("Attr was used: {:?}", attr); - } - } -} - #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum UnusedDelimsCtx { FunctionArg, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 467ec73663be6..6dac3f54cfa94 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3042,6 +3042,7 @@ declare_lint_pass! { RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, UNSUPPORTED_CALLING_CONVENTIONS, BREAK_WITH_LABEL_AND_LOOP, + UNUSED_ATTRIBUTES, ] } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 804b86cd864cb..5f0d8c46f20dc 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -44,8 +44,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> { // Process all of the #[link(..)]-style arguments let sess = &self.tcx.sess; - for m in self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| sess.check_name(a, sym::link)) - { + for m in self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| a.has_name(sym::link)) { let items = match m.meta_item_list() { Some(item) => item, None => continue, diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs index 7ea4902f4bc39..20dcb670cd60b 100644 --- a/compiler/rustc_middle/src/middle/limits.rs +++ b/compiler/rustc_middle/src/middle/limits.rs @@ -48,7 +48,7 @@ pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit { fn get_limit(krate_attrs: &[Attribute], sess: &Session, name: Symbol, default: usize) -> Limit { for attr in krate_attrs { - if !sess.check_name(attr, name) { + if !attr.has_name(name) { continue; } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 106b443ee3c14..9c6ec25213c58 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1136,7 +1136,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound, Bound) { let attrs = self.get_attrs(def_id); let get = |name| { - let attr = match attrs.iter().find(|a| self.sess.check_name(a, name)) { + let attr = match attrs.iter().find(|a| a.has_name(name)) { Some(attr) => attr, None => return Bound::Unbounded, }; diff --git a/compiler/rustc_mir/src/dataflow/framework/engine.rs b/compiler/rustc_mir/src/dataflow/framework/engine.rs index 3f9f558223bb0..7ff7c860591fb 100644 --- a/compiler/rustc_mir/src/dataflow/framework/engine.rs +++ b/compiler/rustc_mir/src/dataflow/framework/engine.rs @@ -338,7 +338,7 @@ impl RustcMirAttrs { let rustc_mir_attrs = attrs .iter() - .filter(|attr| tcx.sess.check_name(attr, sym::rustc_mir)) + .filter(|attr| attr.has_name(sym::rustc_mir)) .flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter())); for attr in rustc_mir_attrs { diff --git a/compiler/rustc_mir/src/dataflow/mod.rs b/compiler/rustc_mir/src/dataflow/mod.rs index 4ca757cf269e4..8a426cc1015cc 100644 --- a/compiler/rustc_mir/src/dataflow/mod.rs +++ b/compiler/rustc_mir/src/dataflow/mod.rs @@ -30,12 +30,12 @@ pub struct MoveDataParamEnv<'tcx> { } pub(crate) fn has_rustc_mir_with( - sess: &Session, + _sess: &Session, attrs: &[ast::Attribute], name: Symbol, ) -> Option { for attr in attrs { - if sess.check_name(attr, sym::rustc_mir) { + if attr.has_name(sym::rustc_mir) { let items = attr.meta_item_list(); for item in items.iter().flat_map(|l| l.iter()) { match item.meta_item() { diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs index 30e758c7fdf05..fea1adfa3d58b 100644 --- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs +++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs @@ -204,11 +204,7 @@ fn emit_unused_generic_params_error<'tcx>( unused_parameters: &FiniteBitSet, ) { let base_def_id = tcx.closure_base_def_id(def_id); - if !tcx - .get_attrs(base_def_id) - .iter() - .any(|a| tcx.sess.check_name(a, sym::rustc_polymorphize_error)) - { + if !tcx.get_attrs(base_def_id).iter().any(|a| a.has_name(sym::rustc_polymorphize_error)) { return; } diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 611d72e61d016..07f972c2fa897 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -13,9 +13,10 @@ use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree}; use rustc_ast::tokenstream::{Spacing, TokenStream}; use rustc_ast::AstLike; use rustc_ast::Attribute; +use rustc_ast::{AttrItem, MetaItem}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Diagnostic, FatalError, Level, PResult}; +use rustc_errors::{Applicability, Diagnostic, FatalError, Level, PResult}; use rustc_session::parse::ParseSess; use rustc_span::{FileName, SourceFile, Span}; @@ -324,3 +325,44 @@ pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal) -> TokenStream { let filename = FileName::macro_expansion_source_code(&source); parse_stream_from_source_str(filename, source, sess, Some(nt.span())) } + +pub fn parse_cfg_attr( + attr: &Attribute, + parse_sess: &ParseSess, +) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> { + match attr.get_normal_item().args { + ast::MacArgs::Delimited(dspan, delim, ref tts) if !tts.is_empty() => { + let msg = "wrong `cfg_attr` delimiters"; + crate::validate_attr::check_meta_bad_delim(parse_sess, dspan, delim, msg); + match parse_in(parse_sess, tts.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) { + Ok(r) => return Some(r), + Err(mut e) => { + e.help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP)) + .note(CFG_ATTR_NOTE_REF) + .emit(); + } + } + } + _ => error_malformed_cfg_attr_missing(attr.span, parse_sess), + } + None +} + +const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]"; +const CFG_ATTR_NOTE_REF: &str = "for more information, visit \ + "; + +fn error_malformed_cfg_attr_missing(span: Span, parse_sess: &ParseSess) { + parse_sess + .span_diagnostic + .struct_span_err(span, "malformed `cfg_attr` attribute input") + .span_suggestion( + span, + "missing condition and attribute", + CFG_ATTR_GRAMMAR_HELP.to_string(), + Applicability::HasPlaceholders, + ) + .note(CFG_ATTR_NOTE_REF) + .emit(); +} diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index 5e49df841d75f..bf1e52cd9a8ad 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -11,6 +11,7 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } +rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_target = { path = "../rustc_target" } rustc_ast = { path = "../rustc_ast" } @@ -18,3 +19,4 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_lexer = { path = "../rustc_lexer" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } +rustc_feature = { path = "../rustc_feature" } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3fea75954b958..3009c2c3f2f4a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -8,8 +8,10 @@ use rustc_middle::hir::map::Map; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; -use rustc_ast::{AttrStyle, Attribute, Lit, LitKind, NestedMetaItem}; +use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, NestedMetaItem}; +use rustc_data_structures::stable_set::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Applicability}; +use rustc_feature::{AttributeType, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; @@ -66,9 +68,10 @@ impl CheckAttrVisitor<'tcx> { ) { let mut is_valid = true; let mut specified_inline = None; + let mut seen = FxHashSet::default(); let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { - is_valid &= match attr.name_or_empty() { + let attr_is_valid = match attr.name_or_empty() { sym::inline => self.check_inline(hir_id, attr, span, target), sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target), sym::marker => self.check_marker(hir_id, attr, span, target), @@ -101,14 +104,66 @@ impl CheckAttrVisitor<'tcx> { sym::default_method_body_is_const => { self.check_default_method_body_is_const(attr, span, target) } + sym::rustc_const_unstable + | sym::rustc_const_stable + | sym::unstable + | sym::stable + | sym::rustc_promotable => self.check_stability_promotable(&attr, span, target), _ => true, }; + is_valid &= attr_is_valid; + // lint-only checks match attr.name_or_empty() { sym::cold => self.check_cold(hir_id, attr, span, target), sym::link_name => self.check_link_name(hir_id, attr, span, target), sym::link_section => self.check_link_section(hir_id, attr, span, target), sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target), + sym::deprecated | sym::rustc_deprecated => { + self.check_deprecated(hir_id, attr, span, target) + } + sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target), + sym::path => self.check_generic_attr(hir_id, attr, target, &[Target::Mod]), + sym::cfg_attr => self.check_cfg_attr(hir_id, attr), + sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target), + sym::macro_export => self.check_macro_export(hir_id, attr, target), + sym::ignore | sym::should_panic | sym::proc_macro_derive => { + self.check_generic_attr(hir_id, attr, target, &[Target::Fn]) + } + _ => {} + } + + if hir_id != CRATE_HIR_ID { + if let Some((_, AttributeType::CrateLevel, ..)) = + attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)) + { + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + let msg = match attr.style { + ast::AttrStyle::Outer => { + "crate-level attribute should be an inner attribute: add an exclamation \ + mark: `#![foo]`" + } + ast::AttrStyle::Inner => "crate-level attribute should be in the root module", + }; + lint.build(msg).emit() + }); + } + } + + // Duplicate attributes + match attr.name_or_empty() { + name @ sym::macro_use => { + let args = attr.meta_item_list().unwrap_or_else(Vec::new); + let args: Vec<_> = args.iter().map(|arg| arg.name_or_empty()).collect(); + if !seen.insert((name, args)) { + self.tcx.struct_span_lint_hir( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + |lint| lint.build("unused attribute").emit(), + ); + } + } _ => {} } } @@ -211,6 +266,38 @@ impl CheckAttrVisitor<'tcx> { } } + fn check_generic_attr( + &self, + hir_id: HirId, + attr: &Attribute, + target: Target, + allowed_targets: &[Target], + ) { + if !allowed_targets.iter().any(|t| t == &target) { + let name = attr.name_or_empty(); + let mut i = allowed_targets.iter(); + // Pluralize + let b = i.next().map_or_else(String::new, |t| t.to_string() + "s"); + let supported_names = i.enumerate().fold(b, |mut b, (i, allowed_target)| { + if allowed_targets.len() > 2 && i == allowed_targets.len() - 2 { + b.push_str(", and "); + } else if allowed_targets.len() == 2 && i == allowed_targets.len() - 2 { + b.push_str(" and "); + } else { + b.push_str(", "); + } + // Pluralize + b.push_str(&(allowed_target.to_string() + "s")); + b + }); + //let supported_names = allowed_targets.iter().fold(String::new(), |msg, t| msg + ", " + &t.to_string()); + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + lint.build(&format!("`#[{name}]` only has an effect on {}", supported_names)) + .emit(); + }); + } + } + /// Checks if `#[naked]` is applied to a function definition. fn check_naked(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) -> bool { match target { @@ -1555,6 +1642,72 @@ impl CheckAttrVisitor<'tcx> { } } } + + fn check_stability_promotable(&self, attr: &Attribute, _span: &Span, target: Target) -> bool { + match target { + Target::Expression => { + self.tcx + .sess + .struct_span_err(attr.span, "attribute cannot be applied to an expression") + .emit(); + false + } + _ => true, + } + } + + fn check_deprecated(&self, hir_id: HirId, attr: &Attribute, _span: &Span, target: Target) { + match target { + Target::Closure | Target::Expression | Target::Statement | Target::Arm => { + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + lint.build("attribute is ignored here").emit(); + }); + } + _ => {} + } + } + + fn check_macro_use(&self, hir_id: HirId, attr: &Attribute, target: Target) { + let name = attr.name_or_empty(); + match target { + Target::ExternCrate | Target::Mod => {} + _ => { + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + lint.build(&format!( + "`#[{name}]` only has an effect on `extern crate` and modules" + )) + .emit(); + }); + } + } + } + + fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) { + if target != Target::MacroDef { + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + lint.build(&format!("`#[macro_export]` only has an effect on macro definitions")) + .emit(); + }); + } + } + + fn check_cfg_attr(&self, hir_id: HirId, attr: &Attribute) { + if let Some((_, attrs)) = rustc_parse::parse_cfg_attr(&attr, &self.tcx.sess.parse_sess) { + if attrs.is_empty() { + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + lint.build("`#[cfg_attr]` does not expand to any attributes").emit(); + }); + } + } + } + + fn check_plugin_registrar(&self, hir_id: HirId, attr: &Attribute, target: Target) { + if target != Target::Fn { + self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { + lint.build("`#[plugin_registrar]` only has an effect on functions").emit(); + }); + } + } } impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { @@ -1675,7 +1828,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { for attr in attrs { for attr_to_check in ATTRS_TO_CHECK { - if tcx.sess.check_name(attr, *attr_to_check) { + if attr.has_name(*attr_to_check) { tcx.sess .struct_span_err( attr.span, @@ -1692,7 +1845,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { fn check_invalid_macro_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { for attr in attrs { - if tcx.sess.check_name(attr, sym::inline) { + if attr.has_name(sym::inline) { struct_span_err!( tcx.sess, attr.span, diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 3cf1d0cdd94b7..e43abda713351 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -15,7 +15,6 @@ use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; -use rustc_session::Session; use rustc_span::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_span::symbol::{sym, Symbol}; @@ -51,7 +50,7 @@ impl<'tcx> DiagnosticItemCollector<'tcx> { fn observe_item(&mut self, def_id: LocalDefId) { let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); let attrs = self.tcx.hir().attrs(hir_id); - if let Some(name) = extract(&self.tcx.sess, attrs) { + if let Some(name) = extract(attrs) { // insert into our table collect_item(self.tcx, &mut self.items, name, def_id.to_def_id()); } @@ -91,10 +90,10 @@ fn collect_item( } } -/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes. -fn extract(sess: &Session, attrs: &[ast::Attribute]) -> Option { +/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.p +fn extract(attrs: &[ast::Attribute]) -> Option { attrs.iter().find_map(|attr| { - if sess.check_name(attr, sym::rustc_diagnostic_item) { attr.value_str() } else { None } + if attr.has_name(sym::rustc_diagnostic_item) { attr.value_str() } else { None } }) } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 3a88d1932a80a..62f9bcfdc4729 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -13,6 +13,7 @@ use crate::weak_lang_items; use rustc_middle::middle::cstore::ExternCrate; use rustc_middle::ty::TyCtxt; +use rustc_ast::Attribute; use rustc_errors::{pluralize, struct_span_err}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -57,7 +58,7 @@ impl LanguageItemCollector<'tcx> { fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId) { let attrs = self.tcx.hir().attrs(hir_id); - let check_name = |attr, sym| self.tcx.sess.check_name(attr, sym); + let check_name = |attr: &Attribute, sym| attr.has_name(sym); if let Some((value, span)) = extract(check_name, &attrs) { match ITEM_REFS.get(&value).cloned() { // Known lang item with attribute on correct target. diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 18c1d647060b1..43a3a3062e77b 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -27,7 +27,7 @@ impl ItemLikeVisitor<'tcx> for LayoutTest<'tcx> { | ItemKind::Struct(..) | ItemKind::Union(..) => { for attr in self.tcx.get_attrs(item.def_id.to_def_id()).iter() { - if self.tcx.sess.check_name(attr, sym::rustc_layout) { + if attr.has_name(sym::rustc_layout) { self.dump_layout_of(item.def_id, item, attr); } } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index cadb8d2358060..f583a5d58d540 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -7,6 +7,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] #![feature(in_band_lifetimes)] +#![feature(format_args_capture)] #![feature(iter_zip)] #![feature(nll)] #![feature(min_specialization)] diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index 363a6417f99d3..605b52f18913f 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -33,9 +33,7 @@ impl LibFeatureCollector<'tcx> { // Find a stability attribute (i.e., `#[stable (..)]`, `#[unstable (..)]`, // `#[rustc_const_unstable (..)]`). - if let Some(stab_attr) = - stab_attrs.iter().find(|stab_attr| self.tcx.sess.check_name(attr, **stab_attr)) - { + if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) { let meta_item = attr.meta(); if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta_item { let mut feature = None; diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 484040de0fb66..b64dcb0bbf03b 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -148,7 +148,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } if self.tcx.features().staged_api { - if let Some(a) = attrs.iter().find(|a| self.tcx.sess.check_name(a, sym::deprecated)) { + if let Some(a) = attrs.iter().find(|a| a.has_name(sym::deprecated)) { self.tcx .sess .struct_span_err(a.span, "`#[deprecated]` cannot be used in staged API") @@ -350,7 +350,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { for attr in attrs { let name = attr.name_or_empty(); if unstable_attrs.contains(&name) { - self.tcx.sess.mark_attr_used(attr); struct_span_err!( self.tcx.sess, attr.span, diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 629513c7cfec9..3a662a9bab2f6 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -1,5 +1,6 @@ //! Validity checking for weak lang items +use rustc_ast::Attribute; use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; @@ -96,7 +97,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { } fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) { - let check_name = |attr, sym| self.tcx.sess.check_name(attr, sym); + let check_name = |attr: &Attribute, sym| attr.has_name(sym); let attrs = self.tcx.hir().attrs(i.hir_id()); if let Some((lang_item, _)) = lang_items::extract(check_name, attrs) { self.register(lang_item, i.span); diff --git a/compiler/rustc_plugin_impl/src/load.rs b/compiler/rustc_plugin_impl/src/load.rs index 5da02e3a4899f..51cf85f794b8a 100644 --- a/compiler/rustc_plugin_impl/src/load.rs +++ b/compiler/rustc_plugin_impl/src/load.rs @@ -32,7 +32,7 @@ pub fn load_plugins( let mut plugins = Vec::new(); for attr in &krate.attrs { - if !sess.check_name(attr, sym::plugin) { + if !attr.has_name(sym::plugin) { continue; } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index a683cb05e16b6..9e4c4b443e77a 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -885,9 +885,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) { // Non-opaque macros cannot make other items more accessible than they already are. let attrs = self.tcx.hir().attrs(md.hir_id()); - if attr::find_transparency(&self.tcx.sess, &attrs, md.ast.macro_rules).0 - != Transparency::Opaque - { + if attr::find_transparency(&attrs, md.ast.macro_rules).0 != Transparency::Opaque { // `#[macro_export]`-ed `macro_rules!` are `Public` since they // ignore their containing path to always appear at the crate root. if md.ast.macro_rules { diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 178d727418d74..c06ef08e0a8bf 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1059,7 +1059,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let mut import_all = None; let mut single_imports = Vec::new(); for attr in &item.attrs { - if self.r.session.check_name(attr, sym::macro_use) { + if attr.has_name(sym::macro_use) { if self.parent_scope.module.parent.is_some() { struct_span_err!( self.r.session, @@ -1165,7 +1165,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { /// Returns `true` if this attribute list contains `macro_use`. fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool { for attr in attrs { - if self.r.session.check_name(attr, sym::macro_escape) { + if attr.has_name(sym::macro_escape) { let msg = "`#[macro_escape]` is a deprecated synonym for `#[macro_use]`"; let mut err = self.r.session.struct_span_warn(attr.span, msg); if let ast::AttrStyle::Inner = attr.style { @@ -1173,7 +1173,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } else { err.emit(); } - } else if !self.r.session.check_name(attr, sym::macro_use) { + } else if !attr.has_name(sym::macro_use) { continue; } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index d79fd910b7e78..882d15cf8920f 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -2057,9 +2057,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { if let Some(def_id) = parent_def_id.as_local() { let parent_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); // lifetimes in `derive` expansions don't count (Issue #53738) - if self.tcx.hir().attrs(parent_hir_id).iter().any(|attr| { - self.tcx.sess.check_name(attr, sym::automatically_derived) - }) { + if self + .tcx + .hir() + .attrs(parent_hir_id) + .iter() + .any(|attr| attr.has_name(sym::automatically_derived)) + { continue; } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 7114fd33188d9..438a109f96737 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -3382,9 +3382,8 @@ impl<'a> Resolver<'a> { let parse_attrs = || { let attrs = self.cstore().item_attrs(def_id, self.session); - let attr = attrs - .iter() - .find(|a| self.session.check_name(a, sym::rustc_legacy_const_generics))?; + let attr = + attrs.iter().find(|a| a.has_name(sym::rustc_legacy_const_generics))?; let mut ret = vec![]; for meta in attr.meta_item_list()? { match meta.literal()?.kind { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 5b163603d5ffb..d49ba861785b3 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -213,8 +213,6 @@ pub struct Session { /// Set of enabled features for the current target. pub target_features: FxHashSet, - used_attrs: Lock, - /// `Span`s for `if` conditions that we have suggested turning into `if let`. pub if_let_suggestions: Lock>, } @@ -1066,39 +1064,14 @@ impl Session { == config::InstrumentCoverage::ExceptUnusedFunctions } - pub fn mark_attr_used(&self, attr: &Attribute) { - self.used_attrs.lock().mark(attr) - } - - pub fn is_attr_used(&self, attr: &Attribute) -> bool { - self.used_attrs.lock().is_marked(attr) - } - - /// Returns `true` if the attribute's path matches the argument. If it - /// matches, then the attribute is marked as used. - /// - /// This method should only be used by rustc, other tools can use - /// `Attribute::has_name` instead, because only rustc is supposed to report - /// the `unused_attributes` lint. (`MetaItem` and `NestedMetaItem` are - /// produced by lowering an `Attribute` and don't have identity, so they - /// only have the `has_name` method, and you need to mark the original - /// `Attribute` as used when necessary.) - pub fn check_name(&self, attr: &Attribute, name: Symbol) -> bool { - let matches = attr.has_name(name); - if matches { - self.mark_attr_used(attr); - } - matches - } - pub fn is_proc_macro_attr(&self, attr: &Attribute) -> bool { [sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive] .iter() - .any(|kind| self.check_name(attr, *kind)) + .any(|kind| attr.has_name(*kind)) } pub fn contains_name(&self, attrs: &[Attribute], name: Symbol) -> bool { - attrs.iter().any(|item| self.check_name(item, name)) + attrs.iter().any(|item| item.has_name(name)) } pub fn find_by_name<'a>( @@ -1106,7 +1079,7 @@ impl Session { attrs: &'a [Attribute], name: Symbol, ) -> Option<&'a Attribute> { - attrs.iter().find(|attr| self.check_name(attr, name)) + attrs.iter().find(|attr| attr.has_name(name)) } pub fn filter_by_name<'a>( @@ -1114,7 +1087,7 @@ impl Session { attrs: &'a [Attribute], name: Symbol, ) -> impl Iterator { - attrs.iter().filter(move |attr| self.check_name(attr, name)) + attrs.iter().filter(move |attr| attr.has_name(name)) } pub fn first_attr_value_str_by_name( @@ -1122,7 +1095,7 @@ impl Session { attrs: &[Attribute], name: Symbol, ) -> Option { - attrs.iter().find(|at| self.check_name(at, name)).and_then(|at| at.value_str()) + attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str()) } } @@ -1359,7 +1332,6 @@ pub fn build_session( miri_unleashed_features: Lock::new(Default::default()), asm_arch, target_features: FxHashSet::default(), - used_attrs: Lock::new(MarkedAttrs::new()), if_let_suggestions: Default::default(), }; diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index bfe9c4d6de3de..183df96f31668 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -35,7 +35,7 @@ impl SymbolNamesTest<'tcx> { fn process_attrs(&mut self, def_id: LocalDefId) { let tcx = self.tcx; for attr in tcx.get_attrs(def_id.to_def_id()).iter() { - if tcx.sess.check_name(attr, SYMBOL_NAME) { + if attr.has_name(SYMBOL_NAME) { let def_id = def_id.to_def_id(); let instance = Instance::new( def_id, @@ -47,7 +47,7 @@ impl SymbolNamesTest<'tcx> { tcx.sess.span_err(attr.span, &format!("demangling({})", demangling)); tcx.sess.span_err(attr.span, &format!("demangling-alt({:#})", demangling)); } - } else if tcx.sess.check_name(attr, DEF_PATH) { + } else if attr.has_name(DEF_PATH) { let path = with_no_trimmed_paths(|| tcx.def_path_str(def_id.to_def_id())); tcx.sess.span_err(attr.span, &format!("def-path({})", path)); } diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index e5a00f706398a..ccfa0893d11fa 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -257,7 +257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // FIXME? Other potential candidate methods: `as_ref` and // `as_mut`? - .any(|a| self.sess().check_name(a, sym::rustc_conversion_suggestion)) + .any(|a| a.has_name(sym::rustc_conversion_suggestion)) }); methods diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 9fbf5ab85334f..1c6fd5983cb59 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -21,6 +21,7 @@ use crate::constrained_generic_params as cgp; use crate::errors; use crate::middle::resolve_lifetime as rl; use rustc_ast as ast; +use rustc_ast::Attribute; use rustc_ast::{MetaItemKind, NestedMetaItem}; use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr}; use rustc_data_structures::captures::Captures; @@ -2769,11 +2770,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { let mut link_ordinal_span = None; let mut no_sanitize_span = None; for attr in attrs.iter() { - if tcx.sess.check_name(attr, sym::cold) { + if attr.has_name(sym::cold) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD; - } else if tcx.sess.check_name(attr, sym::rustc_allocator) { + } else if attr.has_name(sym::rustc_allocator) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR; - } else if tcx.sess.check_name(attr, sym::ffi_returns_twice) { + } else if attr.has_name(sym::ffi_returns_twice) { if tcx.is_foreign_item(id) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE; } else { @@ -2786,9 +2787,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { ) .emit(); } - } else if tcx.sess.check_name(attr, sym::ffi_pure) { + } else if attr.has_name(sym::ffi_pure) { if tcx.is_foreign_item(id) { - if attrs.iter().any(|a| tcx.sess.check_name(a, sym::ffi_const)) { + if attrs.iter().any(|a| a.has_name(sym::ffi_const)) { // `#[ffi_const]` functions cannot be `#[ffi_pure]` struct_span_err!( tcx.sess, @@ -2810,7 +2811,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { ) .emit(); } - } else if tcx.sess.check_name(attr, sym::ffi_const) { + } else if attr.has_name(sym::ffi_const) { if tcx.is_foreign_item(id) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST; } else { @@ -2823,19 +2824,19 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { ) .emit(); } - } else if tcx.sess.check_name(attr, sym::rustc_allocator_nounwind) { + } else if attr.has_name(sym::rustc_allocator_nounwind) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND; - } else if tcx.sess.check_name(attr, sym::naked) { + } else if attr.has_name(sym::naked) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED; - } else if tcx.sess.check_name(attr, sym::no_mangle) { + } else if attr.has_name(sym::no_mangle) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; - } else if tcx.sess.check_name(attr, sym::no_coverage) { + } else if attr.has_name(sym::no_coverage) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE; - } else if tcx.sess.check_name(attr, sym::rustc_std_internal_symbol) { + } else if attr.has_name(sym::rustc_std_internal_symbol) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; - } else if tcx.sess.check_name(attr, sym::used) { + } else if attr.has_name(sym::used) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED; - } else if tcx.sess.check_name(attr, sym::cmse_nonsecure_entry) { + } else if attr.has_name(sym::cmse_nonsecure_entry) { if !matches!(tcx.fn_sig(id).abi(), abi::Abi::C { .. }) { struct_span_err!( tcx.sess, @@ -2850,15 +2851,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { .emit(); } codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY; - } else if tcx.sess.check_name(attr, sym::thread_local) { + } else if attr.has_name(sym::thread_local) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; - } else if tcx.sess.check_name(attr, sym::track_caller) { + } else if attr.has_name(sym::track_caller) { if tcx.is_closure(id) || tcx.fn_sig(id).abi() != abi::Abi::Rust { struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI") .emit(); } codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; - } else if tcx.sess.check_name(attr, sym::export_name) { + } else if attr.has_name(sym::export_name) { if let Some(s) = attr.value_str() { if s.as_str().contains('\0') { // `#[export_name = ...]` will be converted to a null-terminated string, @@ -2873,7 +2874,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } codegen_fn_attrs.export_name = Some(s); } - } else if tcx.sess.check_name(attr, sym::target_feature) { + } else if attr.has_name(sym::target_feature) { if !tcx.is_closure(id) && tcx.fn_sig(id).unsafety() == hir::Unsafety::Normal { if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc { // The `#[target_feature]` attribute is allowed on @@ -2913,11 +2914,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { &supported_target_features, &mut codegen_fn_attrs.target_features, ); - } else if tcx.sess.check_name(attr, sym::linkage) { + } else if attr.has_name(sym::linkage) { if let Some(val) = attr.value_str() { codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str())); } - } else if tcx.sess.check_name(attr, sym::link_section) { + } else if attr.has_name(sym::link_section) { if let Some(val) = attr.value_str() { if val.as_str().bytes().any(|b| b == 0) { let msg = format!( @@ -2930,14 +2931,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.link_section = Some(val); } } - } else if tcx.sess.check_name(attr, sym::link_name) { + } else if attr.has_name(sym::link_name) { codegen_fn_attrs.link_name = attr.value_str(); - } else if tcx.sess.check_name(attr, sym::link_ordinal) { + } else if attr.has_name(sym::link_ordinal) { link_ordinal_span = Some(attr.span); if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) { codegen_fn_attrs.link_ordinal = ordinal; } - } else if tcx.sess.check_name(attr, sym::no_sanitize) { + } else if attr.has_name(sym::no_sanitize) { no_sanitize_span = Some(attr.span); if let Some(list) = attr.meta_item_list() { for item in list.iter() { @@ -2957,7 +2958,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } } } - } else if tcx.sess.check_name(attr, sym::instruction_set) { + } else if attr.has_name(sym::instruction_set) { codegen_fn_attrs.instruction_set = match attr.meta().map(|i| i.kind) { Some(MetaItemKind::List(ref items)) => match items.as_slice() { [NestedMetaItem::MetaItem(set)] => { @@ -3026,7 +3027,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { None } }; - } else if tcx.sess.check_name(attr, sym::repr) { + } else if attr.has_name(sym::repr) { codegen_fn_attrs.alignment = match attr.meta_item_list() { Some(items) => match items.as_slice() { [item] => match item.name_value_literal() { @@ -3064,12 +3065,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { return ia; } match attr.meta().map(|i| i.kind) { - Some(MetaItemKind::Word) => { - tcx.sess.mark_attr_used(attr); - InlineAttr::Hint - } + Some(MetaItemKind::Word) => InlineAttr::Hint, Some(MetaItemKind::List(ref items)) => { - tcx.sess.mark_attr_used(attr); inline_span = Some(attr.span); if items.len() != 1 { struct_span_err!( @@ -3112,7 +3109,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { ia } Some(MetaItemKind::List(ref items)) => { - tcx.sess.mark_attr_used(attr); inline_span = Some(attr.span); if items.len() != 1 { err(attr.span, "expected one argument"); @@ -3181,7 +3177,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { if tcx.is_weak_lang_item(id) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; } - let check_name = |attr, sym| tcx.sess.check_name(attr, sym); + let check_name = |attr: &Attribute, sym| attr.has_name(sym); if let Some(name) = weak_lang_items::link_name(check_name, &attrs) { codegen_fn_attrs.export_name = Some(name); codegen_fn_attrs.link_name = Some(name); diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 9ed2a965dbeab..61631f3b14bb1 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -291,7 +291,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { } for attr in tcx.get_attrs(main_def_id) { - if tcx.sess.check_name(attr, sym::track_caller) { + if attr.has_name(sym::track_caller) { tcx.sess .struct_span_err( attr.span, @@ -405,7 +405,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { let attrs = tcx.hir().attrs(start_id); for attr in attrs { - if tcx.sess.check_name(attr, sym::track_caller) { + if attr.has_name(sym::track_caller) { tcx.sess .struct_span_err( attr.span, diff --git a/src/test/ui/attributes/register-attr-tool-unused.rs b/src/test/ui/attributes/register-attr-tool-unused.rs index 546e372f5e303..680614656538a 100644 --- a/src/test/ui/attributes/register-attr-tool-unused.rs +++ b/src/test/ui/attributes/register-attr-tool-unused.rs @@ -4,7 +4,5 @@ #![feature(register_tool)] #[register_attr(attr)] //~ ERROR crate-level attribute should be an inner attribute - //~| ERROR unused attribute #[register_tool(tool)] //~ ERROR crate-level attribute should be an inner attribute - //~| ERROR unused attribute fn main() {} diff --git a/src/test/ui/attributes/register-attr-tool-unused.stderr b/src/test/ui/attributes/register-attr-tool-unused.stderr index 85a4fa4a74813..8d2e1b6bc2894 100644 --- a/src/test/ui/attributes/register-attr-tool-unused.stderr +++ b/src/test/ui/attributes/register-attr-tool-unused.stderr @@ -1,4 +1,4 @@ -error: unused attribute +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` --> $DIR/register-attr-tool-unused.rs:6:1 | LL | #[register_attr(attr)] @@ -12,22 +12,10 @@ LL | #![deny(unused)] = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]` error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/register-attr-tool-unused.rs:6:1 - | -LL | #[register_attr(attr)] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/register-attr-tool-unused.rs:8:1 - | -LL | #[register_tool(tool)] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/register-attr-tool-unused.rs:8:1 + --> $DIR/register-attr-tool-unused.rs:7:1 | LL | #[register_tool(tool)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.rs b/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.rs index 4c96d6e7ca17d..2600ec7c444a0 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.rs @@ -4,10 +4,10 @@ #![deny(unused)] -#[cfg_attr(FALSE,)] //~ ERROR unused attribute +#[cfg_attr(FALSE,)] //~ ERROR `#[cfg_attr]` does not expand to any attributes fn _f() {} -#[cfg_attr(TRUE,)] //~ ERROR unused attribute +#[cfg_attr(TRUE,)] //~ ERROR `#[cfg_attr]` does not expand to any attributes fn _g() {} fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr b/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr index 67cb6530e3831..87b6988135353 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr +++ b/src/test/ui/conditional-compilation/cfg-attr-empty-is-unused.stderr @@ -1,4 +1,4 @@ -error: unused attribute +error: `#[cfg_attr]` does not expand to any attributes --> $DIR/cfg-attr-empty-is-unused.rs:7:1 | LL | #[cfg_attr(FALSE,)] @@ -11,7 +11,7 @@ LL | #![deny(unused)] | ^^^^^^ = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]` -error: unused attribute +error: `#[cfg_attr]` does not expand to any attributes --> $DIR/cfg-attr-empty-is-unused.rs:10:1 | LL | #[cfg_attr(TRUE,)] diff --git a/src/test/ui/const-generics/defaults/default-annotation.rs b/src/test/ui/const-generics/defaults/default-annotation.rs index 3febb7cffbf15..8eb8f368b12f3 100644 --- a/src/test/ui/const-generics/defaults/default-annotation.rs +++ b/src/test/ui/const-generics/defaults/default-annotation.rs @@ -13,7 +13,6 @@ pub struct ConstDefaultUnstable; #[stable(feature = "const_default_unstable", since="none")] pub struct ConstDefaultStable; diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index b30ab446d7a01..767c521b91f2b 100644 --- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -49,14 +49,14 @@ #![macro_use] // (allowed if no argument; see issue-43160-gating-of-macro_use.rs) // skipping testing of cfg // skipping testing of cfg_attr -#![should_panic] //~ WARN unused attribute -#![ignore] //~ WARN unused attribute +#![should_panic] //~ WARN `#[should_panic]` only has an effect +#![ignore] //~ WARN `#[ignore]` only has an effect on functions #![no_implicit_prelude] #![reexport_test_harness_main = "2900"] // see gated-link-args.rs // see issue-43106-gating-of-macro_escape.rs for crate-level; but non crate-level is below at "2700" // (cannot easily test gating of crate-level #[no_std]; but non crate-level is below at "2600") -#![proc_macro_derive()] //~ WARN unused attribute +#![proc_macro_derive()] //~ WARN `#[proc_macro_derive]` only has an effect #![doc = "2400"] #![cold] //~ WARN attribute should be applied to a function //~^ WARN @@ -182,35 +182,35 @@ mod macro_use { mod inner { #![macro_use] } #[macro_use] fn f() { } - //~^ WARN unused attribute + //~^ `#[macro_use]` only has an effect #[macro_use] struct S; - //~^ WARN unused attribute + //~^ `#[macro_use]` only has an effect #[macro_use] type T = S; - //~^ WARN unused attribute + //~^ `#[macro_use]` only has an effect #[macro_use] impl S { } - //~^ WARN unused attribute + //~^ `#[macro_use]` only has an effect } #[macro_export] -//~^ WARN unused attribute +//~^ WARN `#[macro_export]` only has an effect on macro definitions mod macro_export { mod inner { #![macro_export] } - //~^ WARN unused attribute + //~^ WARN `#[macro_export]` only has an effect on macro definitions #[macro_export] fn f() { } - //~^ WARN unused attribute + //~^ WARN `#[macro_export]` only has an effect on macro definitions #[macro_export] struct S; - //~^ WARN unused attribute + //~^ WARN `#[macro_export]` only has an effect on macro definitions #[macro_export] type T = S; - //~^ WARN unused attribute + //~^ WARN `#[macro_export]` only has an effect on macro definitions #[macro_export] impl S { } - //~^ WARN unused attribute + //~^ WARN `#[macro_export]` only has an effect on macro definitions } // At time of unit test authorship, if compiling without `--test` then @@ -263,35 +263,32 @@ mod path { mod inner { #![path="3800"] } #[path = "3800"] fn f() { } - //~^ WARN unused attribute + //~^ WARN `#[path]` only has an effect #[path = "3800"] struct S; - //~^ WARN unused attribute + //~^ WARN `#[path]` only has an effect #[path = "3800"] type T = S; - //~^ WARN unused attribute + //~^ WARN `#[path]` only has an effect #[path = "3800"] impl S { } - //~^ WARN unused attribute + //~^ WARN `#[path]` only has an effect } +// Don't warn on `automatically_derived` - a custom derive +// could reasonally annotate anything that it emits with +// this attribute #[automatically_derived] -//~^ WARN unused attribute mod automatically_derived { mod inner { #![automatically_derived] } - //~^ WARN unused attribute #[automatically_derived] fn f() { } - //~^ WARN unused attribute #[automatically_derived] struct S; - //~^ WARN unused attribute #[automatically_derived] type T = S; - //~^ WARN unused attribute #[automatically_derived] impl S { } - //~^ WARN unused attribute } #[no_mangle] @@ -335,79 +332,77 @@ mod no_mangle { } #[should_panic] -//~^ WARN unused attribute +//~^ WARN `#[should_panic]` only has an effect on mod should_panic { mod inner { #![should_panic] } - //~^ WARN unused attribute + //~^ WARN `#[should_panic]` only has an effect on #[should_panic] fn f() { } - //~^ WARN unused attribute #[should_panic] struct S; - //~^ WARN unused attribute + //~^ WARN `#[should_panic]` only has an effect on #[should_panic] type T = S; - //~^ WARN unused attribute + //~^ WARN `#[should_panic]` only has an effect on #[should_panic] impl S { } - //~^ WARN unused attribute + //~^ WARN `#[should_panic]` only has an effect on } #[ignore] -//~^ WARN unused attribute +//~^ WARN `#[ignore]` only has an effect on functions mod ignore { mod inner { #![ignore] } - //~^ WARN unused attribute + //~^ WARN `#[ignore]` only has an effect on functions #[ignore] fn f() { } - //~^ WARN unused attribute #[ignore] struct S; - //~^ WARN unused attribute + //~^ WARN `#[ignore]` only has an effect on functions #[ignore] type T = S; - //~^ WARN unused attribute + //~^ WARN `#[ignore]` only has an effect on functions #[ignore] impl S { } - //~^ WARN unused attribute + //~^ WARN `#[ignore]` only has an effect on functions } #[no_implicit_prelude] -//~^ WARN unused attribute +//~^ WARN crate-level attribute mod no_implicit_prelude { mod inner { #![no_implicit_prelude] } - //~^ WARN unused attribute + //~^ WARN crate-level attribute #[no_implicit_prelude] fn f() { } - //~^ WARN unused attribute + //~^ WARN crate-level attribute #[no_implicit_prelude] struct S; - //~^ WARN unused attribute + //~^ WARN crate-level attribute #[no_implicit_prelude] type T = S; - //~^ WARN unused attribute + //~^ WARN crate-level attribute #[no_implicit_prelude] impl S { } - //~^ WARN unused attribute + //~^ WARN crate-level attribute } #[reexport_test_harness_main = "2900"] -//~^ WARN unused attribute +//~^ WARN crate-level attribute should be mod reexport_test_harness_main { mod inner { #![reexport_test_harness_main="2900"] } - //~^ WARN unused attribute + //~^ WARN crate-level attribute should be #[reexport_test_harness_main = "2900"] fn f() { } - //~^ WARN unused attribute + //~^ WARN crate-level attribute should be #[reexport_test_harness_main = "2900"] struct S; - //~^ WARN unused attribute + //~^ WARN crate-level attribute should be #[reexport_test_harness_main = "2900"] type T = S; - //~^ WARN unused attribute + //~^ WARN crate-level attribute should be #[reexport_test_harness_main = "2900"] impl S { } - //~^ WARN unused attribute + //~^ WARN crate-level attribute should be } // Cannot feed "2700" to `#[macro_escape]` without signaling an error. @@ -419,41 +414,35 @@ mod macro_escape { //~| HELP try an outer attribute: `#[macro_use]` #[macro_escape] fn f() { } - //~^ WARN unused attribute + //~^ WARN `#[macro_escape]` only has an effect #[macro_escape] struct S; - //~^ WARN unused attribute + //~^ WARN `#[macro_escape]` only has an effect #[macro_escape] type T = S; - //~^ WARN unused attribute + //~^ WARN `#[macro_escape]` only has an effect #[macro_escape] impl S { } - //~^ WARN unused attribute + //~^ WARN `#[macro_escape]` only has an effect } #[no_std] -//~^ WARN unused attribute -//~| WARN crate-level attribute should be an inner attribute +//~^ WARN crate-level attribute should be an inner attribute mod no_std { mod inner { #![no_std] } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be in the root module +//~^ WARN crate-level attribute should be in the root module #[no_std] fn f() { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[no_std] struct S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[no_std] type T = S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[no_std] impl S { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute } // At time of authorship, #[proc_macro_derive = "2500"] signals error @@ -633,104 +622,80 @@ mod windows_subsystem { // BROKEN USES OF CRATE-LEVEL BUILT-IN ATTRIBUTES #[crate_name = "0900"] -//~^ WARN unused attribute -//~| WARN crate-level attribute should be an inner attribute +//~^ WARN crate-level attribute should be an inner attribute mod crate_name { mod inner { #![crate_name="0900"] } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be in the root module +//~^ WARN crate-level attribute should be in the root module #[crate_name = "0900"] fn f() { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[crate_name = "0900"] struct S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[crate_name = "0900"] type T = S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[crate_name = "0900"] impl S { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute } #[crate_type = "0800"] -//~^ WARN unused attribute -//~| WARN crate-level attribute should be an inner attribute +//~^ WARN crate-level attribute should be an inner attribute mod crate_type { mod inner { #![crate_type="0800"] } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be in the root module +//~^ WARN crate-level attribute should be in the root module #[crate_type = "0800"] fn f() { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[crate_type = "0800"] struct S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[crate_type = "0800"] type T = S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[crate_type = "0800"] impl S { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute } #[feature(x0600)] -//~^ WARN unused attribute -//~| WARN crate-level attribute should be an inner attribute +//~^ WARN crate-level attribute should be an inner attribute mod feature { mod inner { #![feature(x0600)] } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be in the root module +//~^ WARN crate-level attribute should be in the root module #[feature(x0600)] fn f() { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[feature(x0600)] struct S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[feature(x0600)] type T = S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[feature(x0600)] impl S { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute } #[no_main] -//~^ WARN unused attribute -//~| WARN crate-level attribute should be an inner attribute +//~^ WARN crate-level attribute should be an inner attribute mod no_main_1 { mod inner { #![no_main] } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be in the root module +//~^ WARN crate-level attribute should be in the root module #[no_main] fn f() { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[no_main] struct S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[no_main] type T = S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[no_main] impl S { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute } #[no_builtins] @@ -747,53 +712,41 @@ mod no_builtins { } #[recursion_limit="0200"] -//~^ WARN unused attribute -//~| WARN crate-level attribute should be an inner attribute +//~^ WARN crate-level attribute should be an inner attribute mod recursion_limit { mod inner { #![recursion_limit="0200"] } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be in the root module +//~^ WARN crate-level attribute should be in the root module #[recursion_limit="0200"] fn f() { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[recursion_limit="0200"] struct S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[recursion_limit="0200"] type T = S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[recursion_limit="0200"] impl S { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute } #[type_length_limit="0100"] -//~^ WARN unused attribute -//~| WARN crate-level attribute should be an inner attribute +//~^ WARN crate-level attribute should be an inner attribute mod type_length_limit { mod inner { #![type_length_limit="0100"] } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be in the root module +//~^ WARN crate-level attribute should be in the root module #[type_length_limit="0100"] fn f() { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[type_length_limit="0100"] struct S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[type_length_limit="0100"] type T = S; - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute #[type_length_limit="0100"] impl S { } - //~^ WARN unused attribute - //~| WARN crate-level attribute should be an inner attribute + //~^ WARN crate-level attribute should be an inner attribute } fn main() {} diff --git a/src/test/ui/invalid/invalid-plugin-attr.rs b/src/test/ui/invalid/invalid-plugin-attr.rs index 3ba7389d5db69..3080af2450047 100644 --- a/src/test/ui/invalid/invalid-plugin-attr.rs +++ b/src/test/ui/invalid/invalid-plugin-attr.rs @@ -1,8 +1,7 @@ #![deny(unused_attributes)] #![feature(plugin)] -#[plugin(bla)] //~ ERROR unused attribute - //~^ ERROR should be an inner attribute +#[plugin(bla)] //~ ERROR should be an inner attribute //~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated fn main() {} diff --git a/src/test/ui/invalid/invalid-plugin-attr.stderr b/src/test/ui/invalid/invalid-plugin-attr.stderr index c822d908dddf9..d3882d33fc484 100644 --- a/src/test/ui/invalid/invalid-plugin-attr.stderr +++ b/src/test/ui/invalid/invalid-plugin-attr.stderr @@ -6,7 +6,7 @@ LL | #[plugin(bla)] | = note: `#[warn(deprecated)]` on by default -error: unused attribute +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` --> $DIR/invalid-plugin-attr.rs:4:1 | LL | #[plugin(bla)] @@ -18,11 +18,5 @@ note: the lint level is defined here LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/invalid-plugin-attr.rs:4:1 - | -LL | #[plugin(bla)] - | ^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/lint/lint-misplaced-attr.rs b/src/test/ui/lint/lint-misplaced-attr.rs index e5ad7a53e0cc9..d06917ea3f8ab 100644 --- a/src/test/ui/lint/lint-misplaced-attr.rs +++ b/src/test/ui/lint/lint-misplaced-attr.rs @@ -4,9 +4,7 @@ #![deny(unused_attributes)] mod a { - #![crate_type = "bin"] //~ ERROR unused attribute - //~^ ERROR should be in the root module + #![crate_type = "bin"] //~ ERROR should be in the root module } -#[crate_type = "bin"] fn main() {} //~ ERROR unused attribute - //~^ ERROR should be an inner +#[crate_type = "bin"] fn main() {} //~ ERROR should be an inner diff --git a/src/test/ui/lint/lint-misplaced-attr.stderr b/src/test/ui/lint/lint-misplaced-attr.stderr index 3a7ca2f83aeba..abaf4620e6f8f 100644 --- a/src/test/ui/lint/lint-misplaced-attr.stderr +++ b/src/test/ui/lint/lint-misplaced-attr.stderr @@ -1,4 +1,4 @@ -error: unused attribute +error: crate-level attribute should be in the root module --> $DIR/lint-misplaced-attr.rs:7:5 | LL | #![crate_type = "bin"] @@ -10,23 +10,11 @@ note: the lint level is defined here LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -error: crate-level attribute should be in the root module - --> $DIR/lint-misplaced-attr.rs:7:5 - | -LL | #![crate_type = "bin"] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/lint-misplaced-attr.rs:11:1 - | -LL | #[crate_type = "bin"] fn main() {} - | ^^^^^^^^^^^^^^^^^^^^^ - error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/lint-misplaced-attr.rs:11:1 + --> $DIR/lint-misplaced-attr.rs:10:1 | LL | #[crate_type = "bin"] fn main() {} | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/unused/unused-attr-macro-rules.rs b/src/test/ui/lint/unused/unused-attr-macro-rules.rs index 396137a11d069..c0fc280ab1a7c 100644 --- a/src/test/ui/lint/unused/unused-attr-macro-rules.rs +++ b/src/test/ui/lint/unused/unused-attr-macro-rules.rs @@ -4,10 +4,9 @@ // A sample of various built-in attributes. #[macro_export] -#[macro_use] //~ ERROR unused attribute -#[path="foo"] //~ ERROR unused attribute -#[recursion_limit="1"] //~ ERROR unused attribute - //~| ERROR crate-level attribute should be an inner attribute +#[macro_use] //~ ERROR `#[macro_use]` only has an effect +#[path="foo"] //~ ERROR #[path]` only has an effect +#[recursion_limit="1"] //~ ERROR crate-level attribute should be an inner attribute macro_rules! foo { () => {}; } diff --git a/src/test/ui/lint/unused/unused-attr-macro-rules.stderr b/src/test/ui/lint/unused/unused-attr-macro-rules.stderr index 4606be01ac014..e3ca90d9acdd0 100644 --- a/src/test/ui/lint/unused/unused-attr-macro-rules.stderr +++ b/src/test/ui/lint/unused/unused-attr-macro-rules.stderr @@ -1,4 +1,4 @@ -error: unused attribute +error: `#[macro_use]` only has an effect on `extern crate` and modules --> $DIR/unused-attr-macro-rules.rs:7:1 | LL | #[macro_use] @@ -10,23 +10,17 @@ note: the lint level is defined here LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -error: unused attribute +error: `#[path]` only has an effect on modules --> $DIR/unused-attr-macro-rules.rs:8:1 | LL | #[path="foo"] | ^^^^^^^^^^^^^ -error: unused attribute - --> $DIR/unused-attr-macro-rules.rs:9:1 - | -LL | #[recursion_limit="1"] - | ^^^^^^^^^^^^^^^^^^^^^^ - error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` --> $DIR/unused-attr-macro-rules.rs:9:1 | LL | #[recursion_limit="1"] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/unused/unused-attr.rs b/src/test/ui/lint/unused/unused-attr.rs deleted file mode 100644 index cb8ac0e6a05c0..0000000000000 --- a/src/test/ui/lint/unused/unused-attr.rs +++ /dev/null @@ -1,49 +0,0 @@ -#![deny(unused_attributes)] -#![feature(rustc_attrs)] - -#![rustc_dummy] //~ ERROR unused attribute - -#[rustc_dummy] //~ ERROR unused attribute -extern crate core; - -#[rustc_dummy] //~ ERROR unused attribute -use std::collections; - -#[rustc_dummy] //~ ERROR unused attribute -extern "C" { - #[rustc_dummy] //~ ERROR unused attribute - fn foo(); -} - -#[rustc_dummy] //~ ERROR unused attribute -mod foo { - #[rustc_dummy] //~ ERROR unused attribute - pub enum Foo { - #[rustc_dummy] //~ ERROR unused attribute - Bar, - } -} - -#[rustc_dummy] //~ ERROR unused attribute -fn bar(f: foo::Foo) { - match f { - #[rustc_dummy] //~ ERROR unused attribute - foo::Foo::Bar => {} - } -} - -#[rustc_dummy] //~ ERROR unused attribute -struct Foo { - #[rustc_dummy] //~ ERROR unused attribute - a: isize -} - -#[rustc_dummy] //~ ERROR unused attribute -trait Baz { - #[rustc_dummy] //~ ERROR unused attribute - fn blah(&self); - #[rustc_dummy] //~ ERROR unused attribute - fn blah2(&self) {} -} - -fn main() {} diff --git a/src/test/ui/lint/unused/unused-attr.stderr b/src/test/ui/lint/unused/unused-attr.stderr deleted file mode 100644 index 707521b7802f0..0000000000000 --- a/src/test/ui/lint/unused/unused-attr.stderr +++ /dev/null @@ -1,98 +0,0 @@ -error: unused attribute - --> $DIR/unused-attr.rs:4:1 - | -LL | #![rustc_dummy] - | ^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/unused-attr.rs:1:9 - | -LL | #![deny(unused_attributes)] - | ^^^^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:6:1 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:9:1 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:12:1 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:14:5 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:18:1 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:20:5 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:22:9 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:27:1 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:30:9 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:35:1 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:37:5 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:41:1 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:43:5 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: unused attribute - --> $DIR/unused-attr.rs:45:5 - | -LL | #[rustc_dummy] - | ^^^^^^^^^^^^^^ - -error: aborting due to 15 previous errors -