mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-30 05:51:58 +00:00
only_local: always check for misuse
This commit is contained in:
parent
fc128b6764
commit
6c8265dc56
@ -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<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;
|
||||
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) {
|
||||
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!(
|
||||
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();
|
||||
}
|
||||
}
|
||||
} 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!(
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,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<MetaItem> {
|
||||
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<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() {
|
||||
Some(mi) if mi.has_name(name) => return Some(mi.clone()),
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,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);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -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,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,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,
|
||||
|
@ -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,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
|
||||
}
|
||||
|
@ -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,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 {
|
||||
|
Loading…
Reference in New Issue
Block a user