only_local: always check for misuse
This commit is contained in:
parent
fc128b6764
commit
6c8265dc56
36 changed files with 343 additions and 382 deletions
|
@ -868,11 +868,15 @@ 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<ReprAttr> {
|
||||
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<ReprAttr> {
|
||||
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;
|
||||
|
@ -1042,7 +1046,6 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
acc
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 `<Self as TheTrait>::f`.
|
||||
&& tcx.types.self_param == substs.type_at(0)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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<Assertion> {
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
})
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -303,8 +303,7 @@ 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) {
|
||||
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",
|
||||
|
@ -319,13 +318,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||
}
|
||||
err.emit();
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `path_statements` lint detects path statements with no effect.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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<u128>, Bound<u128>) {
|
||||
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);
|
||||
|
|
|
@ -568,11 +568,8 @@ impl<T> Trait<T> 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"
|
||||
);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<Item = &'tcx ast::Attribute>;
|
||||
#[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`.
|
||||
|
|
|
@ -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)))
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -333,14 +333,11 @@ struct RustcMirAttrs {
|
|||
|
||||
impl RustcMirAttrs {
|
||||
fn parse(tcx: TyCtxt<'_>, def_id: DefId) -> Result<Self, ()> {
|
||||
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 {
|
||||
|
|
|
@ -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,13 +49,8 @@ pub struct MoveDataParamEnv<'tcx> {
|
|||
pub param_env: ty::ParamEnv<'tcx>,
|
||||
}
|
||||
|
||||
pub fn has_rustc_mir_with(
|
||||
_sess: &Session,
|
||||
attrs: &[ast::Attribute],
|
||||
name: Symbol,
|
||||
) -> Option<MetaItem> {
|
||||
for attr in attrs {
|
||||
if attr.has_name(sym::rustc_mir) {
|
||||
pub fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option<MetaItem> {
|
||||
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() {
|
||||
|
@ -64,6 +59,5 @@ pub fn has_rustc_mir_with(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -197,7 +197,7 @@ fn emit_unused_generic_params_error<'tcx>(
|
|||
unused_parameters: &FiniteBitSet<u32>,
|
||||
) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -27,12 +27,10 @@ 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,8 +49,10 @@ 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) {
|
||||
// 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,
|
||||
|
@ -62,14 +64,11 @@ impl SymbolNamesTest<'_> {
|
|||
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) {
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
// (*) 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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,9 +175,7 @@ impl<'tcx> OnUnimplementedDirective {
|
|||
}
|
||||
|
||||
pub fn of_item(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> Result<Option<Self>, 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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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: \
|
||||
|
|
|
@ -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,8 +1156,8 @@ 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()
|
||||
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -609,8 +609,7 @@ 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) {
|
||||
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,
|
||||
|
@ -645,8 +644,8 @@ fn check_must_not_suspend_def(
|
|||
},
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -298,18 +298,13 @@ 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) {
|
||||
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]`",
|
||||
)
|
||||
.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 {
|
||||
return;
|
||||
|
|
Loading…
Add table
Reference in a new issue