From 74b6d296dbcdece2b7bf8cf10370c17c0ed564e7 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 1 Apr 2022 15:04:47 +0200 Subject: [PATCH 1/8] don't encode only locally used attrs --- compiler/rustc_feature/src/builtin_attrs.rs | 48 +++++++++++++++----- compiler/rustc_feature/src/lib.rs | 5 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 10 ++-- compiler/rustc_middle/src/query/mod.rs | 3 ++ compiler/rustc_middle/src/ty/mod.rs | 4 ++ 5 files changed, 54 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index c5f42aa7af724..f512594977c8d 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -147,6 +147,16 @@ pub enum AttributeDuplicates { FutureWarnPreceding, } +/// A conveniece macro to deal with `$($expr)?`. +macro_rules! or_default { + ($default:expr,) => { + $default + }; + ($default:expr, $next:expr) => { + $next + }; +} + /// A convenience macro for constructing attribute templates. /// E.g., `template!(Word, List: "description")` means that the attribute /// supports forms `#[attr]` and `#[attr(description)]`. @@ -168,9 +178,10 @@ macro_rules! template { } macro_rules! ungated { - ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(,)?) => { + ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)? $(,)?) => { BuiltinAttribute { name: sym::$attr, + only_local: or_default!(false, $($only_local)?), type_: $typ, template: $tpl, gate: Ungated, @@ -180,18 +191,20 @@ macro_rules! ungated { } macro_rules! gated { - ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $gate:ident, $msg:expr $(,)?) => { + ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $gate:ident, $msg:expr $(,)?) => { BuiltinAttribute { name: sym::$attr, + only_local: or_default!(false, $($only_local)?), type_: $typ, template: $tpl, duplicates: $duplicates, gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)), } }; - ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $msg:expr $(,)?) => { + ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $msg:expr $(,)?) => { BuiltinAttribute { name: sym::$attr, + only_local: or_default!(false, $($only_local)?), type_: $typ, template: $tpl, duplicates: $duplicates, @@ -201,12 +214,13 @@ macro_rules! gated { } macro_rules! rustc_attr { - (TEST, $attr:ident, $typ:expr, $tpl:expr, $duplicate:expr $(,)?) => { + (TEST, $attr:ident, $typ:expr, $tpl:expr, $duplicate:expr $(, @only_local: $only_local:expr)? $(,)?) => { rustc_attr!( $attr, $typ, $tpl, $duplicate, + $(@only_local: $only_local,)? concat!( "the `#[", stringify!($attr), @@ -215,9 +229,10 @@ macro_rules! rustc_attr { ), ) }; - ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $msg:expr $(,)?) => { + ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $msg:expr $(,)?) => { BuiltinAttribute { name: sym::$attr, + only_local: or_default!(false, $($only_local)?), type_: $typ, template: $tpl, duplicates: $duplicates, @@ -237,6 +252,10 @@ const INTERNAL_UNSTABLE: &str = "this is an internal attribute that will never b pub struct BuiltinAttribute { pub name: Symbol, + /// Whether this attribute is only used in the local crate. + /// + /// If so, it is not encoded in the crate metadata. + pub only_local: bool, pub type_: AttributeType, pub template: AttributeTemplate, pub duplicates: AttributeDuplicates, @@ -295,7 +314,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(must_use, Normal, template!(Word, NameValueStr: "reason"), FutureWarnFollowing), gated!( must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, - must_not_suspend, experimental!(must_not_suspend) + experimental!(must_not_suspend) ), ungated!( deprecated, Normal, @@ -394,6 +413,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Plugins: BuiltinAttribute { name: sym::plugin, + only_local: false, type_: CrateLevel, template: template!(List: "name"), duplicates: DuplicatesOk, @@ -475,7 +495,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // DuplicatesOk since it has its own validation ungated!( - stable, Normal, template!(List: r#"feature = "name", since = "version""#), DuplicatesOk + stable, Normal, template!(List: r#"feature = "name", since = "version""#), DuplicatesOk, ), ungated!( unstable, Normal, @@ -633,7 +653,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Internal attributes, Misc: // ========================================================================== gated!( - lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, lang_items, + lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, @only_local: true, lang_items, "language items are subject to change", ), rustc_attr!( @@ -642,11 +662,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference." ), rustc_attr!( - rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, + rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, @only_local: true, "#![rustc_coherence_is_core] allows inherent methods on builtin types, only intended to be used in `core`." ), rustc_attr!( - rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, + rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true, "#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl." ), rustc_attr!( @@ -656,6 +676,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), BuiltinAttribute { name: sym::rustc_diagnostic_item, + // FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`. + only_local: false, type_: Normal, template: template!(NameValueStr: "name"), duplicates: ErrorFollowing, @@ -676,7 +698,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "unboxed_closures are still evolving", ), rustc_attr!( - rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, + rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, @only_local: true, "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", @@ -778,6 +800,10 @@ pub fn is_builtin_attr_name(name: Symbol) -> bool { BUILTIN_ATTRIBUTE_MAP.get(&name).is_some() } +pub fn is_builtin_only_local(name: Symbol) -> bool { + BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| attr.only_local) +} + pub static BUILTIN_ATTRIBUTE_MAP: SyncLazy> = SyncLazy::new(|| { let mut map = FxHashMap::default(); diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 940c4ecdcc23a..26e0538b0eb4e 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -149,7 +149,8 @@ pub use accepted::ACCEPTED_FEATURES; pub use active::{Features, ACTIVE_FEATURES, INCOMPATIBLE_FEATURES}; pub use builtin_attrs::AttributeDuplicates; pub use builtin_attrs::{ - deprecated_attributes, find_gated_cfg, is_builtin_attr_name, AttributeGate, AttributeTemplate, - AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP, + deprecated_attributes, find_gated_cfg, is_builtin_attr_name, is_builtin_only_local, + AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute, GatedCfg, + BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP, }; pub use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES}; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 81388a0bf585d..2f006dfabec8e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -986,9 +986,13 @@ fn should_encode_generics(def_kind: DefKind) -> bool { impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_attrs(&mut self, def_id: DefId) { - let attrs = self.tcx.get_attrs(def_id); - record!(self.tables.attributes[def_id] <- attrs); - if attrs.iter().any(|attr| attr.may_have_doc_links()) { + let mut attrs = self + .tcx + .get_attrs(def_id) + .iter() + .filter(|attr| !rustc_feature::is_builtin_only_local(attr.name_or_empty())); + record!(self.tables.attributes[def_id] <- attrs.clone()); + if attrs.any(|attr| attr.may_have_doc_links()) { self.tables.may_have_doc_links.set(def_id.index, ()); } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 629a550b77596..ec268fc2343d8 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1072,6 +1072,9 @@ rustc_queries! { desc { |tcx| "checking whether `{}` is `doc(hidden)`", tcx.def_path_str(def_id) } } + /// Returns the attributes on the item at `def_id`. + /// + /// Do not use this directly, use `tcx.get_attrs` instead. query item_attrs(def_id: DefId) -> &'tcx [ast::Attribute] { desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) } separate_provide_extern diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d847068b5bfb3..722257f9c5ebe 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2187,6 +2187,10 @@ impl<'tcx> TyCtxt<'tcx> { } /// Gets the attributes of a definition. + /// + /// Note that attributes which are be relevant while + /// the current local crate are not stored in the crate metadata + /// and therefore cannot be accessed outside of that crate. pub fn get_attrs(self, did: DefId) -> Attributes<'tcx> { if let Some(did) = did.as_local() { self.hir().attrs(self.hir().local_def_id_to_hir_id(did)) From b618cdb224963cea9ddddda8ea8a7f11f1b2d9a6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 4 Apr 2022 10:45:46 +0200 Subject: [PATCH 2/8] fix comment --- compiler/rustc_middle/src/ty/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 722257f9c5ebe..4bd4f6428c600 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2188,9 +2188,9 @@ impl<'tcx> TyCtxt<'tcx> { /// Gets the attributes of a definition. /// - /// Note that attributes which are be relevant while - /// the current local crate are not stored in the crate metadata - /// and therefore cannot be accessed outside of that crate. + /// Note that attributes which are only relevant for the current + /// crate are not stored in the crate metadata and therefore cannot + /// be accessed outside of that crate. pub fn get_attrs(self, did: DefId) -> Attributes<'tcx> { if let Some(did) = did.as_local() { self.hir().attrs(self.hir().local_def_id_to_hir_id(did)) From fc128b67647533258e0bc52cc935438e6480732d Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 4 Apr 2022 17:28:42 +0200 Subject: [PATCH 3/8] add check and don't encode `#[inline]` --- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index f512594977c8d..5854d7604f3c0 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -377,7 +377,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(panic_handler, Normal, template!(Word), WarnFollowing), // RFC 2070 // Code generation: - ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing), + ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing, @only_local: true), ungated!(cold, Normal, template!(Word), WarnFollowing), ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing), ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 4bd4f6428c600..94d2a313c7cc0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2201,6 +2201,9 @@ impl<'tcx> TyCtxt<'tcx> { /// Determines whether an item is annotated with an attribute. pub fn has_attr(self, did: DefId, attr: Symbol) -> bool { + if cfg!(debug_assertions) && !did.is_local() && rustc_feature::is_builtin_only_local(attr) { + bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr); + } self.sess.contains_name(&self.get_attrs(did), attr) } From 6c8265dc56d221dce7f3535ecf8cdee6b9d2d618 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 2 May 2022 09:31:56 +0200 Subject: [PATCH 4/8] only_local: always check for misuse --- compiler/rustc_attr/src/builtin.rs | 279 +++++++++--------- compiler/rustc_codegen_llvm/src/attributes.rs | 5 +- .../src/transform/check_consts/check.rs | 10 +- .../src/transform/check_consts/mod.rs | 8 +- .../src/transform/check_consts/ops.rs | 12 +- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- .../src/persist/dirty_clean.rs | 7 +- compiler/rustc_interface/src/queries.rs | 5 +- compiler/rustc_lint/src/builtin.rs | 8 +- compiler/rustc_lint/src/types.rs | 2 +- compiler/rustc_lint/src/unused.rs | 37 ++- compiler/rustc_metadata/src/rmeta/encoder.rs | 16 +- compiler/rustc_middle/src/ty/adt.rs | 3 +- compiler/rustc_middle/src/ty/context.rs | 3 +- compiler/rustc_middle/src/ty/error.rs | 7 +- compiler/rustc_middle/src/ty/instance.rs | 5 +- compiler/rustc_middle/src/ty/mod.rs | 45 +-- compiler/rustc_middle/src/ty/util.rs | 5 +- compiler/rustc_mir_build/src/build/mod.rs | 1 - .../src/framework/engine.rs | 7 +- compiler/rustc_mir_dataflow/src/lib.rs | 26 +- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 22 +- .../rustc_monomorphize/src/polymorphize.rs | 2 +- compiler/rustc_passes/src/check_const.rs | 10 +- compiler/rustc_passes/src/layout_test.rs | 6 +- compiler/rustc_passes/src/stability.rs | 2 +- compiler/rustc_resolve/src/late/lifetimes.rs | 7 +- compiler/rustc_symbol_mangling/src/test.rs | 37 ++- .../src/traits/on_unimplemented.rs | 4 +- .../src/traits/select/mod.rs | 6 +- compiler/rustc_typeck/src/check/check.rs | 33 +-- compiler/rustc_typeck/src/check/demand.rs | 4 +- .../src/check/generator_interior.rs | 67 +++-- compiler/rustc_typeck/src/check_unused.rs | 7 +- compiler/rustc_typeck/src/collect.rs | 4 +- compiler/rustc_typeck/src/lib.rs | 17 +- 36 files changed, 341 insertions(+), 380 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 5a79cf68f113e..3d4bd222715c3 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -868,177 +868,180 @@ impl IntType { /// structure layout, `packed` to remove padding, and `transparent` to delegate representation /// concerns to the only non-ZST field. pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec { - use ReprAttr::*; + if attr.has_name(sym::repr) { parse_repr_attr(sess, attr) } else { Vec::new() } +} +pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { + assert!(attr.has_name(sym::repr), "expected `#[repr(..)]`, found: {:?}", attr); + use ReprAttr::*; let mut acc = Vec::new(); let diagnostic = &sess.parse_sess.span_diagnostic; - if attr.has_name(sym::repr) { - if let Some(items) = attr.meta_item_list() { - for item in items { - let mut recognised = false; - if item.is_word() { - let hint = match item.name_or_empty() { - sym::C => Some(ReprC), - sym::packed => Some(ReprPacked(1)), - sym::simd => Some(ReprSimd), - sym::transparent => Some(ReprTransparent), - sym::no_niche => Some(ReprNoNiche), - sym::align => { - let mut err = struct_span_err!( - diagnostic, - item.span(), - E0589, - "invalid `repr(align)` attribute: `align` needs an argument" - ); - err.span_suggestion( - item.span(), - "supply an argument here", - "align(...)".to_string(), - Applicability::HasPlaceholders, - ); - err.emit(); - recognised = true; - None - } - name => int_type_of_word(name).map(ReprInt), - }; - if let Some(h) = hint { + if let Some(items) = attr.meta_item_list() { + for item in items { + let mut recognised = false; + if item.is_word() { + let hint = match item.name_or_empty() { + sym::C => Some(ReprC), + sym::packed => Some(ReprPacked(1)), + sym::simd => Some(ReprSimd), + sym::transparent => Some(ReprTransparent), + sym::no_niche => Some(ReprNoNiche), + sym::align => { + let mut err = struct_span_err!( + diagnostic, + item.span(), + E0589, + "invalid `repr(align)` attribute: `align` needs an argument" + ); + err.span_suggestion( + item.span(), + "supply an argument here", + "align(...)".to_string(), + Applicability::HasPlaceholders, + ); + err.emit(); recognised = true; - acc.push(h); + None } - } else if let Some((name, value)) = item.name_value_literal() { - let mut literal_error = None; - if name == sym::align { - recognised = true; - match parse_alignment(&value.kind) { - Ok(literal) => acc.push(ReprAlign(literal)), - Err(message) => literal_error = Some(message), - }; - } else if name == sym::packed { - recognised = true; - match parse_alignment(&value.kind) { - Ok(literal) => acc.push(ReprPacked(literal)), - Err(message) => literal_error = Some(message), - }; - } else if matches!(name, sym::C | sym::simd | sym::transparent | sym::no_niche) - || int_type_of_word(name).is_some() - { - recognised = true; - struct_span_err!( + name => int_type_of_word(name).map(ReprInt), + }; + + if let Some(h) = hint { + recognised = true; + acc.push(h); + } + } else if let Some((name, value)) = item.name_value_literal() { + let mut literal_error = None; + if name == sym::align { + recognised = true; + match parse_alignment(&value.kind) { + Ok(literal) => acc.push(ReprAlign(literal)), + Err(message) => literal_error = Some(message), + }; + } else if name == sym::packed { + recognised = true; + match parse_alignment(&value.kind) { + Ok(literal) => acc.push(ReprPacked(literal)), + Err(message) => literal_error = Some(message), + }; + } else if matches!(name, sym::C | sym::simd | sym::transparent | sym::no_niche) + || int_type_of_word(name).is_some() + { + recognised = true; + struct_span_err!( diagnostic, item.span(), E0552, "invalid representation hint: `{}` does not take a parenthesized argument list", name.to_ident_string(), ).emit(); - } - if let Some(literal_error) = literal_error { - struct_span_err!( + } + if let Some(literal_error) = literal_error { + struct_span_err!( + diagnostic, + item.span(), + E0589, + "invalid `repr({})` attribute: {}", + name.to_ident_string(), + literal_error + ) + .emit(); + } + } else if let Some(meta_item) = item.meta_item() { + if let MetaItemKind::NameValue(ref value) = meta_item.kind { + if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) { + let name = meta_item.name_or_empty().to_ident_string(); + recognised = true; + let mut err = struct_span_err!( diagnostic, item.span(), - E0589, - "invalid `repr({})` attribute: {}", - name.to_ident_string(), - literal_error - ) - .emit(); - } - } else if let Some(meta_item) = item.meta_item() { - if let MetaItemKind::NameValue(ref value) = meta_item.kind { - if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) { - let name = meta_item.name_or_empty().to_ident_string(); - recognised = true; - let mut err = struct_span_err!( - diagnostic, - item.span(), - E0693, - "incorrect `repr({})` attribute format", - name, - ); - match value.kind { - ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { - err.span_suggestion( - item.span(), - "use parentheses instead", - format!("{}({})", name, int), - Applicability::MachineApplicable, - ); - } - ast::LitKind::Str(s, _) => { - err.span_suggestion( - item.span(), - "use parentheses instead", - format!("{}({})", name, s), - Applicability::MachineApplicable, - ); - } - _ => {} + E0693, + "incorrect `repr({})` attribute format", + name, + ); + match value.kind { + ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => { + err.span_suggestion( + item.span(), + "use parentheses instead", + format!("{}({})", name, int), + Applicability::MachineApplicable, + ); } - err.emit(); - } else { - if matches!( - meta_item.name_or_empty(), - sym::C | sym::simd | sym::transparent | sym::no_niche - ) || int_type_of_word(meta_item.name_or_empty()).is_some() - { - recognised = true; - struct_span_err!( - diagnostic, - meta_item.span, - E0552, - "invalid representation hint: `{}` does not take a value", - meta_item.name_or_empty().to_ident_string(), - ) - .emit(); + ast::LitKind::Str(s, _) => { + err.span_suggestion( + item.span(), + "use parentheses instead", + format!("{}({})", name, s), + Applicability::MachineApplicable, + ); } + _ => {} } - } else if let MetaItemKind::List(_) = meta_item.kind { - if meta_item.has_name(sym::align) { + err.emit(); + } else { + if matches!( + meta_item.name_or_empty(), + sym::C | sym::simd | sym::transparent | sym::no_niche + ) || int_type_of_word(meta_item.name_or_empty()).is_some() + { recognised = true; struct_span_err!( diagnostic, meta_item.span, - E0693, - "incorrect `repr(align)` attribute format: \ - `align` takes exactly one argument in parentheses" + E0552, + "invalid representation hint: `{}` does not take a value", + meta_item.name_or_empty().to_ident_string(), ) .emit(); - } else if meta_item.has_name(sym::packed) { - recognised = true; - struct_span_err!( - diagnostic, - meta_item.span, - E0552, - "incorrect `repr(packed)` attribute format: \ + } + } + } else if let MetaItemKind::List(_) = meta_item.kind { + if meta_item.has_name(sym::align) { + recognised = true; + struct_span_err!( + diagnostic, + meta_item.span, + E0693, + "incorrect `repr(align)` attribute format: \ + `align` takes exactly one argument in parentheses" + ) + .emit(); + } else if meta_item.has_name(sym::packed) { + recognised = true; + struct_span_err!( + diagnostic, + meta_item.span, + E0552, + "incorrect `repr(packed)` attribute format: \ `packed` takes exactly one parenthesized argument, \ or no parentheses at all" - ) - .emit(); - } else if matches!( - meta_item.name_or_empty(), - sym::C | sym::simd | sym::transparent | sym::no_niche - ) || int_type_of_word(meta_item.name_or_empty()).is_some() - { - recognised = true; - struct_span_err!( + ) + .emit(); + } else if matches!( + meta_item.name_or_empty(), + sym::C | sym::simd | sym::transparent | sym::no_niche + ) || int_type_of_word(meta_item.name_or_empty()).is_some() + { + recognised = true; + struct_span_err!( diagnostic, meta_item.span, E0552, "invalid representation hint: `{}` does not take a parenthesized argument list", meta_item.name_or_empty().to_ident_string(), ).emit(); - } } } - if !recognised { - // Not a word we recognize. This will be caught and reported by - // the `check_mod_attrs` pass, but this pass doesn't always run - // (e.g. if we only pretty-print the source), so we have to gate - // the `delay_span_bug` call as follows: - if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) { - diagnostic.delay_span_bug(item.span(), "unrecognized representation hint"); - } + } + if !recognised { + // Not a word we recognize. This will be caught and reported by + // the `check_mod_attrs` pass, but this pass doesn't always run + // (e.g. if we only pretty-print the source), so we have to gate + // the `delay_span_bug` call as follows: + if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) { + diagnostic.delay_span_bug(item.span(), "unrecognized representation hint"); } } } diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index c098ce36f022f..9394d60134f8c 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -6,6 +6,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::OptLevel; +use rustc_span::symbol::sym; use rustc_target::spec::abi::Abi; use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector}; use smallvec::SmallVec; @@ -329,9 +330,7 @@ pub fn from_fn_attrs<'ll, 'tcx>( ) { let span = cx .tcx - .get_attrs(instance.def_id()) - .iter() - .find(|a| a.has_name(rustc_span::sym::target_feature)) + .get_attr(instance.def_id(), sym::target_feature) .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span); let msg = format!( "the target features {} must all be either enabled or disabled together", diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 7e2a50444db06..8d3bbefb37186 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -312,11 +312,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { Status::Unstable(gate) if self.tcx.features().enabled(gate) => { let unstable_in_stable = self.ccx.is_const_stable_const_fn() - && !super::rustc_allow_const_fn_unstable( - self.tcx, - self.def_id().to_def_id(), - gate, - ); + && !super::rustc_allow_const_fn_unstable(self.tcx, self.def_id(), gate); if unstable_in_stable { emit_unstable_in_stable_error(self.ccx, span, gate); } @@ -713,7 +709,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { match &terminator.kind { TerminatorKind::Call { func, args, fn_span, from_hir_call, .. } => { let ConstCx { tcx, body, param_env, .. } = *self.ccx; - let caller = self.def_id().to_def_id(); + let caller = self.def_id(); let fn_ty = func.ty(body, tcx); @@ -797,7 +793,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // trait. let callee_trait = tcx.trait_of_item(callee); if callee_trait.is_some() - && tcx.has_attr(caller, sym::default_method_body_is_const) + && tcx.has_attr(caller.to_def_id(), sym::default_method_body_is_const) && callee_trait == tcx.trait_of_item(caller) // Can only call methods when it's `::f`. && tcx.types.self_param == substs.type_at(0) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs index 25ba97ee60567..23e2afae79183 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -66,8 +66,12 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> { } } -pub fn rustc_allow_const_fn_unstable(tcx: TyCtxt<'_>, def_id: DefId, feature_gate: Symbol) -> bool { - let attrs = tcx.get_attrs(def_id); +pub fn rustc_allow_const_fn_unstable( + tcx: TyCtxt<'_>, + def_id: LocalDefId, + feature_gate: Symbol, +) -> bool { + let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(def_id)); attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs).any(|name| name == feature_gate) } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index ba248a3b6cbe5..122471b208d80 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -1,5 +1,6 @@ //! Concrete error types for all operations which may be invalid in a certain const context. +use hir::def_id::LocalDefId; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -95,7 +96,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect { /// A function call where the callee is not marked as `const`. #[derive(Debug, Clone, Copy)] pub struct FnCallNonConst<'tcx> { - pub caller: DefId, + pub caller: LocalDefId, pub callee: DefId, pub substs: SubstsRef<'tcx>, pub span: Span, @@ -117,13 +118,8 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { match self_ty.kind() { Param(param_ty) => { debug!(?param_ty); - if let Some(generics) = caller - .as_local() - .map(|id| tcx.hir().local_def_id_to_hir_id(id)) - .map(|id| tcx.hir().get(id)) - .as_ref() - .and_then(|node| node.generics()) - { + let caller_hir_id = tcx.hir().local_def_id_to_hir_id(caller); + if let Some(generics) = tcx.hir().get(caller_hir_id).generics() { let constraint = with_no_trimmed_paths!(format!( "~const {}", trait_ref.print_only_trait_path() diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 5854d7604f3c0..f512594977c8d 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -377,7 +377,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(panic_handler, Normal, template!(Word), WarnFollowing), // RFC 2070 // Code generation: - ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing, @only_local: true), + ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing), ungated!(cold, Normal, template!(Word), WarnFollowing), ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing), ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk), diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index aaf24636598b9..424164d8760c4 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -183,10 +183,7 @@ pub struct DirtyCleanVisitor<'tcx> { impl<'tcx> DirtyCleanVisitor<'tcx> { /// Possibly "deserialize" the attribute into a clean/dirty assertion fn assertion_maybe(&mut self, item_id: LocalDefId, attr: &Attribute) -> Option { - if !attr.has_name(sym::rustc_clean) { - // skip: not rustc_clean/dirty - return None; - } + assert!(attr.has_name(sym::rustc_clean)); if !check_config(self.tcx, attr) { // skip: not the correct `cfg=` return None; @@ -384,7 +381,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { fn check_item(&mut self, item_id: LocalDefId) { let item_span = self.tcx.def_span(item_id.to_def_id()); let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id()); - for attr in self.tcx.get_attrs(item_id.to_def_id()).iter() { + for attr in self.tcx.get_attrs(item_id.to_def_id(), sym::rustc_clean) { let Some(assertion) = self.assertion_maybe(item_id, attr) else { continue; }; diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 22ab62ac372f2..136f0443fa0a3 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -258,10 +258,7 @@ impl<'tcx> Queries<'tcx> { /// an error. fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { let Some((def_id, _)) = tcx.entry_fn(()) else { return }; - - let attrs = &*tcx.get_attrs(def_id); - let attrs = attrs.iter().filter(|attr| attr.has_name(sym::rustc_error)); - for attr in attrs { + for attr in tcx.get_attrs(def_id, sym::rustc_error) { match attr.meta_item_list() { // Check if there is a `#[rustc_error(delay_span_bug_from_inside_query)]`. Some(list) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 524fb6556b995..3fbe40a4253a2 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -551,7 +551,7 @@ impl MissingDoc { } } - let attrs = cx.tcx.get_attrs(def_id.to_def_id()); + let attrs = cx.tcx.hir().attrs(cx.tcx.hir().local_def_id_to_hir_id(def_id)); let has_doc = attrs.iter().any(has_doc); if !has_doc { cx.struct_span_lint( @@ -2737,11 +2737,7 @@ impl ClashingExternDeclarations { // bottleneck, this does just fine. ( overridden_link_name, - tcx.get_attrs(fi.def_id.to_def_id()) - .iter() - .find(|at| at.has_name(sym::link_name)) - .unwrap() - .span, + tcx.get_attr(fi.def_id.to_def_id(), sym::link_name).unwrap().span, ) }) { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index dfce30171ff2b..62d427fcd0238 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -668,7 +668,7 @@ enum FfiResult<'tcx> { } crate fn nonnull_optimization_guaranteed<'tcx>(tcx: TyCtxt<'tcx>, def: ty::AdtDef<'tcx>) -> bool { - tcx.get_attrs(def.did()).iter().any(|a| a.has_name(sym::rustc_nonnull_optimization_guaranteed)) + tcx.has_attr(def.did(), 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 494bdaa1e2b9c..8cae95f46dc37 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -303,26 +303,25 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { descr_pre_path: &str, descr_post_path: &str, ) -> bool { - for attr in cx.tcx.get_attrs(def_id).iter() { - if attr.has_name(sym::must_use) { - cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| { - let msg = format!( - "unused {}`{}`{} that must be used", - descr_pre_path, - cx.tcx.def_path_str(def_id), - descr_post_path - ); - let mut err = lint.build(&msg); - // check for #[must_use = "..."] - if let Some(note) = attr.value_str() { - err.note(note.as_str()); - } - err.emit(); - }); - return true; - } + if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) { + cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| { + let msg = format!( + "unused {}`{}`{} that must be used", + descr_pre_path, + cx.tcx.def_path_str(def_id), + descr_post_path + ); + let mut err = lint.build(&msg); + // check for #[must_use = "..."] + if let Some(note) = attr.value_str() { + err.note(note.as_str()); + } + err.emit(); + }); + true + } else { + false } - false } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 2f006dfabec8e..1de7dae3c25cb 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -985,15 +985,17 @@ fn should_encode_generics(def_kind: DefKind) -> bool { } impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - fn encode_attrs(&mut self, def_id: DefId) { + fn encode_attrs(&mut self, def_id: LocalDefId) { let mut attrs = self .tcx - .get_attrs(def_id) + .hir() + .attrs(self.tcx.hir().local_def_id_to_hir_id(def_id)) .iter() .filter(|attr| !rustc_feature::is_builtin_only_local(attr.name_or_empty())); - record!(self.tables.attributes[def_id] <- attrs.clone()); + + record!(self.tables.attributes[def_id.to_def_id()] <- attrs.clone()); if attrs.any(|attr| attr.may_have_doc_links()) { - self.tables.may_have_doc_links.set(def_id.index, ()); + self.tables.may_have_doc_links.set(def_id.local_def_index, ()); } } @@ -1009,7 +1011,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let Some(def_kind) = def_kind else { continue }; self.tables.opt_def_kind.set(def_id.index, def_kind); record!(self.tables.def_span[def_id] <- tcx.def_span(def_id)); - self.encode_attrs(def_id); + self.encode_attrs(local_id); record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id)); if def_kind.has_codegen_attrs() { record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id)); @@ -1674,7 +1676,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.tables.opt_def_kind.set(LOCAL_CRATE.as_def_id().index, DefKind::Mod); record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id())); - self.encode_attrs(LOCAL_CRATE.as_def_id()); + self.encode_attrs(LOCAL_CRATE.as_def_id().expect_local()); record!(self.tables.visibility[LOCAL_CRATE.as_def_id()] <- tcx.visibility(LOCAL_CRATE.as_def_id())); if let Some(stability) = stability { record!(self.tables.lookup_stability[LOCAL_CRATE.as_def_id()] <- stability); @@ -1715,7 +1717,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def_id = id.to_def_id(); self.tables.opt_def_kind.set(def_id.index, DefKind::Macro(macro_kind)); record!(self.tables.kind[def_id] <- EntryKind::ProcMacro(macro_kind)); - self.encode_attrs(def_id); + self.encode_attrs(id); record!(self.tables.def_keys[def_id] <- def_key); record!(self.tables.def_ident_span[def_id] <- span); record!(self.tables.def_span[def_id] <- span); diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 2e4c16e39eb96..bf7cb610a9097 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -230,8 +230,7 @@ impl AdtDefData { flags |= AdtFlags::HAS_CTOR; } - let attrs = tcx.get_attrs(did); - if tcx.sess.contains_name(&attrs, sym::fundamental) { + if tcx.has_attr(did, sym::fundamental) { flags |= AdtFlags::IS_FUNDAMENTAL; } if Some(did) == tcx.lang_items().phantom_data() { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 9d3d509eb216b..36f1045efef01 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1148,9 +1148,8 @@ impl<'tcx> TyCtxt<'tcx> { /// `rustc_layout_scalar_valid_range` attribute. // FIXME(eddyb) this is an awkward spot for this method, maybe move it? pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound, Bound) { - let attrs = self.get_attrs(def_id); let get = |name| { - let Some(attr) = attrs.iter().find(|a| a.has_name(name)) else { + let Some(attr) = self.get_attr(def_id, name) else { return Bound::Unbounded; }; debug!("layout_scalar_valid_range: attr={:?}", attr); diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index da0934b67c5df..a0fe632f11a07 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -568,11 +568,8 @@ impl Trait for X { } } TargetFeatureCast(def_id) => { - let attrs = self.get_attrs(*def_id); - let target_spans = attrs - .iter() - .filter(|attr| attr.has_name(sym::target_feature)) - .map(|attr| attr.span); + let target_spans = + self.get_attrs(*def_id, sym::target_feature).map(|attr| attr.span); diag.note( "functions with `#[target_feature]` can only be coerced to `unsafe` function pointers" ); diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 7cf7f8973475d..2180078133301 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -8,6 +8,7 @@ use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::lang_items::LangItem; use rustc_macros::HashStable; use rustc_middle::ty::normalize_erasing_regions::NormalizationError; +use rustc_span::Symbol; use std::fmt; @@ -185,8 +186,8 @@ impl<'tcx> InstanceDef<'tcx> { } #[inline] - pub fn attrs(&self, tcx: TyCtxt<'tcx>) -> ty::Attributes<'tcx> { - tcx.get_attrs(self.def_id()) + pub fn get_attrs(&self, tcx: TyCtxt<'tcx>, attr: Symbol) -> ty::Attributes<'tcx> { + tcx.get_attrs(self.def_id(), attr) } /// Returns `true` if the LLVM version of this instance is unconditionally diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 94d2a313c7cc0..49b2f3480b719 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -14,12 +14,6 @@ pub use self::AssocItemContainer::*; pub use self::BorrowKind::*; pub use self::IntVarValue::*; pub use self::Variance::*; -pub use adt::*; -pub use assoc::*; -pub use generics::*; -use rustc_data_structures::fingerprint::Fingerprint; -pub use vtable::*; - use crate::metadata::ModChild; use crate::middle::privacy::AccessLevels; use crate::mir::{Body, GeneratorLayout}; @@ -28,8 +22,12 @@ use crate::ty; use crate::ty::fast_reject::SimplifiedType; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::util::Discr; +pub use adt::*; +pub use assoc::*; +pub use generics::*; use rustc_ast as ast; use rustc_attr as attr; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::intern::{Interned, WithStableHash}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -44,6 +42,7 @@ use rustc_session::cstore::CrateStoreDyn; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::abi::Align; +pub use vtable::*; use std::fmt::Debug; use std::hash::Hash; @@ -1818,8 +1817,8 @@ impl ReprOptions { field_shuffle_seed ^= user_seed; } - for attr in tcx.get_attrs(did).iter() { - for r in attr::find_repr_attrs(&tcx.sess, attr) { + for attr in tcx.get_attrs(did, sym::repr) { + for r in attr::parse_repr_attr(&tcx.sess, attr) { flags.insert(match r { attr::ReprC => ReprFlags::IS_C, attr::ReprPacked(pack) => { @@ -1941,8 +1940,7 @@ impl<'tcx> FieldDef { } } -pub type Attributes<'tcx> = &'tcx [ast::Attribute]; - +pub type Attributes<'tcx> = impl Iterator; #[derive(Debug, PartialEq, Eq)] pub enum ImplOverlapKind { /// These impls are always allowed to overlap. @@ -2186,12 +2184,8 @@ impl<'tcx> TyCtxt<'tcx> { } } - /// Gets the attributes of a definition. - /// - /// Note that attributes which are only relevant for the current - /// crate are not stored in the crate metadata and therefore cannot - /// be accessed outside of that crate. - pub fn get_attrs(self, did: DefId) -> Attributes<'tcx> { + // TODO: Remove this function. + pub fn get_attrs_unchecked(self, did: DefId) -> &'tcx [ast::Attribute] { if let Some(did) = did.as_local() { self.hir().attrs(self.hir().local_def_id_to_hir_id(did)) } else { @@ -2199,12 +2193,29 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Gets all attributes with the given name. + pub fn get_attrs(self, did: DefId, attr: Symbol) -> ty::Attributes<'tcx> { + let filter_fn = move |a: &&ast::Attribute| a.has_name(attr); + if let Some(did) = did.as_local() { + self.hir().attrs(self.hir().local_def_id_to_hir_id(did)).iter().filter(filter_fn) + } else if cfg!(debug_assertions) && rustc_feature::is_builtin_only_local(attr) { + bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr); + } else { + self.item_attrs(did).iter().filter(filter_fn) + } + } + + pub fn get_attr(self, did: DefId, attr: Symbol) -> Option<&'tcx ast::Attribute> { + self.get_attrs(did, attr).next() + } + /// Determines whether an item is annotated with an attribute. pub fn has_attr(self, did: DefId, attr: Symbol) -> bool { if cfg!(debug_assertions) && !did.is_local() && rustc_feature::is_builtin_only_local(attr) { bug!("tried to access the `only_local` attribute `{}` from an extern crate", attr); + } else { + self.get_attrs(did, attr).next().is_some() } - self.sess.contains_name(&self.get_attrs(did), attr) } /// Returns `true` if this is an `auto trait`. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 1c8af13ce9ca1..b5f8726cdc5b1 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1163,9 +1163,8 @@ pub fn normalize_opaque_types<'tcx>( /// Determines whether an item is annotated with `doc(hidden)`. pub fn is_doc_hidden(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - tcx.get_attrs(def_id) - .iter() - .filter_map(|attr| if attr.has_name(sym::doc) { attr.meta_item_list() } else { None }) + tcx.get_attrs(def_id, sym::doc) + .filter_map(|attr| attr.meta_item_list()) .any(|items| items.iter().any(|item| item.has_name(sym::hidden))) } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index ce57e5fe846eb..c63c511e09cb4 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -679,7 +679,6 @@ where } else { None }; - debug!("fn_id {:?} has attrs {:?}", fn_def, tcx.get_attrs(fn_def.did.to_def_id())); let mut body = builder.finish(); body.spread_arg = spread_arg; diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index 88ed0128a1fd3..50efb4c1dc42a 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -333,14 +333,11 @@ struct RustcMirAttrs { impl RustcMirAttrs { fn parse(tcx: TyCtxt<'_>, def_id: DefId) -> Result { - let attrs = tcx.get_attrs(def_id); - let mut result = Ok(()); let mut ret = RustcMirAttrs::default(); - let rustc_mir_attrs = attrs - .iter() - .filter(|attr| attr.has_name(sym::rustc_mir)) + let rustc_mir_attrs = tcx + .get_attrs(def_id, 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_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index d0837bcf754e4..c1124a533bf2b 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -14,9 +14,9 @@ extern crate tracing; #[macro_use] extern crate rustc_middle; -use rustc_ast::{self as ast, MetaItem}; -use rustc_middle::ty; -use rustc_session::Session; +use rustc_ast::MetaItem; +use rustc_hir::def_id::DefId; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; pub use self::drop_flag_effects::{ @@ -49,19 +49,13 @@ pub struct MoveDataParamEnv<'tcx> { pub param_env: ty::ParamEnv<'tcx>, } -pub fn has_rustc_mir_with( - _sess: &Session, - attrs: &[ast::Attribute], - name: Symbol, -) -> Option { - for attr in attrs { - 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() { - Some(mi) if mi.has_name(name) => return Some(mi.clone()), - _ => continue, - } +pub fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option { + for attr in tcx.get_attrs(def_id, sym::rustc_mir) { + let items = attr.meta_item_list(); + for item in items.iter().flat_map(|l| l.iter()) { + match item.meta_item() { + Some(mi) if mi.has_name(name) => return Some(mi.clone()), + _ => continue, } } } diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 51ab5b43bff0a..cc9ee1016c6db 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -1,4 +1,3 @@ -use rustc_ast::ast; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_target::spec::abi::Abi; @@ -31,43 +30,41 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { debug!("running rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); } - let attributes = tcx.get_attrs(def_id); let param_env = tcx.param_env(def_id); let move_data = MoveData::gather_moves(body, tcx, param_env).unwrap(); let mdpe = MoveDataParamEnv { move_data, param_env }; - let sess = &tcx.sess; - if has_rustc_mir_with(sess, &attributes, sym::rustc_peek_maybe_init).is_some() { + if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() { let flow_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe) .into_engine(tcx, body) .iterate_to_fixpoint(); - sanity_check_via_rustc_peek(tcx, body, &attributes, &flow_inits); + sanity_check_via_rustc_peek(tcx, body, &flow_inits); } - if has_rustc_mir_with(sess, &attributes, sym::rustc_peek_maybe_uninit).is_some() { + if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() { let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &mdpe) .into_engine(tcx, body) .iterate_to_fixpoint(); - sanity_check_via_rustc_peek(tcx, body, &attributes, &flow_uninits); + sanity_check_via_rustc_peek(tcx, body, &flow_uninits); } - if has_rustc_mir_with(sess, &attributes, sym::rustc_peek_definite_init).is_some() { + if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() { let flow_def_inits = DefinitelyInitializedPlaces::new(tcx, body, &mdpe) .into_engine(tcx, body) .iterate_to_fixpoint(); - sanity_check_via_rustc_peek(tcx, body, &attributes, &flow_def_inits); + sanity_check_via_rustc_peek(tcx, body, &flow_def_inits); } - if has_rustc_mir_with(sess, &attributes, sym::rustc_peek_liveness).is_some() { + if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_liveness).is_some() { let flow_liveness = MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint(); - sanity_check_via_rustc_peek(tcx, body, &attributes, &flow_liveness); + sanity_check_via_rustc_peek(tcx, body, &flow_liveness); } - if has_rustc_mir_with(sess, &attributes, sym::stop_after_dataflow).is_some() { + if has_rustc_mir_with(tcx, def_id, sym::stop_after_dataflow).is_some() { tcx.sess.fatal("stop_after_dataflow ended compilation"); } } @@ -92,7 +89,6 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { pub fn sanity_check_via_rustc_peek<'tcx, A>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - _attributes: &[ast::Attribute], results: &Results<'tcx, A>, ) where A: RustcPeekAt<'tcx>, diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index cf13c856a71c1..3cfd935d8b0ae 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -197,7 +197,7 @@ fn emit_unused_generic_params_error<'tcx>( unused_parameters: &FiniteBitSet, ) { let base_def_id = tcx.typeck_root_def_id(def_id); - if !tcx.get_attrs(base_def_id).iter().any(|a| a.has_name(sym::rustc_polymorphize_error)) { + if !tcx.has_attr(base_def_id, sym::rustc_polymorphize_error) { return; } diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 9e352fa5cc673..15e24299075b9 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -170,7 +170,7 @@ impl<'tcx> CheckConstVisitor<'tcx> { // If `def_id` is `None`, we don't need to consider stability attributes. let def_id = match def_id { - Some(x) => x.to_def_id(), + Some(x) => x, None => return true, }; @@ -182,14 +182,16 @@ impl<'tcx> CheckConstVisitor<'tcx> { // If this crate is not using stability attributes, or this function is not claiming to be a // stable `const fn`, that is all that is required. - if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) { + if !tcx.features().staged_api + || tcx.has_attr(def_id.to_def_id(), sym::rustc_const_unstable) + { return true; } // However, we cannot allow stable `const fn`s to use unstable features without an explicit // opt-in via `rustc_allow_const_fn_unstable`. - attr::rustc_allow_const_fn_unstable(&tcx.sess, &tcx.get_attrs(def_id)) - .any(|name| name == feature_gate) + let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(def_id)); + attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs).any(|name| name == feature_gate) }; match required_gates { diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 00e8eb5eb2b38..728aaab6137ab 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -27,10 +27,8 @@ impl<'tcx> ItemLikeVisitor<'tcx> for LayoutTest<'tcx> { | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { - for attr in self.tcx.get_attrs(item.def_id.to_def_id()).iter() { - if attr.has_name(sym::rustc_layout) { - self.dump_layout_of(item.def_id, item, attr); - } + for attr in self.tcx.get_attrs(item.def_id.to_def_id(), sym::rustc_layout) { + self.dump_layout_of(item.def_id, item, attr); } } _ => {} diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 10dc587be6e48..e1bc248971ae2 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -110,7 +110,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { ) where F: FnOnce(&mut Self), { - let attrs = self.tcx.get_attrs(def_id.to_def_id()); + let attrs = self.tcx.hir().attrs(self.tcx.hir().local_def_id_to_hir_id(def_id)); debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs); let depr = attr::find_deprecation(&self.tcx.sess, attrs); diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 030c27af4447d..ae4455531ab5b 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -2002,12 +2002,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let parent_def_id = self.tcx.parent(def_id); if let Some(def_id) = parent_def_id.as_local() { // lifetimes in `derive` expansions don't count (Issue #53738) - if self - .tcx - .get_attrs(def_id.to_def_id()) - .iter() - .any(|attr| attr.has_name(sym::automatically_derived)) - { + if self.tcx.has_attr(def_id.to_def_id(), sym::automatically_derived) { continue; } diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 37d1cffa2a52b..7249ce04c155e 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -49,27 +49,26 @@ struct SymbolNamesTest<'tcx> { impl SymbolNamesTest<'_> { 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 attr.has_name(SYMBOL_NAME) { - let def_id = def_id.to_def_id(); - let instance = Instance::new( - def_id, - tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def_id)), - ); - let mangled = tcx.symbol_name(instance); - tcx.sess.span_err(attr.span, &format!("symbol-name({})", mangled)); - if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) { - tcx.sess.span_err(attr.span, &format!("demangling({})", demangling)); - tcx.sess.span_err(attr.span, &format!("demangling-alt({:#})", demangling)); - } - } 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)); + // The formatting of `tag({})` is chosen so that tests can elect + // to test the entirety of the string, if they choose, or else just + // some subset. + for attr in tcx.get_attrs(def_id.to_def_id(), SYMBOL_NAME) { + let def_id = def_id.to_def_id(); + let instance = Instance::new( + def_id, + tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def_id)), + ); + let mangled = tcx.symbol_name(instance); + tcx.sess.span_err(attr.span, &format!("symbol-name({})", mangled)); + if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) { + tcx.sess.span_err(attr.span, &format!("demangling({})", demangling)); + tcx.sess.span_err(attr.span, &format!("demangling-alt({:#})", demangling)); } + } - // (*) The formatting of `tag({})` is chosen so that tests can elect - // to test the entirety of the string, if they choose, or else just - // some subset. + for attr in tcx.get_attrs(def_id.to_def_id(), 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_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index c266eec25aa6b..7d41819819536 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -175,9 +175,7 @@ impl<'tcx> OnUnimplementedDirective { } pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result, ErrorGuaranteed> { - let attrs = tcx.get_attrs(item_def_id); - - let Some(attr) = tcx.sess.find_by_name(&attrs, sym::rustc_on_unimplemented) else { + let Some(attr) = tcx.get_attr(item_def_id, sym::rustc_on_unimplemented) else { return Ok(None); }; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6584d33032a46..3d6bcc93c978c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1156,9 +1156,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let ImplCandidate(def_id) = candidate { if let ty::ImplPolarity::Reservation = tcx.impl_polarity(def_id) { if let Some(intercrate_ambiguity_clauses) = &mut self.intercrate_ambiguity_causes { - let attrs = tcx.get_attrs(def_id); - let attr = tcx.sess.find_by_name(&attrs, sym::rustc_reservation_impl); - let value = attr.and_then(|a| a.value_str()); + let value = tcx + .get_attr(def_id, sym::rustc_reservation_impl) + .and_then(|a| a.value_str()); if let Some(value) = value { debug!( "filter_reservation_impls: \ diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 4627b58c9bcd3..35cc2da15bd69 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -1056,9 +1056,7 @@ fn check_impl_items_against_trait<'tcx>( if let Some(missing_items) = must_implement_one_of { let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span); let attr_span = tcx - .get_attrs(impl_trait_ref.def_id) - .iter() - .find(|attr| attr.has_name(sym::rustc_must_implement_one_of)) + .get_attr(impl_trait_ref.def_id, sym::rustc_must_implement_one_of) .map(|attr| attr.span); missing_items_must_implement_one_of_err(tcx, impl_span, missing_items, attr_span); @@ -1158,20 +1156,20 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) { let repr = def.repr(); if repr.packed() { - for attr in tcx.get_attrs(def.did()).iter() { - for r in attr::find_repr_attrs(&tcx.sess, attr) { + for attr in tcx.get_attrs(def.did(), sym::repr) { + for r in attr::parse_repr_attr(&tcx.sess, attr) { if let attr::ReprPacked(pack) = r - && let Some(repr_pack) = repr.pack - && pack as u64 != repr_pack.bytes() - { - struct_span_err!( - tcx.sess, - sp, - E0634, - "type has conflicting packed representation hints" - ) - .emit(); - } + && let Some(repr_pack) = repr.pack + && pack as u64 != repr_pack.bytes() + { + struct_span_err!( + tcx.sess, + sp, + E0634, + "type has conflicting packed representation hints" + ) + .emit(); + } } } if repr.align.is_some() { @@ -1321,8 +1319,7 @@ fn check_enum<'tcx>( def.destructor(tcx); // force the destructor to be evaluated if vs.is_empty() { - let attributes = tcx.get_attrs(def_id.to_def_id()); - if let Some(attr) = tcx.sess.find_by_name(&attributes, sym::repr) { + if let Some(attr) = tcx.get_attr(def_id.to_def_id(), sym::repr) { struct_span_err!( tcx.sess, attr.span, diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index bfd2c32fd7e3c..ae4cebe866bdb 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -407,8 +407,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.has_only_self_parameter(m) && self .tcx - .get_attrs(m.def_id) - .iter() // This special internal attribute is used to permit // "identity-like" conversion methods to be suggested here. // @@ -419,7 +417,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // FIXME? Other potential candidate methods: `as_ref` and // `as_mut`? - .any(|a| a.has_name(sym::rustc_conversion_suggestion)) + .has_attr(m.def_id, sym::rustc_conversion_suggestion) }); methods diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index 15edc11a4974d..be389f0e3f515 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -609,44 +609,43 @@ fn check_must_not_suspend_def( hir_id: HirId, data: SuspendCheckData<'_, '_>, ) -> bool { - for attr in tcx.get_attrs(def_id).iter() { - if attr.has_name(sym::must_not_suspend) { - tcx.struct_span_lint_hir( - rustc_session::lint::builtin::MUST_NOT_SUSPEND, - hir_id, - data.source_span, - |lint| { - let msg = format!( - "{}`{}`{} held across a suspend point, but should not be", - data.descr_pre, - tcx.def_path_str(def_id), - data.descr_post, - ); - let mut err = lint.build(&msg); + if let Some(attr) = tcx.get_attr(def_id, sym::must_not_suspend) { + tcx.struct_span_lint_hir( + rustc_session::lint::builtin::MUST_NOT_SUSPEND, + hir_id, + data.source_span, + |lint| { + let msg = format!( + "{}`{}`{} held across a suspend point, but should not be", + data.descr_pre, + tcx.def_path_str(def_id), + data.descr_post, + ); + let mut err = lint.build(&msg); - // add span pointing to the offending yield/await - err.span_label(data.yield_span, "the value is held across this suspend point"); + // add span pointing to the offending yield/await + err.span_label(data.yield_span, "the value is held across this suspend point"); - // Add optional reason note - if let Some(note) = attr.value_str() { - // FIXME(guswynn): consider formatting this better - err.span_note(data.source_span, note.as_str()); - } + // Add optional reason note + if let Some(note) = attr.value_str() { + // FIXME(guswynn): consider formatting this better + err.span_note(data.source_span, note.as_str()); + } - // Add some quick suggestions on what to do - // FIXME: can `drop` work as a suggestion here as well? - err.span_help( - data.source_span, - "consider using a block (`{ ... }`) \ - to shrink the value's scope, ending before the suspend point", - ); + // Add some quick suggestions on what to do + // FIXME: can `drop` work as a suggestion here as well? + err.span_help( + data.source_span, + "consider using a block (`{ ... }`) \ + to shrink the value's scope, ending before the suspend point", + ); - err.emit(); - }, - ); + err.emit(); + }, + ); - return true; - } + true + } else { + false } - false } diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs index 1310467aeb968..00f0d1e6f02a9 100644 --- a/compiler/rustc_typeck/src/check_unused.rs +++ b/compiler/rustc_typeck/src/check_unused.rs @@ -128,7 +128,8 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { tcx.struct_span_lint_hir(lint, id, span, |lint| { // Removal suggestion span needs to include attributes (Issue #54400) let span_with_attrs = tcx - .get_attrs(extern_crate.def_id) + .hir() + .attrs(id) .iter() .map(|attr| attr.span) .fold(span, |acc, attr_span| acc.to(attr_span)); @@ -166,13 +167,13 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { continue; } + let id = tcx.hir().local_def_id_to_hir_id(def_id); // If the extern crate has any attributes, they may have funky // semantics we can't faithfully represent using `use` (most // notably `#[macro_use]`). Ignore it. - if !tcx.get_attrs(extern_crate.def_id).is_empty() { + if !tcx.hir().attrs(id).is_empty() { continue; } - let id = tcx.hir().local_def_id_to_hir_id(def_id); tcx.struct_span_lint_hir(lint, id, extern_crate.span, |lint| { // Otherwise, we can convert it into a `use` of some kind. let base_replacement = match extern_crate.orig_name { diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 2e0e026631b51..cda817dee1e1e 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1200,9 +1200,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { ty::trait_def::TraitSpecializationKind::None }; let must_implement_one_of = tcx - .get_attrs(def_id) - .iter() - .find(|attr| attr.has_name(sym::rustc_must_implement_one_of)) + .get_attr(def_id, sym::rustc_must_implement_one_of) // Check that there are at least 2 arguments of `#[rustc_must_implement_one_of]` // and that they are all identifiers .and_then(|attr| match attr.meta_item_list() { diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index fe285820ba6df..67c6e791bfe58 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -298,17 +298,12 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { error = true; } - for attr in tcx.get_attrs(main_def_id) { - if attr.has_name(sym::track_caller) { - tcx.sess - .struct_span_err( - attr.span, - "`main` function is not allowed to be `#[track_caller]`", - ) - .span_label(main_span, "`main` function is not allowed to be `#[track_caller]`") - .emit(); - error = true; - } + for attr in tcx.get_attrs(main_def_id, sym::track_caller) { + tcx.sess + .struct_span_err(attr.span, "`main` function is not allowed to be `#[track_caller]`") + .span_label(main_span, "`main` function is not allowed to be `#[track_caller]`") + .emit(); + error = true; } if error { From bae84a484cae0e13c250fa64e12f66d04f45c5f7 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 26 Apr 2022 13:21:09 +0200 Subject: [PATCH 5/8] update rustdoc --- src/librustdoc/clean/inline.rs | 6 ++-- src/librustdoc/clean/types.rs | 31 ++++++++++++-------- src/librustdoc/clean/utils.rs | 7 ++--- src/librustdoc/html/render/print_item.rs | 2 +- src/librustdoc/passes/collect_trait_impls.rs | 4 +-- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 261eb39bf723d..9a579cb531164 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -22,7 +22,7 @@ use crate::clean::{ use crate::core::DocContext; use crate::formats::item_type::ItemType; -type Attrs<'hir> = rustc_middle::ty::Attributes<'hir>; +type Attrs<'hir> = &'hir [ast::Attribute]; /// Attempt to inline a definition into this AST. /// @@ -155,7 +155,7 @@ crate fn try_inline_glob( } crate fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> Attrs<'hir> { - cx.tcx.get_attrs(did) + cx.tcx.get_attrs_unchecked(did) } /// Record an external fully qualified name in the external_paths cache. @@ -691,7 +691,7 @@ crate fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) { let trait_ = clean::TraitWithExtraInfo { trait_, - is_notable: clean::utils::has_doc_flag(cx.tcx.get_attrs(did), sym::notable_trait), + is_notable: clean::utils::has_doc_flag(cx.tcx, did, sym::notable_trait), }; cx.external_traits.borrow_mut().insert(did, trait_); cx.active_extern_traits.remove(&did); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 2b65b8f910c70..456d860f12559 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -211,8 +211,8 @@ impl ExternalCrate { // Failing that, see if there's an attribute specifying where to find this // external crate let did = self.crate_num.as_def_id(); - tcx.get_attrs(did) - .lists(sym::doc) + tcx.get_attrs(did, sym::doc) + .flat_map(|attr| attr.meta_item_list().unwrap_or_default()) .filter(|a| a.has_name(sym::html_root_url)) .filter_map(|a| a.value_str()) .map(to_remote) @@ -226,11 +226,13 @@ impl ExternalCrate { let as_keyword = |res: Res| { if let Res::Def(DefKind::Mod, def_id) = res { - let attrs = tcx.get_attrs(def_id); let mut keyword = None; - for attr in attrs.lists(sym::doc) { - if attr.has_name(sym::keyword) { - if let Some(v) = attr.value_str() { + let meta_items = tcx + .get_attrs(def_id, sym::doc) + .flat_map(|attr| attr.meta_item_list().unwrap_or_default()); + for meta in meta_items { + if meta.has_name(sym::keyword) { + if let Some(v) = meta.value_str() { keyword = Some(v); break; } @@ -288,11 +290,13 @@ impl ExternalCrate { // rendering by delegating everything to a hash map. let as_primitive = |res: Res| { if let Res::Def(DefKind::Mod, def_id) = res { - let attrs = tcx.get_attrs(def_id); let mut prim = None; - for attr in attrs.lists(sym::doc) { - if let Some(v) = attr.value_str() { - if attr.has_name(sym::primitive) { + let meta_items = tcx + .get_attrs(def_id, sym::doc) + .flat_map(|attr| attr.meta_item_list().unwrap_or_default()); + for meta in meta_items { + if let Some(v) = meta.value_str() { + if meta.has_name(sym::primitive) { prim = PrimitiveType::from_symbol(v); if prim.is_some() { break; @@ -413,7 +417,10 @@ impl Item { } crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool { - self.item_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false) + self.item_id + .as_def_id() + .map(|did| tcx.get_attrs_unchecked(did).inner_docs()) + .unwrap_or(false) } crate fn span(&self, tcx: TyCtxt<'_>) -> Span { @@ -464,7 +471,7 @@ impl Item { kind: ItemKind, cx: &mut DocContext<'_>, ) -> Item { - let ast_attrs = cx.tcx.get_attrs(def_id); + let ast_attrs = cx.tcx.get_attrs_unchecked(def_id); Self::from_def_id_and_attrs_and_parts( def_id, diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 3a2f24d719c93..c67b92df6431f 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -474,10 +474,9 @@ crate fn find_nearest_parent_module(tcx: TyCtxt<'_>, def_id: DefId) -> Option, flag: Symbol) -> bool { - attrs.iter().any(|attr| { - attr.has_name(sym::doc) - && attr.meta_item_list().map_or(false, |l| rustc_attr::list_contains_name(&l, flag)) +crate fn has_doc_flag(tcx: TyCtxt<'_>, did: DefId, flag: Symbol) -> bool { + tcx.get_attrs(did, sym::doc).any(|attr| { + attr.meta_item_list().map_or(false, |l| rustc_attr::list_contains_name(&l, flag)) }) } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index fbb3d3e45845b..4951cd83af207 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -323,7 +323,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl clean::ImportItem(ref import) => { let (stab, stab_tags) = if let Some(import_def_id) = import.source.did { - let ast_attrs = cx.tcx().get_attrs(import_def_id); + let ast_attrs = cx.tcx().get_attrs_unchecked(import_def_id); let import_attrs = Box::new(clean::Attributes::from_ast(ast_attrs, None)); // Just need an item with the correct def_id and attrs diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index d245c3750ec08..3b7ca7dc3c519 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -53,9 +53,7 @@ crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate while let Some(did) = parent { attr_buf.extend( cx.tcx - .get_attrs(did) - .iter() - .filter(|attr| attr.has_name(sym::doc)) + .get_attrs(did, sym::doc) .filter(|attr| { if let Some([attr]) = attr.meta_item_list().as_deref() { attr.has_name(sym::cfg) From 5ee1b18a14a4474cd767f5f14d7c9e58278db8a4 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 26 Apr 2022 14:04:23 +0200 Subject: [PATCH 6/8] update clippy --- compiler/rustc_middle/src/ty/mod.rs | 2 +- .../clippy/clippy_lints/src/derivable_impls.rs | 6 +++--- src/tools/clippy/clippy_lints/src/derive.rs | 10 +++++----- .../clippy/clippy_lints/src/functions/must_use.rs | 8 ++++---- .../clippy_lints/src/manual_non_exhaustive.rs | 3 +-- .../clippy_lints/src/matches/match_wild_enum.rs | 3 +-- .../clippy_lints/src/new_without_default.rs | 2 +- .../clippy/clippy_lints/src/partialeq_ne_impl.rs | 4 +--- .../src/significant_drop_in_scrutinee.rs | 2 +- src/tools/clippy/clippy_utils/src/attrs.rs | 7 ++----- src/tools/clippy/clippy_utils/src/lib.rs | 15 ++------------- src/tools/clippy/clippy_utils/src/ty.rs | 12 ++++++------ 12 files changed, 28 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 49b2f3480b719..0e30998388d31 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2184,7 +2184,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - // TODO: Remove this function. + // FIXME(@lcnr): Remove this function. pub fn get_attrs_unchecked(self, did: DefId) -> &'tcx [ast::Attribute] { if let Some(did) = did.as_local() { self.hir().attrs(self.hir().local_def_id_to_hir_id(did)) diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs index 14098340745b1..34a5f8444dea0 100644 --- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs +++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::{is_automatically_derived, is_default_equivalent, peel_blocks}; +use clippy_utils::{is_default_equivalent, peel_blocks}; use rustc_hir::{ def::{DefKind, Res}, Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind, @@ -71,8 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls { self_ty, .. }) = item.kind; - if let attrs = cx.tcx.hir().attrs(item.hir_id()); - if !is_automatically_derived(attrs); + if !cx.tcx.has_attr(item.def_id.to_def_id(), sym::automatically_derived); if !item.span.from_expansion(); if let Some(def_id) = trait_ref.trait_def_id(); if cx.tcx.is_diagnostic_item(sym::Default, def_id); @@ -81,6 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls { if let ImplItemKind::Fn(_, b) = &impl_item.kind; if let Body { value: func_expr, .. } = cx.tcx.hir().body(*b); if let Some(adt_def) = cx.tcx.type_of(item.def_id).ty_adt_def(); + if let attrs = cx.tcx.hir().attrs(item.hir_id()); if !attrs.iter().any(|attr| attr.doc_str().is_some()); if let child_attrs = cx.tcx.hir().attrs(impl_item_hir); if !child_attrs.iter().any(|attr| attr.doc_str().is_some()); diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 557e101494e3a..545bc7d210332 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_then}; use clippy_utils::paths; use clippy_utils::ty::{implements_trait, is_copy}; -use clippy_utils::{is_automatically_derived, is_lint_allowed, match_def_path}; +use clippy_utils::{is_lint_allowed, match_def_path}; use if_chain::if_chain; use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor}; use rustc_hir::{ @@ -171,8 +171,8 @@ impl<'tcx> LateLintPass<'tcx> for Derive { }) = item.kind { let ty = cx.tcx.type_of(item.def_id); - let attrs = cx.tcx.hir().attrs(item.hir_id()); - let is_automatically_derived = is_automatically_derived(attrs); + let is_automatically_derived = + cx.tcx.has_attr(item.def_id.to_def_id(), sym::automatically_derived); check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived); @@ -201,7 +201,7 @@ fn check_hash_peq<'tcx>( then { // Look for the PartialEq implementations for `ty` cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| { - let peq_is_automatically_derived = is_automatically_derived(cx.tcx.get_attrs(impl_id)); + let peq_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived); if peq_is_automatically_derived == hash_is_automatically_derived { return; @@ -255,7 +255,7 @@ fn check_ord_partial_ord<'tcx>( then { // Look for the PartialOrd implementations for `ty` cx.tcx.for_each_relevant_impl(partial_ord_trait_def_id, ty, |impl_id| { - let partial_ord_is_automatically_derived = is_automatically_derived(cx.tcx.get_attrs(impl_id)); + let partial_ord_is_automatically_derived = cx.tcx.has_attr(impl_id, sym::automatically_derived); if partial_ord_is_automatically_derived == ord_is_automatically_derived { return; diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 38e943d2eb872..6672a6cb0b58f 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -13,13 +13,13 @@ use clippy_utils::attrs::is_proc_macro; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; use clippy_utils::source::snippet_opt; use clippy_utils::ty::is_must_use_ty; -use clippy_utils::{match_def_path, must_use_attr, return_ty, trait_ref_of_method}; +use clippy_utils::{match_def_path, return_ty, trait_ref_of_method}; use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT}; pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { let attrs = cx.tcx.hir().attrs(item.hir_id()); - let attr = must_use_attr(attrs); + let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use); if let hir::ItemKind::Fn(ref sig, _generics, ref body_id) = item.kind { let is_public = cx.access_levels.is_exported(item.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); @@ -44,7 +44,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp let is_public = cx.access_levels.is_exported(item.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir().attrs(item.hir_id()); - let attr = must_use_attr(attrs); + let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use); if let Some(attr) = attr { check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.def_id).is_none() { @@ -67,7 +67,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir().attrs(item.hir_id()); - let attr = must_use_attr(attrs); + let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use); if let Some(attr) = attr { check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr); } else if let hir::TraitFn::Provided(eid) = *eid { diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index b8d620d817130..09164690700ef 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -1,4 +1,3 @@ -use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_opt; use clippy_utils::{is_lint_allowed, meets_msrv, msrvs}; @@ -161,7 +160,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum { let id = cx.tcx.hir().local_def_id(v.id); (matches!(v.data, hir::VariantData::Unit(_)) && v.ident.as_str().starts_with('_') - && is_doc_hidden(cx.tcx.get_attrs(id.to_def_id()))) + && cx.tcx.is_doc_hidden(id.to_def_id())) .then(|| (id, v.span)) }); if let Some((id, span)) = iter.next() diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs index 93bf0dc62e076..fc45ccee18528 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs @@ -193,6 +193,5 @@ impl<'a> CommonPrefixSearcher<'a> { } fn is_hidden(cx: &LateContext<'_>, variant_def: &VariantDef) -> bool { - let attrs = cx.tcx.get_attrs(variant_def.def_id); - clippy_utils::attrs::is_doc_hidden(attrs) || clippy_utils::attrs::is_unstable(attrs) + cx.tcx.is_doc_hidden(variant_def.def_id) || cx.tcx.has_attr(variant_def.def_id, sym::unstable) } diff --git a/src/tools/clippy/clippy_lints/src/new_without_default.rs b/src/tools/clippy/clippy_lints/src/new_without_default.rs index 2f733f221d572..2bdccb425071b 100644 --- a/src/tools/clippy/clippy_lints/src/new_without_default.rs +++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs @@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { // can't be implemented for unsafe new return; } - if clippy_utils::is_doc_hidden(cx.tcx.hir().attrs(id)) { + if cx.tcx.is_doc_hidden(impl_item.def_id) { // shouldn't be implemented when it is hidden in docs return; } diff --git a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs index 1469cb434c00c..09ac514d014eb 100644 --- a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs +++ b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs @@ -1,5 +1,4 @@ use clippy_utils::diagnostics::span_lint_hir; -use clippy_utils::is_automatically_derived; use if_chain::if_chain; use rustc_hir::{Impl, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -37,8 +36,7 @@ impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if_chain! { if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind; - let attrs = cx.tcx.hir().attrs(item.hir_id()); - if !is_automatically_derived(attrs); + if !cx.tcx.has_attr(item.def_id.to_def_id(), sym::automatically_derived); if let Some(eq_trait) = cx.tcx.lang_items().eq_trait(); if trait_ref.path.res.def_id() == eq_trait; then { diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/significant_drop_in_scrutinee.rs index 94ae0c8f5a659..f300acf0fb2ba 100644 --- a/src/tools/clippy/clippy_lints/src/significant_drop_in_scrutinee.rs +++ b/src/tools/clippy/clippy_lints/src/significant_drop_in_scrutinee.rs @@ -290,7 +290,7 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> { fn has_sig_drop_attr(&mut self, cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { if let Some(adt) = ty.ty_adt_def() { - if get_attr(cx.sess(), cx.tcx.get_attrs(adt.did()), "has_significant_drop").count() > 0 { + if get_attr(cx.sess(), cx.tcx.get_attrs_unchecked(adt.did()), "has_significant_drop").count() > 0 { return true; } } diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs index 7f448175e3267..904b1a05ccc30 100644 --- a/src/tools/clippy/clippy_utils/src/attrs.rs +++ b/src/tools/clippy/clippy_utils/src/attrs.rs @@ -1,6 +1,7 @@ -use rustc_ast::{ast, attr}; +use rustc_ast::ast; use rustc_errors::Applicability; use rustc_session::Session; +use rustc_ast::attr; use rustc_span::sym; use std::str::FromStr; @@ -158,7 +159,3 @@ pub fn is_doc_hidden(attrs: &[ast::Attribute]) -> bool { .any(|l| attr::list_contains_name(&l, sym::hidden)) } -/// Return true if the attributes contain `#[unstable]` -pub fn is_unstable(attrs: &[ast::Attribute]) -> bool { - attrs.iter().any(|attr| attr.has_name(sym::unstable)) -} diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 7d46952d9718b..98a073d122e31 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -66,7 +66,7 @@ use std::lazy::SyncOnceCell; use std::sync::{Mutex, MutexGuard}; use if_chain::if_chain; -use rustc_ast::ast::{self, Attribute, LitKind}; +use rustc_ast::ast::{self, LitKind}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unhash::UnhashMap; use rustc_hir as hir; @@ -1472,12 +1472,6 @@ pub fn recurse_or_patterns<'tcx, F: FnMut(&'tcx Pat<'tcx>)>(pat: &'tcx Pat<'tcx> } } -/// Checks for the `#[automatically_derived]` attribute all `#[derive]`d -/// implementations have. -pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool { - has_attr(attrs, sym::automatically_derived) -} - pub fn is_self(slf: &Param<'_>) -> bool { if let PatKind::Binding(.., name, _) = slf.pat.kind { name.name == kw::SelfLower @@ -1724,11 +1718,6 @@ pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'t None } -// Finds the `#[must_use]` attribute, if any -pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> { - attrs.iter().find(|a| a.has_name(sym::must_use)) -} - // check if expr is calling method or function with #[must_use] attribute pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let did = match expr.kind { @@ -1745,7 +1734,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { _ => None, }; - did.map_or(false, |did| must_use_attr(cx.tcx.get_attrs(did)).is_some()) + did.map_or(false, |did| cx.tcx.has_attr(did, sym::must_use)) } /// Checks if an expression represents the identity function diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 901e3e5390c5d..7f14a306d0e52 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -22,7 +22,7 @@ use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::query::normalize::AtExt; use std::iter; -use crate::{match_def_path, must_use_attr, path_res, paths}; +use crate::{match_def_path, path_res, paths}; // Checks if the given type implements copy. pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { @@ -178,18 +178,18 @@ pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { // Returns whether the type has #[must_use] attribute pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { - ty::Adt(adt, _) => must_use_attr(cx.tcx.get_attrs(adt.did())).is_some(), - ty::Foreign(ref did) => must_use_attr(cx.tcx.get_attrs(*did)).is_some(), + ty::Adt(adt, _) => cx.tcx.has_attr(adt.did(), sym::must_use), + ty::Foreign(did) => cx.tcx.has_attr(*did, sym::must_use), ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => { // for the Array case we don't need to care for the len == 0 case // because we don't want to lint functions returning empty arrays is_must_use_ty(cx, *ty) }, ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), - ty::Opaque(ref def_id, _) => { + ty::Opaque(def_id, _) => { for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { if let ty::PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder() { - if must_use_attr(cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() { + if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { return true; } } @@ -199,7 +199,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { ty::Dynamic(binder, _) => { for predicate in binder.iter() { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { - if must_use_attr(cx.tcx.get_attrs(trait_ref.def_id)).is_some() { + if cx.tcx.has_attr(trait_ref.def_id, sym::must_use) { return true; } } From 7cf9f1ab91736e27e812849a5bac0feb9fae38a9 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 2 May 2022 09:48:17 +0200 Subject: [PATCH 7/8] change some attrs to `only_local` --- compiler/rustc_feature/src/builtin_attrs.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index f512594977c8d..097493e8985fb 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -343,8 +343,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(repr, Normal, template!(List: "C"), DuplicatesOk), ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), - ungated!(no_mangle, Normal, template!(Word), WarnFollowing), - ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing), + ungated!(no_mangle, Normal, template!(Word), WarnFollowing, @only_local: true), + ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, @only_local: true), // Limits: ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing), @@ -377,8 +377,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(panic_handler, Normal, template!(Word), WarnFollowing), // RFC 2070 // Code generation: - ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing), - ungated!(cold, Normal, template!(Word), WarnFollowing), + ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing, @only_local: true), + ungated!(cold, Normal, template!(Word), WarnFollowing, @only_local: true), ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing), ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk), ungated!(track_caller, Normal, template!(Word), WarnFollowing), @@ -404,7 +404,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Linking: - gated!(naked, Normal, template!(Word), WarnFollowing, naked_functions, experimental!(naked)), + gated!(naked, Normal, template!(Word), WarnFollowing, @only_local: true, naked_functions, experimental!(naked)), gated!( link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, raw_dylib, experimental!(link_ordinal) @@ -566,11 +566,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== gated!( - linkage, Normal, template!(NameValueStr: "external|internal|..."), ErrorPreceding, + linkage, Normal, template!(NameValueStr: "external|internal|..."), ErrorPreceding, @only_local: true, "the `linkage` attribute is experimental and not portable across platforms", ), rustc_attr!( - rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE + rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing, @only_local: true, INTERNAL_UNSTABLE ), // ========================================================================== From ebf95836e3cfc8c442cc71239324d947aafa3eac Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 10 May 2022 12:02:20 +0200 Subject: [PATCH 8/8] fix typo --- compiler/rustc_passes/src/diagnostic_items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 9cbb7917e9a32..ed694eb0e327a 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -83,7 +83,7 @@ fn collect_item(tcx: TyCtxt<'_>, items: &mut DiagnosticItems, name: Symbol, item } } -/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.p +/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes. fn extract(attrs: &[ast::Attribute]) -> Option { attrs.iter().find_map(|attr| { if attr.has_name(sym::rustc_diagnostic_item) { attr.value_str() } else { None }