summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_passes/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_passes/src')
-rw-r--r--compiler/rustc_passes/src/check_attr.rs352
-rw-r--r--compiler/rustc_passes/src/check_const.rs6
-rw-r--r--compiler/rustc_passes/src/dead.rs83
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs66
-rw-r--r--compiler/rustc_passes/src/errors.rs205
-rw-r--r--compiler/rustc_passes/src/hir_id_validator.rs39
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs7
-rw-r--r--compiler/rustc_passes/src/lang_items.rs27
-rw-r--r--compiler/rustc_passes/src/layout_test.rs2
-rw-r--r--compiler/rustc_passes/src/lib.rs4
-rw-r--r--compiler/rustc_passes/src/lib_features.rs5
-rw-r--r--compiler/rustc_passes/src/liveness.rs8
-rw-r--r--compiler/rustc_passes/src/liveness/rwu_table.rs2
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs2
-rw-r--r--compiler/rustc_passes/src/reachable.rs31
-rw-r--r--compiler/rustc_passes/src/stability.rs63
16 files changed, 592 insertions, 310 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index f9f9799d3..5ef3e13ef 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -4,13 +4,10 @@
//! conflicts between multiple such attributes attached to the same
//! item.
-use crate::errors::{
- self, AttrApplication, DebugVisualizerUnreadable, InvalidAttrAtCrateLevel, ObjectLifetimeErr,
- OnlyHasEffectOn, TransparentIncompatible, UnrecognizedReprHint,
-};
+use crate::{errors, fluent_generated as fluent};
use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem};
use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{fluent, Applicability, MultiSpan};
+use rustc_errors::{Applicability, IntoDiagnosticArg, MultiSpan};
use rustc_expand::base::resolve_path;
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
use rustc_hir as hir;
@@ -19,18 +16,21 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{
self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
};
-use rustc_hir::{MethodKind, Target};
+use rustc_hir::{MethodKind, Target, Unsafety};
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
+use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
+use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{ParamEnv, TyCtxt};
use rustc_session::lint::builtin::{
- CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, UNUSED_ATTRIBUTES,
+ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
+ UNUSED_ATTRIBUTES,
};
use rustc_session::parse::feature_err;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
+use std::cell::Cell;
use std::collections::hash_map::Entry;
pub(crate) fn target_from_impl_item<'tcx>(
@@ -62,8 +62,29 @@ enum ItemLike<'tcx> {
ForeignItem,
}
+#[derive(Copy, Clone)]
+pub(crate) enum ProcMacroKind {
+ FunctionLike,
+ Derive,
+ Attribute,
+}
+
+impl IntoDiagnosticArg for ProcMacroKind {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ match self {
+ ProcMacroKind::Attribute => "attribute proc macro",
+ ProcMacroKind::Derive => "derive proc macro",
+ ProcMacroKind::FunctionLike => "function-like proc macro",
+ }
+ .into_diagnostic_arg()
+ }
+}
+
struct CheckAttrVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
+
+ // Whether or not this visitor should abort after finding errors
+ abort: Cell<bool>,
}
impl CheckAttrVisitor<'_> {
@@ -136,6 +157,7 @@ impl CheckAttrVisitor<'_> {
| sym::rustc_dirty
| sym::rustc_if_this_changed
| sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr),
+ sym::rustc_coinductive => self.check_rustc_coinductive(&attr, span, target),
sym::cmse_nonsecure_entry => {
self.check_cmse_nonsecure_entry(hir_id, attr, span, target)
}
@@ -150,6 +172,9 @@ impl CheckAttrVisitor<'_> {
sym::rustc_has_incoherent_inherent_impls => {
self.check_has_incoherent_inherent_impls(&attr, span, target)
}
+ sym::ffi_pure => self.check_ffi_pure(attr.span, attrs, target),
+ sym::ffi_const => self.check_ffi_const(attr.span, target),
+ sym::ffi_returns_twice => self.check_ffi_returns_twice(attr.span, target),
sym::rustc_const_unstable
| sym::rustc_const_stable
| sym::unstable
@@ -173,7 +198,7 @@ impl CheckAttrVisitor<'_> {
sym::path => self.check_generic_attr(hir_id, attr, target, Target::Mod),
sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target),
sym::macro_export => self.check_macro_export(hir_id, attr, target),
- sym::ignore | sym::should_panic | sym::proc_macro_derive => {
+ sym::ignore | sym::should_panic => {
self.check_generic_attr(hir_id, attr, target, Target::Fn)
}
sym::automatically_derived => {
@@ -183,6 +208,16 @@ impl CheckAttrVisitor<'_> {
self.check_generic_attr(hir_id, attr, target, Target::Mod)
}
sym::rustc_object_lifetime_default => self.check_object_lifetime_default(hir_id),
+ sym::proc_macro => {
+ self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike)
+ }
+ sym::proc_macro_attribute => {
+ self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute);
+ }
+ sym::proc_macro_derive => {
+ self.check_generic_attr(hir_id, attr, target, Target::Fn);
+ self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
+ }
_ => {}
}
@@ -362,7 +397,7 @@ impl CheckAttrVisitor<'_> {
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
- OnlyHasEffectOn {
+ errors::OnlyHasEffectOn {
attr_name: attr.name_or_empty(),
target_name: allowed_target.name().replace(' ', "_"),
},
@@ -419,7 +454,9 @@ impl CheckAttrVisitor<'_> {
/// Debugging aid for `object_lifetime_default` query.
fn check_object_lifetime_default(&self, hir_id: HirId) {
let tcx = self.tcx;
- if let Some(generics) = tcx.hir().get_generics(tcx.hir().local_def_id(hir_id)) {
+ if let Some(owner_id) = hir_id.as_owner()
+ && let Some(generics) = tcx.hir().get_generics(owner_id.def_id)
+ {
for p in generics.params {
let hir::GenericParamKind::Type { .. } = p.kind else { continue };
let default = tcx.object_lifetime_default(p.def_id);
@@ -429,7 +466,7 @@ impl CheckAttrVisitor<'_> {
ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
};
- tcx.sess.emit_err(ObjectLifetimeErr { span: p.span, repr });
+ tcx.sess.emit_err(errors::ObjectLifetimeErr { span: p.span, repr });
}
}
}
@@ -828,33 +865,39 @@ impl CheckAttrVisitor<'_> {
target: Target,
specified_inline: &mut Option<(bool, Span)>,
) -> bool {
- if target == Target::Use || target == Target::ExternCrate {
- let do_inline = meta.name_or_empty() == sym::inline;
- if let Some((prev_inline, prev_span)) = *specified_inline {
- if do_inline != prev_inline {
- let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]);
- spans.push_span_label(prev_span, fluent::passes_doc_inline_conflict_first);
- spans.push_span_label(meta.span(), fluent::passes_doc_inline_conflict_second);
- self.tcx.sess.emit_err(errors::DocKeywordConflict { spans });
- return false;
+ match target {
+ Target::Use | Target::ExternCrate => {
+ let do_inline = meta.name_or_empty() == sym::inline;
+ if let Some((prev_inline, prev_span)) = *specified_inline {
+ if do_inline != prev_inline {
+ let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]);
+ spans.push_span_label(prev_span, fluent::passes_doc_inline_conflict_first);
+ spans.push_span_label(
+ meta.span(),
+ fluent::passes_doc_inline_conflict_second,
+ );
+ self.tcx.sess.emit_err(errors::DocKeywordConflict { spans });
+ return false;
+ }
+ true
+ } else {
+ *specified_inline = Some((do_inline, meta.span()));
+ true
}
- true
- } else {
- *specified_inline = Some((do_inline, meta.span()));
- true
}
- } else {
- self.tcx.emit_spanned_lint(
- INVALID_DOC_ATTRIBUTES,
- hir_id,
- meta.span(),
- errors::DocInlineOnlyUse {
- attr_span: meta.span(),
- item_span: (attr.style == AttrStyle::Outer)
- .then(|| self.tcx.hir().span(hir_id)),
- },
- );
- false
+ _ => {
+ self.tcx.emit_spanned_lint(
+ INVALID_DOC_ATTRIBUTES,
+ hir_id,
+ meta.span(),
+ errors::DocInlineOnlyUse {
+ attr_span: meta.span(),
+ item_span: (attr.style == AttrStyle::Outer)
+ .then(|| self.tcx.hir().span(hir_id)),
+ },
+ );
+ false
+ }
}
}
@@ -893,15 +936,15 @@ impl CheckAttrVisitor<'_> {
src.insert(1, '!');
err.span_suggestion_verbose(
attr.span,
- fluent::suggestion,
+ fluent::passes_suggestion,
src,
Applicability::MaybeIncorrect,
);
} else {
- err.span_help(attr.span, fluent::help);
+ err.span_help(attr.span, fluent::passes_help);
}
}
- err.note(fluent::note);
+ err.note(fluent::passes_note);
err
},
);
@@ -1101,7 +1144,7 @@ impl CheckAttrVisitor<'_> {
errors::DocTestUnknownInclude {
path,
value: value.to_string(),
- inner: if attr.style == AttrStyle::Inner { "!" } else { "" },
+ inner: match attr.style { AttrStyle::Inner=> "!" , AttrStyle::Outer => "" },
sugg: (attr.meta().unwrap().span, applicability),
}
);
@@ -1171,6 +1214,38 @@ impl CheckAttrVisitor<'_> {
}
}
+ fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute], target: Target) -> bool {
+ if target != Target::ForeignFn {
+ self.tcx.sess.emit_err(errors::FfiPureInvalidTarget { attr_span });
+ return false;
+ }
+ if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
+ // `#[ffi_const]` functions cannot be `#[ffi_pure]`
+ self.tcx.sess.emit_err(errors::BothFfiConstAndPure { attr_span });
+ false
+ } else {
+ true
+ }
+ }
+
+ fn check_ffi_const(&self, attr_span: Span, target: Target) -> bool {
+ if target == Target::ForeignFn {
+ true
+ } else {
+ self.tcx.sess.emit_err(errors::FfiConstInvalidTarget { attr_span });
+ false
+ }
+ }
+
+ fn check_ffi_returns_twice(&self, attr_span: Span, target: Target) -> bool {
+ if target == Target::ForeignFn {
+ true
+ } else {
+ self.tcx.sess.emit_err(errors::FfiReturnsTwiceInvalidTarget { attr_span });
+ false
+ }
+ }
+
/// Warns against some misuses of `#[must_use]`
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool {
if !matches!(
@@ -1535,6 +1610,20 @@ impl CheckAttrVisitor<'_> {
}
}
+ /// Checks if the `#[rustc_coinductive]` attribute is applied to a trait.
+ fn check_rustc_coinductive(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+ match target {
+ Target::Trait => true,
+ _ => {
+ self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToTrait {
+ attr_span: attr.span,
+ defn_span: span,
+ });
+ false
+ }
+ }
+ }
+
/// Checks if `#[link_section]` is applied to a function or static.
fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
match target {
@@ -1638,7 +1727,7 @@ impl CheckAttrVisitor<'_> {
match target {
Target::Struct | Target::Union | Target::Enum => continue,
_ => {
- self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
+ self.tcx.sess.emit_err(errors::AttrApplication::StructEnumUnion {
hint_span: hint.span(),
span,
});
@@ -1659,16 +1748,18 @@ impl CheckAttrVisitor<'_> {
match target {
Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
_ => {
- self.tcx.sess.emit_err(AttrApplication::StructEnumFunctionUnion {
- hint_span: hint.span(),
- span,
- });
+ self.tcx.sess.emit_err(
+ errors::AttrApplication::StructEnumFunctionUnion {
+ hint_span: hint.span(),
+ span,
+ },
+ );
}
}
}
sym::packed => {
if target != Target::Struct && target != Target::Union {
- self.tcx.sess.emit_err(AttrApplication::StructUnion {
+ self.tcx.sess.emit_err(errors::AttrApplication::StructUnion {
hint_span: hint.span(),
span,
});
@@ -1679,9 +1770,10 @@ impl CheckAttrVisitor<'_> {
sym::simd => {
is_simd = true;
if target != Target::Struct {
- self.tcx
- .sess
- .emit_err(AttrApplication::Struct { hint_span: hint.span(), span });
+ self.tcx.sess.emit_err(errors::AttrApplication::Struct {
+ hint_span: hint.span(),
+ span,
+ });
} else {
continue;
}
@@ -1691,7 +1783,7 @@ impl CheckAttrVisitor<'_> {
match target {
Target::Struct | Target::Union | Target::Enum => continue,
_ => {
- self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
+ self.tcx.sess.emit_err(errors::AttrApplication::StructEnumUnion {
hint_span: hint.span(),
span,
});
@@ -1712,15 +1804,16 @@ impl CheckAttrVisitor<'_> {
| sym::usize => {
int_reprs += 1;
if target != Target::Enum {
- self.tcx
- .sess
- .emit_err(AttrApplication::Enum { hint_span: hint.span(), span });
+ self.tcx.sess.emit_err(errors::AttrApplication::Enum {
+ hint_span: hint.span(),
+ span,
+ });
} else {
continue;
}
}
_ => {
- self.tcx.sess.emit_err(UnrecognizedReprHint { span: hint.span() });
+ self.tcx.sess.emit_err(errors::UnrecognizedReprHint { span: hint.span() });
continue;
}
};
@@ -1733,9 +1826,10 @@ impl CheckAttrVisitor<'_> {
// Error on repr(transparent, <anything else>).
if is_transparent && hints.len() > 1 {
let hint_spans: Vec<_> = hint_spans.clone().collect();
- self.tcx
- .sess
- .emit_err(TransparentIncompatible { hint_spans, target: target.to_string() });
+ self.tcx.sess.emit_err(errors::TransparentIncompatible {
+ hint_spans,
+ target: target.to_string(),
+ });
}
// Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
if (int_reprs > 1)
@@ -1888,7 +1982,7 @@ impl CheckAttrVisitor<'_> {
match std::fs::File::open(&file) {
Ok(_) => true,
Err(error) => {
- self.tcx.sess.emit_err(DebugVisualizerUnreadable {
+ self.tcx.sess.emit_err(errors::DebugVisualizerUnreadable {
span: meta_item.span,
file: &file,
error,
@@ -1909,7 +2003,7 @@ impl CheckAttrVisitor<'_> {
) -> bool {
match target {
Target::Fn | Target::Method(_)
- if self.tcx.is_const_fn_raw(self.tcx.hir().local_def_id(hir_id).to_def_id()) =>
+ if self.tcx.is_const_fn_raw(hir_id.expect_owner().to_def_id()) =>
{
true
}
@@ -2009,7 +2103,33 @@ impl CheckAttrVisitor<'_> {
fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) {
if target != Target::MacroDef {
- self.tcx.emit_spanned_lint(UNUSED_ATTRIBUTES, hir_id, attr.span, errors::MacroExport);
+ self.tcx.emit_spanned_lint(
+ UNUSED_ATTRIBUTES,
+ hir_id,
+ attr.span,
+ errors::MacroExport::Normal,
+ );
+ } else if let Some(meta_item_list) = attr.meta_item_list() &&
+ !meta_item_list.is_empty() {
+ if meta_item_list.len() > 1 {
+ self.tcx.emit_spanned_lint(
+ INVALID_MACRO_EXPORT_ARGUMENTS,
+ hir_id,
+ attr.span,
+ errors::MacroExport::TooManyItems,
+ );
+ } else {
+ if meta_item_list[0].name_or_empty() != sym::local_inner_macros {
+ self.tcx.emit_spanned_lint(
+ INVALID_MACRO_EXPORT_ARGUMENTS,
+ hir_id,
+ meta_item_list[0].span(),
+ errors::MacroExport::UnknownItem {
+ name: meta_item_list[0].name_or_empty(),
+ },
+ );
+ }
+ }
}
}
@@ -2063,6 +2183,107 @@ impl CheckAttrVisitor<'_> {
errors::Unused { attr_span: attr.span, note },
);
}
+
+ /// A best effort attempt to create an error for a mismatching proc macro signature.
+ ///
+ /// If this best effort goes wrong, it will just emit a worse error later (see #102923)
+ fn check_proc_macro(&self, hir_id: HirId, target: Target, kind: ProcMacroKind) {
+ let expected_input_count = match kind {
+ ProcMacroKind::Attribute => 2,
+ ProcMacroKind::Derive | ProcMacroKind::FunctionLike => 1,
+ };
+
+ let expected_signature = match kind {
+ ProcMacroKind::Attribute => "fn(TokenStream, TokenStream) -> TokenStream",
+ ProcMacroKind::Derive | ProcMacroKind::FunctionLike => "fn(TokenStream) -> TokenStream",
+ };
+
+ let tcx = self.tcx;
+ if target == Target::Fn {
+ let Some(tokenstream) = tcx.get_diagnostic_item(sym::TokenStream) else {return};
+ let tokenstream = tcx.type_of(tokenstream).subst_identity();
+
+ let id = hir_id.expect_owner();
+ let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id).unwrap();
+
+ let sig =
+ tcx.liberate_late_bound_regions(id.to_def_id(), tcx.fn_sig(id).subst_identity());
+ let sig = tcx.normalize_erasing_regions(ParamEnv::empty(), sig);
+
+ // We don't currently require that the function signature is equal to
+ // `fn(TokenStream) -> TokenStream`, but instead monomorphizes to
+ // `fn(TokenStream) -> TokenStream` after some substitution of generic arguments.
+ //
+ // Properly checking this means pulling in additional `rustc` crates, so we don't.
+ let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer };
+
+ if sig.abi != Abi::Rust {
+ tcx.sess.emit_err(errors::ProcMacroInvalidAbi {
+ span: hir_sig.span,
+ abi: sig.abi.name(),
+ });
+ self.abort.set(true);
+ }
+
+ if sig.unsafety == Unsafety::Unsafe {
+ tcx.sess.emit_err(errors::ProcMacroUnsafe { span: hir_sig.span });
+ self.abort.set(true);
+ }
+
+ let output = sig.output();
+
+ // Typecheck the output
+ if !drcx.types_may_unify(output, tokenstream) {
+ tcx.sess.emit_err(errors::ProcMacroTypeError {
+ span: hir_sig.decl.output.span(),
+ found: output,
+ kind,
+ expected_signature,
+ });
+ self.abort.set(true);
+ }
+
+ if sig.inputs().len() < expected_input_count {
+ tcx.sess.emit_err(errors::ProcMacroMissingArguments {
+ expected_input_count,
+ span: hir_sig.span,
+ kind,
+ expected_signature,
+ });
+ self.abort.set(true);
+ }
+
+ // Check that the inputs are correct, if there are enough.
+ if sig.inputs().len() >= expected_input_count {
+ for (arg, input) in
+ sig.inputs().iter().zip(hir_sig.decl.inputs).take(expected_input_count)
+ {
+ if !drcx.types_may_unify(*arg, tokenstream) {
+ tcx.sess.emit_err(errors::ProcMacroTypeError {
+ span: input.span,
+ found: *arg,
+ kind,
+ expected_signature,
+ });
+ self.abort.set(true);
+ }
+ }
+ }
+
+ // Check that there are not too many arguments
+ let body_id = tcx.hir().body_owned_by(id.def_id);
+ let excess = tcx.hir().body(body_id).params.get(expected_input_count..);
+ if let Some(excess @ [begin @ end] | excess @ [begin, .., end]) = excess {
+ tcx.sess.emit_err(errors::ProcMacroDiffArguments {
+ span: begin.span.to(end.span),
+ count: excess.len(),
+ kind,
+ expected_signature,
+ });
+ self.abort.set(true);
+ }
+ }
+ }
}
impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
@@ -2203,7 +2424,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
if attr.style == AttrStyle::Inner {
for attr_to_check in ATTRS_TO_CHECK {
if attr.has_name(*attr_to_check) {
- tcx.sess.emit_err(InvalidAttrAtCrateLevel {
+ tcx.sess.emit_err(errors::InvalidAttrAtCrateLevel {
span: attr.span,
snippet: tcx.sess.source_map().span_to_snippet(attr.span).ok(),
name: *attr_to_check,
@@ -2225,12 +2446,15 @@ fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>)
}
fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
- let check_attr_visitor = &mut CheckAttrVisitor { tcx };
+ let check_attr_visitor = &mut CheckAttrVisitor { tcx, abort: Cell::new(false) };
tcx.hir().visit_item_likes_in_module(module_def_id, check_attr_visitor);
if module_def_id.is_top_level_module() {
check_attr_visitor.check_attributes(CRATE_HIR_ID, DUMMY_SP, Target::Mod, None);
check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
}
+ if check_attr_visitor.abort.get() {
+ tcx.sess.abort_if_errors()
+ }
}
pub(crate) fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index aa726d6cd..526b829bf 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -17,7 +17,7 @@ use rustc_middle::ty::TyCtxt;
use rustc_session::parse::feature_err;
use rustc_span::{sym, Span, Symbol};
-use crate::errors::ExprNotAllowedInContext;
+use crate::errors::{ExprNotAllowedInContext, SkippingConstChecks};
/// An expression that is not *always* legal in a const context.
#[derive(Clone, Copy)]
@@ -48,7 +48,7 @@ impl NonConstExpr {
Self::Match(TryDesugar) => &[sym::const_try],
// All other expressions are allowed.
- Self::Loop(Loop | While) | Self::Match(Normal) => &[],
+ Self::Loop(Loop | While) | Self::Match(Normal | FormatArgs) => &[],
};
Some(gates)
@@ -124,7 +124,7 @@ impl<'tcx> CheckConstVisitor<'tcx> {
// corresponding feature gate. This encourages nightly users to use feature gates when
// possible.
None if tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you => {
- tcx.sess.span_warn(span, "skipping const checks");
+ tcx.sess.emit_warning(SkippingConstChecks { span });
return;
}
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 94171b4b0..e2f858a34 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -259,7 +259,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
/// for discussion).
fn should_ignore_item(&mut self, def_id: DefId) -> bool {
if let Some(impl_of) = self.tcx.impl_of_method(def_id) {
- if !self.tcx.has_attr(impl_of, sym::automatically_derived) {
+ if !self.tcx.is_automatically_derived(impl_of) {
return false;
}
@@ -315,7 +315,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
//// This is done to handle the case where, for example, the static
//// method of a private type is used, but the type itself is never
//// called directly.
- let self_ty = self.tcx.type_of(item);
+ let self_ty = self.tcx.type_of(item).subst_identity();
match *self_ty.kind() {
ty::Adt(def, _) => self.check_def_id(def.did()),
ty::Foreign(did) => self.check_def_id(did),
@@ -395,6 +395,9 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
self.mark_as_used_if_union(*adt, fields);
}
}
+ hir::ExprKind::Closure(cls) => {
+ self.insert_def_id(cls.def_id.to_def_id());
+ }
_ => (),
}
@@ -451,47 +454,40 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
// referenced by it should be considered as used.
let in_pat = mem::replace(&mut self.in_pat, false);
- self.live_symbols.insert(self.tcx.hir().local_def_id(c.hir_id));
+ self.live_symbols.insert(c.def_id);
intravisit::walk_anon_const(self, c);
self.in_pat = in_pat;
}
}
-fn has_allow_dead_code_or_lang_attr_helper(
- tcx: TyCtxt<'_>,
- id: hir::HirId,
- lint: &'static lint::Lint,
-) -> bool {
- let attrs = tcx.hir().attrs(id);
- if tcx.sess.contains_name(attrs, sym::lang) {
- return true;
+fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+ fn has_lang_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+ tcx.has_attr(def_id.to_def_id(), sym::lang)
+ // Stable attribute for #[lang = "panic_impl"]
+ || tcx.has_attr(def_id.to_def_id(), sym::panic_handler)
}
- // Stable attribute for #[lang = "panic_impl"]
- if tcx.sess.contains_name(attrs, sym::panic_handler) {
- return true;
+ fn has_allow_dead_code(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0 == lint::Allow
}
- let def_id = tcx.hir().local_def_id(id);
- if tcx.def_kind(def_id).has_codegen_attrs() {
- let cg_attrs = tcx.codegen_fn_attrs(def_id);
+ fn has_used_like_attr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
+ tcx.def_kind(def_id).has_codegen_attrs() && {
+ let cg_attrs = tcx.codegen_fn_attrs(def_id);
- // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
- // forcefully, e.g., for placing it in a specific section.
- if cg_attrs.contains_extern_indicator()
- || cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
- || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
- {
- return true;
+ // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
+ // forcefully, e.g., for placing it in a specific section.
+ cg_attrs.contains_extern_indicator()
+ || cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
+ || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
}
}
- tcx.lint_level_at_node(lint, id).0 == lint::Allow
-}
-
-fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
- has_allow_dead_code_or_lang_attr_helper(tcx, id, lint::builtin::DEAD_CODE)
+ has_allow_dead_code(tcx, def_id)
+ || has_used_like_attr(tcx, def_id)
+ || has_lang_attr(tcx, def_id)
}
// These check_* functions seeds items that
@@ -513,7 +509,7 @@ fn check_item<'tcx>(
struct_constructors: &mut FxHashMap<LocalDefId, LocalDefId>,
id: hir::ItemId,
) {
- let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.hir_id());
+ let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id);
if allow_dead_code {
worklist.push(id.owner_id.def_id);
}
@@ -533,10 +529,8 @@ fn check_item<'tcx>(
}
}
}
- DefKind::Impl => {
- let of_trait = tcx.impl_trait_ref(id.owner_id);
-
- if of_trait.is_some() {
+ DefKind::Impl { of_trait } => {
+ if of_trait {
worklist.push(id.owner_id.def_id);
}
@@ -548,9 +542,7 @@ fn check_item<'tcx>(
// And we access the Map here to get HirId from LocalDefId
for id in local_def_ids {
- if of_trait.is_some()
- || has_allow_dead_code_or_lang_attr(tcx, tcx.hir().local_def_id_to_hir_id(id))
- {
+ if of_trait || has_allow_dead_code_or_lang_attr(tcx, id) {
worklist.push(id);
}
}
@@ -558,9 +550,9 @@ fn check_item<'tcx>(
DefKind::Struct => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Struct(ref variant_data, _) = item.kind
- && let Some(ctor_hir_id) = variant_data.ctor_hir_id()
+ && let Some(ctor_def_id) = variant_data.ctor_def_id()
{
- struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.owner_id.def_id);
+ struct_constructors.insert(ctor_def_id, item.owner_id.def_id);
}
}
DefKind::GlobalAsm => {
@@ -576,7 +568,7 @@ fn check_trait_item(tcx: TyCtxt<'_>, worklist: &mut Vec<LocalDefId>, id: hir::Tr
if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) {
let trait_item = tcx.hir().trait_item(id);
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_)))
- && has_allow_dead_code_or_lang_attr(tcx, trait_item.hir_id())
+ && has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
{
worklist.push(trait_item.owner_id.def_id);
}
@@ -585,7 +577,7 @@ fn check_trait_item(tcx: TyCtxt<'_>, worklist: &mut Vec<LocalDefId>, id: hir::Tr
fn check_foreign_item(tcx: TyCtxt<'_>, worklist: &mut Vec<LocalDefId>, id: hir::ForeignItemId) {
if matches!(tcx.def_kind(id.owner_id), DefKind::Static(_) | DefKind::Fn)
- && has_allow_dead_code_or_lang_attr(tcx, id.hir_id())
+ && has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id)
{
worklist.push(id.owner_id.def_id);
}
@@ -665,7 +657,7 @@ impl<'tcx> DeadVisitor<'tcx> {
if self.live_symbols.contains(&field.did.expect_local()) {
return ShouldWarnAboutField::No;
}
- let field_type = self.tcx.type_of(field.did);
+ let field_type = self.tcx.type_of(field.did).subst_identity();
if field_type.is_phantom_data() {
return ShouldWarnAboutField::No;
}
@@ -702,7 +694,7 @@ impl<'tcx> DeadVisitor<'tcx> {
})
.collect();
- let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
+ let descr = tcx.def_descr(first_id.to_def_id());
let num = dead_codes.len();
let multiple = num > 6;
let name_list = names.into();
@@ -714,7 +706,7 @@ impl<'tcx> DeadVisitor<'tcx> {
};
let parent_info = if let Some(parent_item) = parent_item {
- let parent_descr = tcx.def_kind(parent_item).descr(parent_item.to_def_id());
+ let parent_descr = tcx.def_descr(parent_item.to_def_id());
Some(ParentInfo {
num,
descr,
@@ -806,8 +798,7 @@ impl<'tcx> DeadVisitor<'tcx> {
if self.live_symbols.contains(&def_id) {
return;
}
- let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
- if has_allow_dead_code_or_lang_attr(self.tcx, hir_id) {
+ if has_allow_dead_code_or_lang_attr(self.tcx, def_id) {
return;
}
let Some(name) = self.tcx.opt_item_name(def_id.to_def_id()) else {
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 10ffa87ef..110eb210d 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -11,19 +11,19 @@
use rustc_ast as ast;
use rustc_hir::diagnostic_items::DiagnosticItems;
+use rustc_hir::OwnerId;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
-use rustc_span::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
-use rustc_span::symbol::{kw::Empty, sym, Symbol};
+use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_span::symbol::{sym, Symbol};
-use crate::errors::{DuplicateDiagnosticItem, DuplicateDiagnosticItemInCrate};
+use crate::errors::DuplicateDiagnosticItemInCrate;
-fn observe_item(tcx: TyCtxt<'_>, diagnostic_items: &mut DiagnosticItems, def_id: LocalDefId) {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let attrs = tcx.hir().attrs(hir_id);
+fn observe_item<'tcx>(tcx: TyCtxt<'tcx>, diagnostic_items: &mut DiagnosticItems, owner: OwnerId) {
+ let attrs = tcx.hir().attrs(owner.into());
if let Some(name) = extract(attrs) {
// insert into our table
- collect_item(tcx, diagnostic_items, name, def_id.to_def_id());
+ collect_item(tcx, diagnostic_items, name, owner.to_def_id());
}
}
@@ -31,26 +31,29 @@ fn collect_item(tcx: TyCtxt<'_>, items: &mut DiagnosticItems, name: Symbol, item
items.id_to_name.insert(item_def_id, name);
if let Some(original_def_id) = items.name_to_id.insert(name, item_def_id) {
if original_def_id != item_def_id {
- let orig_span = tcx.hir().span_if_local(original_def_id);
- let orig_crate_name = if orig_span.is_some() {
- None
- } else {
- Some(tcx.crate_name(original_def_id.krate))
- };
- match tcx.hir().span_if_local(item_def_id) {
- Some(span) => tcx.sess.emit_err(DuplicateDiagnosticItem { span, name }),
- None => tcx.sess.emit_err(DuplicateDiagnosticItemInCrate {
- span: orig_span,
- orig_crate_name: orig_crate_name.unwrap_or(Empty),
- have_orig_crate_name: orig_crate_name.map(|_| ()),
- crate_name: tcx.crate_name(item_def_id.krate),
- name,
- }),
- };
+ report_duplicate_item(tcx, name, original_def_id, item_def_id);
}
}
}
+fn report_duplicate_item(
+ tcx: TyCtxt<'_>,
+ name: Symbol,
+ original_def_id: DefId,
+ item_def_id: DefId,
+) {
+ let orig_span = tcx.hir().span_if_local(original_def_id);
+ let duplicate_span = tcx.hir().span_if_local(item_def_id);
+ tcx.sess.emit_err(DuplicateDiagnosticItemInCrate {
+ duplicate_span,
+ orig_span,
+ crate_name: tcx.crate_name(item_def_id.krate),
+ orig_crate_name: tcx.crate_name(original_def_id.krate),
+ different_crates: (item_def_id.krate != original_def_id.krate).then_some(()),
+ name,
+ });
+}
+
/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.
fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
attrs.iter().find_map(|attr| {
@@ -67,21 +70,8 @@ fn diagnostic_items(tcx: TyCtxt<'_>, cnum: CrateNum) -> DiagnosticItems {
// Collect diagnostic items in this crate.
let crate_items = tcx.hir_crate_items(());
-
- for id in crate_items.items() {
- observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
- }
-
- for id in crate_items.trait_items() {
- observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
- }
-
- for id in crate_items.impl_items() {
- observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
- }
-
- for id in crate_items.foreign_items() {
- observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
+ for id in crate_items.owners() {
+ observe_item(tcx, &mut diagnostic_items, id);
}
diagnostic_items
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 9c6519ea4..9f1c0b5a0 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -3,6 +3,7 @@ use std::{
path::{Path, PathBuf},
};
+use crate::fluent_generated as fluent;
use rustc_ast::Label;
use rustc_errors::{
error_code, Applicability, DiagnosticSymbolList, ErrorGuaranteed, IntoDiagnostic, MultiSpan,
@@ -12,6 +13,7 @@ use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::{MainDefinition, Ty};
use rustc_span::{Span, Symbol, DUMMY_SP};
+use crate::check_attr::ProcMacroKind;
use crate::lang_items::Duplicate;
#[derive(Diagnostic)]
@@ -260,7 +262,7 @@ pub struct DocKeywordConflict {
pub struct DocInlineOnlyUse {
#[label]
pub attr_span: Span,
- #[label(not_a_use_item_label)]
+ #[label(passes_not_a_use_item_label)]
pub item_span: Option<Span>,
}
@@ -299,7 +301,7 @@ pub struct DocTestUnknownAny {
#[derive(LintDiagnostic)]
#[diag(passes_doc_test_unknown_spotlight)]
#[note]
-#[note(no_op_note)]
+#[note(passes_no_op_note)]
pub struct DocTestUnknownSpotlight {
pub path: String,
#[suggestion(style = "short", applicability = "machine-applicable", code = "notable_trait")]
@@ -347,6 +349,34 @@ pub struct HasIncoherentInherentImpl {
pub span: Span,
}
+#[derive(Diagnostic)]
+#[diag(passes_both_ffi_const_and_pure, code = "E0757")]
+pub struct BothFfiConstAndPure {
+ #[primary_span]
+ pub attr_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_ffi_pure_invalid_target, code = "E0755")]
+pub struct FfiPureInvalidTarget {
+ #[primary_span]
+ pub attr_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_ffi_const_invalid_target, code = "E0756")]
+pub struct FfiConstInvalidTarget {
+ #[primary_span]
+ pub attr_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_ffi_returns_twice_invalid_target, code = "E0724")]
+pub struct FfiReturnsTwiceInvalidTarget {
+ #[primary_span]
+ pub attr_span: Span,
+}
+
#[derive(LintDiagnostic)]
#[diag(passes_must_use_async)]
pub struct MustUseAsync {
@@ -544,9 +574,9 @@ pub struct DebugVisualizerPlacement {
#[derive(Diagnostic)]
#[diag(passes_debug_visualizer_invalid)]
-#[note(note_1)]
-#[note(note_2)]
-#[note(note_3)]
+#[note(passes_note_1)]
+#[note(passes_note_2)]
+#[note(passes_note_3)]
pub struct DebugVisualizerInvalid {
#[primary_span]
pub span: Span,
@@ -611,8 +641,16 @@ pub struct MacroUse {
}
#[derive(LintDiagnostic)]
-#[diag(passes_macro_export)]
-pub struct MacroExport;
+pub enum MacroExport {
+ #[diag(passes_macro_export)]
+ Normal,
+
+ #[diag(passes_invalid_macro_export_arguments)]
+ UnknownItem { name: Symbol },
+
+ #[diag(passes_invalid_macro_export_arguments_too_many_items)]
+ TooManyItems,
+}
#[derive(LintDiagnostic)]
#[diag(passes_plugin_registrar)]
@@ -753,7 +791,7 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
self,
handler: &'_ rustc_errors::Handler,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
- let mut diag = handler.struct_err(rustc_errors::fluent::passes_invalid_attr_at_crate_level);
+ let mut diag = handler.struct_err(fluent::passes_invalid_attr_at_crate_level);
diag.set_span(self.span);
diag.set_arg("name", self.name);
// Only emit an error with a suggestion if we can create a string out
@@ -762,7 +800,7 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
let replacement = src.replace("#!", "#");
diag.span_suggestion_verbose(
self.span,
- rustc_errors::fluent::suggestion,
+ fluent::passes_suggestion,
replacement,
rustc_errors::Applicability::MachineApplicable,
);
@@ -772,22 +810,16 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
}
#[derive(Diagnostic)]
-#[diag(passes_duplicate_diagnostic_item)]
-pub struct DuplicateDiagnosticItem {
- #[primary_span]
- pub span: Span,
- pub name: Symbol,
-}
-
-#[derive(Diagnostic)]
#[diag(passes_duplicate_diagnostic_item_in_crate)]
pub struct DuplicateDiagnosticItemInCrate {
+ #[primary_span]
+ pub duplicate_span: Option<Span>,
#[note(passes_diagnostic_item_first_defined)]
- pub span: Option<Span>,
- pub orig_crate_name: Symbol,
+ pub orig_span: Option<Span>,
#[note]
- pub have_orig_crate_name: Option<()>,
+ pub different_crates: Option<()>,
pub crate_name: Symbol,
+ pub orig_crate_name: Symbol,
pub name: Symbol,
}
@@ -888,17 +920,17 @@ impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> {
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut diag = handler.struct_span_err_with_code(
self.span,
- rustc_errors::fluent::passes_break_non_loop,
+ fluent::passes_break_non_loop,
error_code!(E0571),
);
diag.set_arg("kind", self.kind);
- diag.span_label(self.span, rustc_errors::fluent::label);
+ diag.span_label(self.span, fluent::passes_label);
if let Some(head) = self.head {
- diag.span_label(head, rustc_errors::fluent::label2);
+ diag.span_label(head, fluent::passes_label2);
}
diag.span_suggestion(
self.span,
- rustc_errors::fluent::suggestion,
+ fluent::passes_suggestion,
self.suggestion,
Applicability::MaybeIncorrect,
);
@@ -916,7 +948,7 @@ impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> {
_ => {
diag.span_suggestion(
self.break_expr_span,
- rustc_errors::fluent::break_expr_suggestion,
+ fluent::passes_break_expr_suggestion,
label.ident,
Applicability::MaybeIncorrect,
);
@@ -933,7 +965,7 @@ pub struct ContinueLabeledBlock {
#[primary_span]
#[label]
pub span: Span,
- #[label(block_label)]
+ #[label(passes_block_label)]
pub block_span: Span,
}
@@ -943,7 +975,7 @@ pub struct BreakInsideClosure<'a> {
#[primary_span]
#[label]
pub span: Span,
- #[label(closure_label)]
+ #[label(passes_closure_label)]
pub closure_span: Span,
pub name: &'a str,
}
@@ -954,7 +986,7 @@ pub struct BreakInsideAsyncBlock<'a> {
#[primary_span]
#[label]
pub span: Span,
- #[label(async_block_label)]
+ #[label(passes_async_block_label)]
pub closure_span: Span,
pub name: &'a str,
}
@@ -1027,14 +1059,14 @@ impl IntoDiagnostic<'_> for NakedFunctionsAsmBlock {
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut diag = handler.struct_span_err_with_code(
self.span,
- rustc_errors::fluent::passes_naked_functions_asm_block,
+ fluent::passes_naked_functions_asm_block,
error_code!(E0787),
);
for span in self.multiple_asms.iter() {
- diag.span_label(*span, rustc_errors::fluent::label_multiple_asm);
+ diag.span_label(*span, fluent::passes_label_multiple_asm);
}
for span in self.non_asms.iter() {
- diag.span_label(*span, rustc_errors::fluent::label_non_asm);
+ diag.span_label(*span, fluent::passes_label_non_asm);
}
diag
}
@@ -1093,9 +1125,9 @@ pub struct AttrOnlyInFunctions {
pub struct MultipleRustcMain {
#[primary_span]
pub span: Span,
- #[label(first)]
+ #[label(passes_first)]
pub first: Span,
- #[label(additional)]
+ #[label(passes_additional)]
pub additional: Span,
}
@@ -1106,7 +1138,7 @@ pub struct MultipleStartFunctions {
pub span: Span,
#[label]
pub labeled: Span,
- #[label(previous)]
+ #[label(passes_previous)]
pub previous: Span,
}
@@ -1151,7 +1183,7 @@ impl<'a> IntoDiagnostic<'a> for NoMainErr {
) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> {
let mut diag = handler.struct_span_err_with_code(
DUMMY_SP,
- rustc_errors::fluent::passes_no_main_function,
+ fluent::passes_no_main_function,
error_code!(E0601),
);
diag.set_arg("crate_name", self.crate_name);
@@ -1159,16 +1191,16 @@ impl<'a> IntoDiagnostic<'a> for NoMainErr {
diag.set_arg("has_filename", self.has_filename);
let note = if !self.non_main_fns.is_empty() {
for &span in &self.non_main_fns {
- diag.span_note(span, rustc_errors::fluent::here_is_main);
+ diag.span_note(span, fluent::passes_here_is_main);
}
- diag.note(rustc_errors::fluent::one_or_more_possible_main);
- diag.help(rustc_errors::fluent::consider_moving_main);
+ diag.note(fluent::passes_one_or_more_possible_main);
+ diag.help(fluent::passes_consider_moving_main);
// There were some functions named `main` though. Try to give the user a hint.
- rustc_errors::fluent::main_must_be_defined_at_crate
+ fluent::passes_main_must_be_defined_at_crate
} else if self.has_filename {
- rustc_errors::fluent::consider_adding_main_to_file
+ fluent::passes_consider_adding_main_to_file
} else {
- rustc_errors::fluent::consider_adding_main_at_crate
+ fluent::passes_consider_adding_main_at_crate
};
if self.file_empty {
diag.note(note);
@@ -1179,11 +1211,11 @@ impl<'a> IntoDiagnostic<'a> for NoMainErr {
if let Some(main_def) = self.main_def_opt && main_def.opt_fn_def_id().is_none(){
// There is something at `crate::main`, but it is not a function definition.
- diag.span_label(main_def.span, rustc_errors::fluent::non_function_main);
+ diag.span_label(main_def.span, fluent::passes_non_function_main);
}
if self.add_teach_note {
- diag.note(rustc_errors::fluent::teach_note);
+ diag.note(fluent::passes_teach_note);
}
diag
}
@@ -1212,12 +1244,9 @@ impl IntoDiagnostic<'_> for DuplicateLangItem {
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
let mut diag = handler.struct_err_with_code(
match self.duplicate {
- Duplicate::Plain => rustc_errors::fluent::passes_duplicate_lang_item,
-
- Duplicate::Crate => rustc_errors::fluent::passes_duplicate_lang_item_crate,
- Duplicate::CrateDepends => {
- rustc_errors::fluent::passes_duplicate_lang_item_crate_depends
- }
+ Duplicate::Plain => fluent::passes_duplicate_lang_item,
+ Duplicate::Crate => fluent::passes_duplicate_lang_item_crate,
+ Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends,
},
error_code!(E0152),
);
@@ -1232,24 +1261,24 @@ impl IntoDiagnostic<'_> for DuplicateLangItem {
diag.set_span(span);
}
if let Some(span) = self.first_defined_span {
- diag.span_note(span, rustc_errors::fluent::first_defined_span);
+ diag.span_note(span, fluent::passes_first_defined_span);
} else {
if self.orig_dependency_of.is_empty() {
- diag.note(rustc_errors::fluent::first_defined_crate);
+ diag.note(fluent::passes_first_defined_crate);
} else {
- diag.note(rustc_errors::fluent::first_defined_crate_depends);
+ diag.note(fluent::passes_first_defined_crate_depends);
}
if self.orig_is_local {
- diag.note(rustc_errors::fluent::first_definition_local);
+ diag.note(fluent::passes_first_definition_local);
} else {
- diag.note(rustc_errors::fluent::first_definition_path);
+ diag.note(fluent::passes_first_definition_path);
}
if self.is_local {
- diag.note(rustc_errors::fluent::second_definition_local);
+ diag.note(fluent::passes_second_definition_local);
} else {
- diag.note(rustc_errors::fluent::second_definition_path);
+ diag.note(fluent::passes_second_definition_path);
}
}
diag
@@ -1360,7 +1389,7 @@ pub struct UselessStability {
#[primary_span]
#[label]
pub span: Span,
- #[label(item)]
+ #[label(passes_item)]
pub item_sp: Span,
}
@@ -1370,7 +1399,7 @@ pub struct InvalidStability {
#[primary_span]
#[label]
pub span: Span,
- #[label(item)]
+ #[label(passes_item)]
pub item_sp: Span,
}
@@ -1380,7 +1409,7 @@ pub struct CannotStabilizeDeprecated {
#[primary_span]
#[label]
pub span: Span,
- #[label(item)]
+ #[label(passes_item)]
pub item_sp: Span,
}
@@ -1390,7 +1419,7 @@ pub struct InvalidDeprecationVersion {
#[primary_span]
#[label]
pub span: Span,
- #[label(item)]
+ #[label(passes_item)]
pub item_sp: Span,
}
@@ -1515,3 +1544,59 @@ pub struct ChangeFieldsToBeOfUnitType {
#[suggestion_part(code = "()")]
pub spans: Vec<Span>,
}
+
+#[derive(Diagnostic)]
+#[diag(passes_proc_macro_typeerror)]
+#[note]
+pub(crate) struct ProcMacroTypeError<'tcx> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub found: Ty<'tcx>,
+ pub kind: ProcMacroKind,
+ pub expected_signature: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_proc_macro_diff_arg_count)]
+pub(crate) struct ProcMacroDiffArguments {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub count: usize,
+ pub kind: ProcMacroKind,
+ pub expected_signature: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_proc_macro_missing_args)]
+pub(crate) struct ProcMacroMissingArguments {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub expected_input_count: usize,
+ pub kind: ProcMacroKind,
+ pub expected_signature: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_proc_macro_invalid_abi)]
+pub(crate) struct ProcMacroInvalidAbi {
+ #[primary_span]
+ pub span: Span,
+ pub abi: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_proc_macro_unsafe)]
+pub(crate) struct ProcMacroUnsafe {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_skipping_const_checks)]
+pub struct SkippingConstChecks {
+ #[primary_span]
+ pub span: Span,
+}
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index d143adb2e..de0e50a65 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -74,37 +74,26 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
.expect("owning item has no entry");
if max != self.hir_ids_seen.len() - 1 {
- // Collect the missing ItemLocalIds
- let missing: Vec<_> = (0..=max as u32)
- .filter(|&i| !self.hir_ids_seen.contains(ItemLocalId::from_u32(i)))
- .collect();
-
- // Try to map those to something more useful
- let mut missing_items = Vec::with_capacity(missing.len());
+ let hir = self.tcx.hir();
+ let pretty_owner = hir.def_path(owner.def_id).to_string_no_crate_verbose();
- for local_id in missing {
- let hir_id = HirId { owner, local_id: ItemLocalId::from_u32(local_id) };
+ let missing_items: Vec<_> = (0..=max as u32)
+ .map(|i| ItemLocalId::from_u32(i))
+ .filter(|&local_id| !self.hir_ids_seen.contains(local_id))
+ .map(|local_id| hir.node_to_string(HirId { owner, local_id }))
+ .collect();
- trace!("missing hir id {:#?}", hir_id);
+ let seen_items: Vec<_> = self
+ .hir_ids_seen
+ .iter()
+ .map(|local_id| hir.node_to_string(HirId { owner, local_id }))
+ .collect();
- missing_items.push(format!(
- "[local_id: {}, owner: {}]",
- local_id,
- self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose()
- ));
- }
self.error(|| {
format!(
"ItemLocalIds not assigned densely in {}. \
- Max ItemLocalId = {}, missing IDs = {:#?}; seens IDs = {:#?}",
- self.tcx.hir().def_path(owner.def_id).to_string_no_crate_verbose(),
- max,
- missing_items,
- self.hir_ids_seen
- .iter()
- .map(|local_id| HirId { owner, local_id })
- .map(|h| format!("({:?} {})", h, self.tcx.hir().node_to_string(h)))
- .collect::<Vec<_>>()
+ Max ItemLocalId = {}, missing IDs = {:#?}; seen IDs = {:#?}",
+ pretty_owner, max, missing_items, seen_items
)
});
}
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index b86d23168..5e2d2d3e5 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -12,6 +12,7 @@ use rustc_hir::HirId;
use rustc_middle::hir::map::Map;
use rustc_middle::ty::TyCtxt;
use rustc_middle::util::common::to_readable_str;
+use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
@@ -363,7 +364,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
fd: &'v hir::FnDecl<'v>,
b: hir::BodyId,
_: Span,
- id: hir::HirId,
+ id: LocalDefId,
) {
self.record("FnDecl", Id::None, fd);
hir_visit::walk_fn(self, fk, fd, b, id)
@@ -567,7 +568,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
Box, Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let,
If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign,
AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret,
- InlineAsm, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err
+ InlineAsm, FormatArgs, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, IncludedBytes, Err
]
);
ast_visit::walk_expr(self, e)
@@ -645,7 +646,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
}
// `UseTree` has one inline use (in `ast::ItemKind::Use`) and one
- // non-inline use (in `ast::UseTreeKind::Nested). The former case is more
+ // non-inline use (in `ast::UseTreeKind::Nested`). The former case is more
// common, so we don't implement `visit_use_tree` and tolerate the missed
// coverage in the latter case.
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 9a40b847d..fdd0e5dab 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -15,9 +15,9 @@ use crate::weak_lang_items;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::{extract, GenericRequirement};
-use rustc_hir::{HirId, LangItem, LanguageItems, Target};
+use rustc_hir::{LangItem, LanguageItems, Target};
use rustc_middle::ty::TyCtxt;
use rustc_session::cstore::ExternCrate;
use rustc_span::{symbol::kw::Empty, Span};
@@ -40,13 +40,13 @@ impl<'tcx> LanguageItemCollector<'tcx> {
LanguageItemCollector { tcx, items: LanguageItems::new() }
}
- fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId) {
- let attrs = self.tcx.hir().attrs(hir_id);
+ fn check_for_lang(&mut self, actual_target: Target, def_id: LocalDefId) {
+ let attrs = self.tcx.hir().attrs(self.tcx.hir().local_def_id_to_hir_id(def_id));
if let Some((name, span)) = extract(&attrs) {
match LangItem::from_name(name) {
// Known lang item with attribute on correct target.
Some(lang_item) if actual_target == lang_item.target() => {
- self.collect_item_extended(lang_item, hir_id, span);
+ self.collect_item_extended(lang_item, def_id, span);
}
// Known lang item with attribute on incorrect target.
Some(lang_item) => {
@@ -142,8 +142,7 @@ impl<'tcx> LanguageItemCollector<'tcx> {
// Like collect_item() above, but also checks whether the lang item is declared
// with the right number of generic arguments.
- fn collect_item_extended(&mut self, lang_item: LangItem, hir_id: HirId, span: Span) {
- let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
+ fn collect_item_extended(&mut self, lang_item: LangItem, item_def_id: LocalDefId, span: Span) {
let name = lang_item.name();
// Now check whether the lang_item has the expected number of generic
@@ -154,7 +153,8 @@ impl<'tcx> LanguageItemCollector<'tcx> {
// Some other types like Box and various functions like drop_in_place
// have minimum requirements.
- if let hir::Node::Item(hir::Item { kind, span: item_span, .. }) = self.tcx.hir().get(hir_id)
+ if let hir::Node::Item(hir::Item { kind, span: item_span, .. }) =
+ self.tcx.hir().get_by_def_id(item_def_id)
{
let (actual_num, generics_span) = match kind.generics() {
Some(generics) => (generics.params.len(), generics.span),
@@ -191,7 +191,7 @@ impl<'tcx> LanguageItemCollector<'tcx> {
}
}
- self.collect_item(lang_item, item_def_id);
+ self.collect_item(lang_item, item_def_id.to_def_id());
}
}
@@ -211,13 +211,14 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
- collector.check_for_lang(Target::from_def_kind(tcx.def_kind(id.owner_id)), id.hir_id());
+ collector
+ .check_for_lang(Target::from_def_kind(tcx.def_kind(id.owner_id)), id.owner_id.def_id);
if matches!(tcx.def_kind(id.owner_id), DefKind::Enum) {
let item = tcx.hir().item(id);
if let hir::ItemKind::Enum(def, ..) = &item.kind {
for variant in def.variants {
- collector.check_for_lang(Target::Variant, variant.hir_id);
+ collector.check_for_lang(Target::Variant, variant.def_id);
}
}
}
@@ -226,13 +227,13 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
// FIXME: avoid calling trait_item() when possible
for id in crate_items.trait_items() {
let item = tcx.hir().trait_item(id);
- collector.check_for_lang(Target::from_trait_item(item), item.hir_id())
+ collector.check_for_lang(Target::from_trait_item(item), item.owner_id.def_id)
}
// FIXME: avoid calling impl_item() when possible
for id in crate_items.impl_items() {
let item = tcx.hir().impl_item(id);
- collector.check_for_lang(target_from_impl_item(tcx, item), item.hir_id())
+ collector.check_for_lang(target_from_impl_item(tcx, item), item.owner_id.def_id)
}
// Extract out the found lang items.
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 827d86780..047b9b525 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -29,7 +29,7 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
let tcx = tcx;
let param_env = tcx.param_env(item_def_id);
- let ty = tcx.type_of(item_def_id);
+ let ty = tcx.type_of(item_def_id).subst_identity();
match tcx.layout_of(param_env.and(ty)) {
Ok(ty_layout) => {
// Check out the `#[rustc_layout(..)]` attribute to tell what to dump.
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 6e621b7eb..0cb842408 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -18,6 +18,8 @@ extern crate rustc_middle;
#[macro_use]
extern crate tracing;
+use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_macros::fluent_messages;
use rustc_middle::ty::query::Providers;
mod check_attr;
@@ -40,6 +42,8 @@ pub mod stability;
mod upvars;
mod weak_lang_items;
+fluent_messages! { "../locales/en-US.ftl" }
+
pub fn provide(providers: &mut Providers) {
check_attr::provide(providers);
check_const::provide(providers);
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index 4c6a9b23f..f4da1aaec 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -4,7 +4,7 @@
//! but are not declared in one single location (unlike lang features), which means we need to
//! collect them instead.
-use rustc_ast::{Attribute, MetaItemKind};
+use rustc_ast::Attribute;
use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER};
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
@@ -42,8 +42,7 @@ impl<'tcx> LibFeatureCollector<'tcx> {
// Find a stability attribute: one of #[stable(…)], #[unstable(…)],
// #[rustc_const_stable(…)], #[rustc_const_unstable(…)] or #[rustc_default_body_unstable].
if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) {
- let meta_kind = attr.meta_kind();
- if let Some(MetaItemKind::List(ref metas)) = meta_kind {
+ if let Some(metas) = attr.meta_item_list() {
let mut feature = None;
let mut since = None;
for meta in metas {
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 6afdcc37f..df5c8f53e 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -145,7 +145,7 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) {
// Don't run unused pass for #[derive()]
let parent = tcx.local_parent(local_def_id);
- if let DefKind::Impl = tcx.def_kind(parent)
+ if let DefKind::Impl { .. } = tcx.def_kind(parent)
&& tcx.has_attr(parent.to_def_id(), sym::automatically_derived)
{
return;
@@ -475,7 +475,7 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
| hir::ExprKind::InlineAsm(..)
| hir::ExprKind::Box(..)
| hir::ExprKind::Type(..)
- | hir::ExprKind::Err
+ | hir::ExprKind::Err(_)
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
| hir::ExprKind::Path(hir::QPath::LangItem(..)) => {
intravisit::walk_expr(self, expr);
@@ -1129,7 +1129,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprKind::Lit(..)
| hir::ExprKind::ConstBlock(..)
- | hir::ExprKind::Err
+ | hir::ExprKind::Err(_)
| hir::ExprKind::Path(hir::QPath::TypeRelative(..))
| hir::ExprKind::Path(hir::QPath::LangItem(..)) => succ,
@@ -1427,7 +1427,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
| hir::ExprKind::Yield(..)
| hir::ExprKind::Box(..)
| hir::ExprKind::Type(..)
- | hir::ExprKind::Err => {}
+ | hir::ExprKind::Err(_) => {}
}
}
diff --git a/compiler/rustc_passes/src/liveness/rwu_table.rs b/compiler/rustc_passes/src/liveness/rwu_table.rs
index 6d5983f53..053bf5c23 100644
--- a/compiler/rustc_passes/src/liveness/rwu_table.rs
+++ b/compiler/rustc_passes/src/liveness/rwu_table.rs
@@ -9,7 +9,7 @@ pub(super) struct RWU {
}
/// Conceptually, this is like a `Vec<Vec<RWU>>`. But the number of
-/// RWU`s can get very large, so it uses a more compact representation.
+/// RWU's can get very large, so it uses a more compact representation.
pub(super) struct RWUTable {
/// Total number of live nodes.
live_nodes: usize,
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index acc54e7e1..c5b5cf7f5 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -219,7 +219,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
hir::intravisit::walk_expr(self, expr);
}
- ExprKind::Err => {
+ ExprKind::Err(_) => {
self.items.push((ItemKind::Err, span));
}
}
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index ad0952203..051100c56 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -320,31 +320,28 @@ fn check_item<'tcx>(
worklist.push(id.owner_id.def_id);
}
- if !matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
+ if !matches!(tcx.def_kind(id.owner_id), DefKind::Impl { of_trait: true }) {
return;
}
// We need only trait impls here, not inherent impls, and only non-exported ones
- let item = tcx.hir().item(id);
- if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) =
- item.kind
- {
- if !effective_visibilities.is_reachable(item.owner_id.def_id) {
- worklist.extend(items.iter().map(|ii_ref| ii_ref.id.owner_id.def_id));
+ if effective_visibilities.is_reachable(id.owner_id.def_id) {
+ return;
+ }
- let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res else {
- unreachable!();
- };
+ let items = tcx.associated_item_def_ids(id.owner_id);
+ worklist.extend(items.iter().map(|ii_ref| ii_ref.expect_local()));
- if !trait_def_id.is_local() {
- return;
- }
+ let Some(trait_def_id) = tcx.trait_id_of_impl(id.owner_id.to_def_id()) else {
+ unreachable!();
+ };
- worklist.extend(
- tcx.provided_trait_methods(trait_def_id).map(|assoc| assoc.def_id.expect_local()),
- );
- }
+ if !trait_def_id.is_local() {
+ return;
}
+
+ worklist
+ .extend(tcx.provided_trait_methods(trait_def_id).map(|assoc| assoc.def_id.expect_local()));
}
fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 34e1abb78..16194a6f1 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -1,12 +1,7 @@
//! A pass that annotates every item and method with its stability level,
//! propagating default levels lexically from parent to children ast nodes.
-use crate::errors::{
- self, CannotStabilizeDeprecated, DeprecatedAttribute, DuplicateFeatureErr,
- FeatureOnlyOnNightly, ImpliedFeatureNotExist, InvalidDeprecationVersion, InvalidStability,
- MissingConstErr, MissingConstStabAttr, MissingStabilityAttr, TraitImplConstStable,
- UnknownFeature, UselessStability,
-};
+use crate::errors;
use rustc_attr::{
self as attr, rust_version_symbol, ConstStability, Stability, StabilityLevel, Unstable,
UnstableReason, VERSION_PLACEHOLDER,
@@ -125,7 +120,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if let Some((depr, span)) = &depr {
is_deprecated = true;
- if kind == AnnotationKind::Prohibited || kind == AnnotationKind::DeprecationProhibited {
+ if matches!(kind, AnnotationKind::Prohibited | AnnotationKind::DeprecationProhibited) {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
self.tcx.emit_spanned_lint(
USELESS_DEPRECATED,
@@ -185,7 +180,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
{
self.tcx
.sess
- .emit_err(MissingConstErr { fn_sig_span: fn_sig.span, const_span });
+ .emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span });
}
}
}
@@ -203,7 +198,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if let Some((rustc_attr::Deprecation { is_since_rustc_version: true, .. }, span)) = &depr {
if stab.is_none() {
- self.tcx.sess.emit_err(DeprecatedAttribute { span: *span });
+ self.tcx.sess.emit_err(errors::DeprecatedAttribute { span: *span });
}
}
@@ -219,7 +214,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if kind == AnnotationKind::Prohibited
|| (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated)
{
- self.tcx.sess.emit_err(UselessStability { span, item_sp });
+ self.tcx.sess.emit_err(errors::UselessStability { span, item_sp });
}
debug!("annotate: found {:?}", stab);
@@ -235,15 +230,16 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
{
match stab_v.parse::<u64>() {
Err(_) => {
- self.tcx.sess.emit_err(InvalidStability { span, item_sp });
+ self.tcx.sess.emit_err(errors::InvalidStability { span, item_sp });
break;
}
Ok(stab_vp) => match dep_v.parse::<u64>() {
Ok(dep_vp) => match dep_vp.cmp(&stab_vp) {
Ordering::Less => {
- self.tcx
- .sess
- .emit_err(CannotStabilizeDeprecated { span, item_sp });
+ self.tcx.sess.emit_err(errors::CannotStabilizeDeprecated {
+ span,
+ item_sp,
+ });
break;
}
Ordering::Equal => continue,
@@ -251,9 +247,10 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
},
Err(_) => {
if dep_v != "TBD" {
- self.tcx
- .sess
- .emit_err(InvalidDeprecationVersion { span, item_sp });
+ self.tcx.sess.emit_err(errors::InvalidDeprecationVersion {
+ span,
+ item_sp,
+ });
}
break;
}
@@ -284,7 +281,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
self.recurse_with_stability_attrs(
depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
stab,
- if inherit_const_stability.yes() { const_stab } else { None },
+ inherit_const_stability.yes().then_some(const_stab).flatten(),
visit_children,
);
}
@@ -526,8 +523,8 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
&& stab.is_none()
&& self.effective_visibilities.is_reachable(def_id)
{
- let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
- self.tcx.sess.emit_err(MissingStabilityAttr { span, descr });
+ let descr = self.tcx.def_descr(def_id.to_def_id());
+ self.tcx.sess.emit_err(errors::MissingStabilityAttr { span, descr });
}
}
@@ -540,7 +537,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
// then it would be "stable" at least for the impl.
// We gate usages of it using `feature(const_trait_impl)` anyways
// so there is no unstable leakage
- if self.tcx.is_builtin_derive(def_id.to_def_id()) {
+ if self.tcx.is_automatically_derived(def_id.to_def_id()) {
return;
}
@@ -554,8 +551,8 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
let is_reachable = self.effective_visibilities.is_reachable(def_id);
if is_const && is_stable && missing_const_stability_attribute && is_reachable {
- let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
- self.tcx.sess.emit_err(MissingConstStabAttr { span, descr });
+ let descr = self.tcx.def_descr(def_id.to_def_id());
+ self.tcx.sess.emit_err(errors::MissingConstStabAttr { span, descr });
}
}
}
@@ -751,7 +748,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true };
c.visit_ty(self_ty);
c.visit_trait_ref(t);
- if c.fully_stable {
+
+ // do not lint when the trait isn't resolved, since resolution error should
+ // be fixed first
+ if t.path.res != Res::Err && c.fully_stable {
self.tcx.struct_span_lint_hir(
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
item.hir_id(),
@@ -768,7 +768,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
&& *constness == hir::Constness::Const
&& const_stab.map_or(false, |(stab, _)| stab.is_const_stable())
{
- self.tcx.sess.emit_err(TraitImplConstStable { span: item.span });
+ self.tcx.sess.emit_err(errors::TraitImplConstStable { span: item.span });
}
}
@@ -855,7 +855,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
/// See issue #94972 for details on why this is a special case
fn is_unstable_reexport(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
// Get the LocalDefId so we can lookup the item to check the kind.
- let Some(def_id) = tcx.hir().opt_local_def_id(id) else { return false; };
+ let Some(owner) = id.as_owner() else { return false; };
+ let def_id = owner.def_id;
let Some(stab) = tcx.stability().local_stability(def_id) else {
return false;
@@ -946,7 +947,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
}
if !lang_features.insert(feature) {
// Warn if the user enables a lang feature multiple times.
- tcx.sess.emit_err(DuplicateFeatureErr { span, feature });
+ tcx.sess.emit_err(errors::DuplicateFeatureErr { span, feature });
}
}
@@ -954,14 +955,14 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
let mut remaining_lib_features = FxIndexMap::default();
for (feature, span) in declared_lib_features {
if !tcx.sess.opts.unstable_features.is_nightly_build() {
- tcx.sess.emit_err(FeatureOnlyOnNightly {
+ tcx.sess.emit_err(errors::FeatureOnlyOnNightly {
span: *span,
release_channel: env!("CFG_RELEASE_CHANNEL"),
});
}
if remaining_lib_features.contains_key(&feature) {
// Warn if the user enables a lib feature multiple times.
- tcx.sess.emit_err(DuplicateFeatureErr { span: *span, feature: *feature });
+ tcx.sess.emit_err(errors::DuplicateFeatureErr { span: *span, feature: *feature });
}
remaining_lib_features.insert(feature, *span);
}
@@ -1062,7 +1063,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
}
for (feature, span) in remaining_lib_features {
- tcx.sess.emit_err(UnknownFeature { span, feature: *feature });
+ tcx.sess.emit_err(errors::UnknownFeature { span, feature: *feature });
}
for (implied_by, feature) in remaining_implications {
@@ -1073,7 +1074,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
.map(|(_, span)| span)
.or_else(|| local_defined_features.unstable.get(&feature))
.expect("feature that implied another does not exist");
- tcx.sess.emit_err(ImpliedFeatureNotExist { span, feature, implied_by });
+ tcx.sess.emit_err(errors::ImpliedFeatureNotExist { span, feature, implied_by });
}
// FIXME(#44232): the `used_features` table no longer exists, so we