summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_passes
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_passes')
-rw-r--r--compiler/rustc_passes/src/check_attr.rs277
-rw-r--r--compiler/rustc_passes/src/check_const.rs17
-rw-r--r--compiler/rustc_passes/src/dead.rs136
-rw-r--r--compiler/rustc_passes/src/debugger_visualizer.rs15
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs45
-rw-r--r--compiler/rustc_passes/src/entry.rs157
-rw-r--r--compiler/rustc_passes/src/errors.rs1095
-rw-r--r--compiler/rustc_passes/src/hir_id_validator.rs23
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs4
-rw-r--r--compiler/rustc_passes/src/lang_items.rs211
-rw-r--r--compiler/rustc_passes/src/layout_test.rs77
-rw-r--r--compiler/rustc_passes/src/lib.rs3
-rw-r--r--compiler/rustc_passes/src/lib_features.rs34
-rw-r--r--compiler/rustc_passes/src/liveness.rs65
-rw-r--r--compiler/rustc_passes/src/loops.rs161
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs88
-rw-r--r--compiler/rustc_passes/src/reachable.rs53
-rw-r--r--compiler/rustc_passes/src/stability.rs230
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs31
19 files changed, 1659 insertions, 1063 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index b3f15ba7c..27a57adf9 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -4,16 +4,21 @@
//! conflicts between multiple such attributes attached to the same
//! item.
-use crate::errors;
+use crate::errors::{
+ self, AttrApplication, DebugVisualizerUnreadable, InvalidAttrAtCrateLevel, ObjectLifetimeErr,
+ OnlyHasEffectOn, TransparentIncompatible, UnrecognizedReprHint,
+};
use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{fluent, struct_span_err, Applicability, MultiSpan};
+use rustc_errors::{fluent, Applicability, MultiSpan};
use rustc_expand::base::resolve_path;
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
use rustc_hir as hir;
-use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
+use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID};
+use rustc_hir::{
+ self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
+};
use rustc_hir::{MethodKind, Target};
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
@@ -35,8 +40,8 @@ pub(crate) fn target_from_impl_item<'tcx>(
match impl_item.kind {
hir::ImplItemKind::Const(..) => Target::AssocConst,
hir::ImplItemKind::Fn(..) => {
- let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id());
- let containing_item = tcx.hir().expect_item(parent_hir_id);
+ let parent_def_id = tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
+ let containing_item = tcx.hir().expect_item(parent_def_id);
let containing_impl_is_for_trait = match &containing_item.kind {
hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(),
_ => bug!("parent of an ImplItem must be an Impl"),
@@ -47,7 +52,7 @@ pub(crate) fn target_from_impl_item<'tcx>(
Target::Method(MethodKind::Inherent)
}
}
- hir::ImplItemKind::TyAlias(..) => Target::AssocTy,
+ hir::ImplItemKind::Type(..) => Target::AssocTy,
}
}
@@ -162,17 +167,17 @@ impl CheckAttrVisitor<'_> {
sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target),
sym::deprecated => self.check_deprecated(hir_id, attr, span, target),
sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target),
- sym::path => self.check_generic_attr(hir_id, attr, target, &[Target::Mod]),
+ sym::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 => {
- self.check_generic_attr(hir_id, attr, target, &[Target::Fn])
+ self.check_generic_attr(hir_id, attr, target, Target::Fn)
}
sym::automatically_derived => {
- self.check_generic_attr(hir_id, attr, target, &[Target::Impl])
+ self.check_generic_attr(hir_id, attr, target, Target::Impl)
}
sym::no_implicit_prelude => {
- self.check_generic_attr(hir_id, attr, target, &[Target::Mod])
+ self.check_generic_attr(hir_id, attr, target, Target::Mod)
}
sym::rustc_object_lifetime_default => self.check_object_lifetime_default(hir_id),
_ => {}
@@ -263,7 +268,7 @@ impl CheckAttrVisitor<'_> {
}
// FIXME(#65833): We permit associated consts to have an `#[inline]` attribute with
// just a lint, because we previously erroneously allowed it and some crates used it
- // accidentally, to to be compatible with crates depending on them, we can't throw an
+ // accidentally, to be compatible with crates depending on them, we can't throw an
// error here.
Target::AssocConst => {
self.tcx.emit_spanned_lint(
@@ -349,29 +354,18 @@ impl CheckAttrVisitor<'_> {
hir_id: HirId,
attr: &Attribute,
target: Target,
- allowed_targets: &[Target],
+ allowed_target: Target,
) {
- if !allowed_targets.iter().any(|t| t == &target) {
- let name = attr.name_or_empty();
- let mut i = allowed_targets.iter();
- // Pluralize
- let b = i.next().map_or_else(String::new, |t| t.to_string() + "s");
- let supported_names = i.enumerate().fold(b, |mut b, (i, allowed_target)| {
- if allowed_targets.len() > 2 && i == allowed_targets.len() - 2 {
- b.push_str(", and ");
- } else if allowed_targets.len() == 2 && i == allowed_targets.len() - 2 {
- b.push_str(" and ");
- } else {
- b.push_str(", ");
- }
- // Pluralize
- b.push_str(&(allowed_target.to_string() + "s"));
- b
- });
- self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
- lint.build(&format!("`#[{name}]` only has an effect on {}", supported_names))
- .emit();
- });
+ if target != allowed_target {
+ self.tcx.emit_spanned_lint(
+ UNUSED_ATTRIBUTES,
+ hir_id,
+ attr.span,
+ OnlyHasEffectOn {
+ attr_name: attr.name_or_empty(),
+ target_name: allowed_target.name().replace(" ", "_"),
+ },
+ );
}
}
@@ -382,7 +376,7 @@ impl CheckAttrVisitor<'_> {
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[allow_internal_unstable]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "naked");
@@ -427,7 +421,7 @@ impl CheckAttrVisitor<'_> {
ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
};
- tcx.sess.span_err(p.span, &repr);
+ tcx.sess.emit_err(ObjectLifetimeErr { span: p.span, repr });
}
}
}
@@ -462,7 +456,7 @@ impl CheckAttrVisitor<'_> {
Target::Fn | Target::Method(..) | Target::ForeignFn | Target::Closure => true,
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[track_caller]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
for attr in attrs {
@@ -491,7 +485,7 @@ impl CheckAttrVisitor<'_> {
Target::Struct | Target::Enum | Target::Variant => true,
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[non_exhaustive]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "non_exhaustive");
@@ -513,7 +507,7 @@ impl CheckAttrVisitor<'_> {
Target::Trait => true,
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[marker]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "marker");
@@ -572,7 +566,7 @@ impl CheckAttrVisitor<'_> {
}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[target_feature]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature");
@@ -640,8 +634,8 @@ impl CheckAttrVisitor<'_> {
let span = meta.span();
if let Some(location) = match target {
Target::AssocTy => {
- let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
- let containing_item = self.tcx.hir().expect_item(parent_hir_id);
+ let parent_def_id = self.tcx.hir().get_parent_item(hir_id).def_id;
+ let containing_item = self.tcx.hir().expect_item(parent_def_id);
if Target::from_item(containing_item) == Target::Impl {
Some("type alias in implementation block")
} else {
@@ -649,8 +643,8 @@ impl CheckAttrVisitor<'_> {
}
}
Target::AssocConst => {
- let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
- let containing_item = self.tcx.hir().expect_item(parent_hir_id);
+ let parent_def_id = self.tcx.hir().get_parent_item(hir_id).def_id;
+ let containing_item = self.tcx.hir().expect_item(parent_def_id);
// We can't link to trait impl's consts.
let err = "associated constant in trait implementation block";
match containing_item.kind {
@@ -828,8 +822,8 @@ impl CheckAttrVisitor<'_> {
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);
+ 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;
}
@@ -875,25 +869,31 @@ impl CheckAttrVisitor<'_> {
hir_id: HirId,
) -> bool {
if hir_id != CRATE_HIR_ID {
- self.tcx.struct_span_lint_hir(INVALID_DOC_ATTRIBUTES, hir_id, meta.span(), |lint| {
- let mut err = lint.build(fluent::passes::attr_crate_level);
- if attr.style == AttrStyle::Outer
- && self.tcx.hir().get_parent_item(hir_id) == CRATE_DEF_ID
- {
- if let Ok(mut src) = self.tcx.sess.source_map().span_to_snippet(attr.span) {
- src.insert(1, '!');
- err.span_suggestion_verbose(
- attr.span,
- fluent::passes::suggestion,
- src,
- Applicability::MaybeIncorrect,
- );
- } else {
- err.span_help(attr.span, fluent::passes::help);
+ self.tcx.struct_span_lint_hir(
+ INVALID_DOC_ATTRIBUTES,
+ hir_id,
+ meta.span(),
+ fluent::passes_attr_crate_level,
+ |err| {
+ if attr.style == AttrStyle::Outer
+ && self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID
+ {
+ if let Ok(mut src) = self.tcx.sess.source_map().span_to_snippet(attr.span) {
+ src.insert(1, '!');
+ err.span_suggestion_verbose(
+ attr.span,
+ fluent::suggestion,
+ src,
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ err.span_help(attr.span, fluent::help);
+ }
}
- }
- err.note(fluent::passes::note).emit();
- });
+ err.note(fluent::note);
+ err
+ },
+ );
return false;
}
true
@@ -934,6 +934,22 @@ impl CheckAttrVisitor<'_> {
is_valid
}
+ /// Check that the `#![doc(cfg_hide(...))]` attribute only contains a list of attributes.
+ /// Returns `true` if valid.
+ fn check_doc_cfg_hide(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
+ if meta.meta_item_list().is_some() {
+ true
+ } else {
+ self.tcx.emit_spanned_lint(
+ INVALID_DOC_ATTRIBUTES,
+ hir_id,
+ meta.span(),
+ errors::DocCfgHideTakesList,
+ );
+ false
+ }
+ }
+
/// Runs various checks on `#[doc]` attributes. Returns `true` if valid.
///
/// `specified_inline` should be initialized to `None` and kept for the scope
@@ -987,6 +1003,13 @@ impl CheckAttrVisitor<'_> {
is_valid = false;
}
+ sym::cfg_hide
+ if !self.check_attr_crate_level(attr, meta, hir_id)
+ || !self.check_doc_cfg_hide(meta, hir_id) =>
+ {
+ is_valid = false;
+ }
+
sym::inline | sym::no_inline
if !self.check_doc_inline(
attr,
@@ -1205,7 +1228,7 @@ impl CheckAttrVisitor<'_> {
Target::Fn | Target::Method(..) | Target::ForeignFn | Target::Closure => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[cold]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "cold");
@@ -1247,7 +1270,7 @@ impl CheckAttrVisitor<'_> {
Target::ForeignFn | Target::ForeignStatic => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[link_name]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "link_name");
@@ -1281,7 +1304,7 @@ impl CheckAttrVisitor<'_> {
Target::ExternCrate => true,
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[no_link]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "no_link");
@@ -1311,7 +1334,7 @@ impl CheckAttrVisitor<'_> {
Target::Method(..) if self.is_impl_item(hir_id) => true,
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[export_name]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "export_name");
@@ -1503,7 +1526,7 @@ impl CheckAttrVisitor<'_> {
Target::Static | Target::Fn | Target::Method(..) => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[link_section]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "link_section");
@@ -1528,7 +1551,7 @@ impl CheckAttrVisitor<'_> {
Target::Method(..) if self.is_impl_item(hir_id) => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[no_mangle]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "no_mangle");
@@ -1594,12 +1617,17 @@ impl CheckAttrVisitor<'_> {
continue;
}
- let (article, allowed_targets) = match hint.name_or_empty() {
+ match hint.name_or_empty() {
sym::C => {
is_c = true;
match target {
Target::Struct | Target::Union | Target::Enum => continue,
- _ => ("a", "struct, enum, or union"),
+ _ => {
+ self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
+ hint_span: hint.span(),
+ span,
+ });
+ }
}
}
sym::align => {
@@ -1615,12 +1643,20 @@ impl CheckAttrVisitor<'_> {
match target {
Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
- _ => ("a", "struct, enum, function, or union"),
+ _ => {
+ self.tcx.sess.emit_err(AttrApplication::StructEnumFunctionUnion {
+ hint_span: hint.span(),
+ span,
+ });
+ }
}
}
sym::packed => {
if target != Target::Struct && target != Target::Union {
- ("a", "struct or union")
+ self.tcx.sess.emit_err(AttrApplication::StructUnion {
+ hint_span: hint.span(),
+ span,
+ });
} else {
continue;
}
@@ -1628,7 +1664,9 @@ impl CheckAttrVisitor<'_> {
sym::simd => {
is_simd = true;
if target != Target::Struct {
- ("a", "struct")
+ self.tcx
+ .sess
+ .emit_err(AttrApplication::Struct { hint_span: hint.span(), span });
} else {
continue;
}
@@ -1637,7 +1675,12 @@ impl CheckAttrVisitor<'_> {
is_transparent = true;
match target {
Target::Struct | Target::Union | Target::Enum => continue,
- _ => ("a", "struct, enum, or union"),
+ _ => {
+ self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
+ hint_span: hint.span(),
+ span,
+ });
+ }
}
}
sym::i8
@@ -1654,35 +1697,18 @@ impl CheckAttrVisitor<'_> {
| sym::usize => {
int_reprs += 1;
if target != Target::Enum {
- ("an", "enum")
+ self.tcx
+ .sess
+ .emit_err(AttrApplication::Enum { hint_span: hint.span(), span });
} else {
continue;
}
}
_ => {
- struct_span_err!(
- self.tcx.sess,
- hint.span(),
- E0552,
- "unrecognized representation hint"
- )
- .help("valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, \
- `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`")
- .emit();
-
+ self.tcx.sess.emit_err(UnrecognizedReprHint { span: hint.span() });
continue;
}
};
-
- struct_span_err!(
- self.tcx.sess,
- hint.span(),
- E0517,
- "{}",
- &format!("attribute should be applied to {article} {allowed_targets}")
- )
- .span_label(span, &format!("not {article} {allowed_targets}"))
- .emit();
}
// Just point at all repr hints if there are any incompatibilities.
@@ -1692,14 +1718,9 @@ impl CheckAttrVisitor<'_> {
// Error on repr(transparent, <anything else>).
if is_transparent && hints.len() > 1 {
let hint_spans: Vec<_> = hint_spans.clone().collect();
- struct_span_err!(
- self.tcx.sess,
- hint_spans,
- E0692,
- "transparent {} cannot have other repr hints",
- target
- )
- .emit();
+ self.tcx
+ .sess
+ .emit_err(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)
@@ -1742,7 +1763,7 @@ impl CheckAttrVisitor<'_> {
}
}
Some(_) => {
- // This error case is handled in rustc_typeck::collect.
+ // This error case is handled in rustc_hir_analysis::collect.
}
None => {
// Default case (compiler) when arg isn't defined.
@@ -1784,7 +1805,7 @@ impl CheckAttrVisitor<'_> {
Target::MacroDef => true,
// FIXME(#80564): We permit struct fields and match arms to have an
// `#[allow_internal_unstable]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm => {
self.inline_attr_str_error_without_macro_def(
@@ -1851,14 +1872,12 @@ impl CheckAttrVisitor<'_> {
match std::fs::File::open(&file) {
Ok(_) => true,
- Err(err) => {
- self.tcx
- .sess
- .struct_span_err(
- meta_item.span,
- &format!("couldn't read {}: {}", file.display(), err),
- )
- .emit();
+ Err(error) => {
+ self.tcx.sess.emit_err(DebugVisualizerUnreadable {
+ span: meta_item.span,
+ file: &file,
+ error,
+ });
false
}
}
@@ -1881,7 +1900,7 @@ impl CheckAttrVisitor<'_> {
}
// FIXME(#80564): We permit struct fields and match arms to have an
// `#[allow_internal_unstable]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "allow_internal_unstable");
@@ -2043,7 +2062,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
// so this lets us continue to run them while maintaining backwards compatibility.
// In the long run, the checks should be harmonized.
if let ItemKind::Macro(ref macro_def, _) = item.kind {
- let def_id = item.def_id.to_def_id();
+ let def_id = item.owner_id.to_def_id();
if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) {
check_non_exported_macro_for_invalid_attrs(self.tcx, item);
}
@@ -2169,25 +2188,11 @@ 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) {
- let mut err = tcx.sess.struct_span_err(
- attr.span,
- &format!(
- "`{}` attribute cannot be used at crate level",
- attr_to_check.to_ident_string()
- ),
- );
- // Only emit an error with a suggestion if we can create a
- // string out of the attribute span
- if let Ok(src) = tcx.sess.source_map().span_to_snippet(attr.span) {
- let replacement = src.replace("#!", "#");
- err.span_suggestion_verbose(
- attr.span,
- "perhaps you meant to use an outer attribute",
- replacement,
- rustc_errors::Applicability::MachineApplicable,
- );
- }
- err.emit();
+ tcx.sess.emit_err(InvalidAttrAtCrateLevel {
+ span: attr.span,
+ snippet: tcx.sess.source_map().span_to_snippet(attr.span).ok(),
+ name: *attr_to_check,
+ });
}
}
}
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 70518284c..aa726d6cd 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -8,7 +8,6 @@
//! through, but errors for structured control flow in a `const` should be emitted here.
use rustc_attr as attr;
-use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
@@ -18,6 +17,8 @@ use rustc_middle::ty::TyCtxt;
use rustc_session::parse::feature_err;
use rustc_span::{sym, Span, Symbol};
+use crate::errors::ExprNotAllowedInContext;
+
/// An expression that is not *always* legal in a const context.
#[derive(Clone, Copy)]
enum NonConstExpr {
@@ -133,18 +134,22 @@ impl<'tcx> CheckConstVisitor<'tcx> {
let const_kind =
const_kind.expect("`const_check_violated` may only be called inside a const context");
- let msg = format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name());
-
let required_gates = required_gates.unwrap_or(&[]);
let missing_gates: Vec<_> =
required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect();
match missing_gates.as_slice() {
[] => {
- struct_span_err!(tcx.sess, span, E0744, "{}", msg).emit();
+ tcx.sess.emit_err(ExprNotAllowedInContext {
+ span,
+ expr: expr.name(),
+ context: const_kind.keyword_name(),
+ });
}
[missing_primary, ref missing_secondary @ ..] => {
+ let msg =
+ format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name());
let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, &msg);
// If multiple feature gates would be required to enable this expression, include
@@ -191,10 +196,6 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
self.tcx.hir()
}
- fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- intravisit::walk_item(self, item);
- }
-
fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
let kind = Some(hir::ConstContext::Const);
self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index f141d7bee..753d01f46 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -11,13 +11,15 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{Node, PatKind, TyKind};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::middle::privacy;
+use rustc_middle::middle::privacy::Level;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_session::lint;
use rustc_span::symbol::{sym, Symbol};
use std::mem;
+use crate::errors::UselessAssignment;
+
// Any local node that may call something in its body block should be
// explored. For example, if it's a live Node::Item that is a
// function, then we should explore its block to check for codes that
@@ -102,14 +104,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
}
}
Res::Def(_, def_id) => self.check_def_id(def_id),
- Res::SelfTy { trait_: t, alias_to: i } => {
- if let Some(t) = t {
- self.check_def_id(t);
- }
- if let Some((i, _)) = i {
- self.check_def_id(i);
- }
- }
+ Res::SelfTyParam { trait_: t } => self.check_def_id(t),
+ Res::SelfTyAlias { alias_to: i, .. } => self.check_def_id(i),
Res::ToolMod | Res::NonMacroAttr(..) | Res::Err => {}
}
}
@@ -186,18 +182,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
&& !assign.span.from_expansion()
{
let is_field_assign = matches!(lhs.kind, hir::ExprKind::Field(..));
- self.tcx.struct_span_lint_hir(
+ self.tcx.emit_spanned_lint(
lint::builtin::DEAD_CODE,
assign.hir_id,
assign.span,
- |lint| {
- lint.build(&format!(
- "useless assignment of {} of type `{}` to itself",
- if is_field_assign { "field" } else { "variable" },
- self.typeck_results().expr_ty(lhs),
- ))
- .emit();
- },
+ UselessAssignment { is_field_assign, ty: self.typeck_results().expr_ty(lhs) }
)
}
}
@@ -291,8 +280,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
}
fn visit_node(&mut self, node: Node<'tcx>) {
- if let Node::ImplItem(hir::ImplItem { def_id, .. }) = node
- && self.should_ignore_item(def_id.to_def_id())
+ if let Node::ImplItem(hir::ImplItem { owner_id, .. }) = node
+ && self.should_ignore_item(owner_id.to_def_id())
{
return;
}
@@ -304,7 +293,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
match node {
Node::Item(item) => match item.kind {
hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
- let def = self.tcx.adt_def(item.def_id);
+ let def = self.tcx.adt_def(item.owner_id);
self.repr_has_repr_c = def.repr().c();
self.repr_has_repr_simd = def.repr().simd();
@@ -317,7 +306,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
intravisit::walk_trait_item(self, trait_item);
}
Node::ImplItem(impl_item) => {
- let item = self.tcx.local_parent(impl_item.def_id);
+ let item = self.tcx.local_parent(impl_item.owner_id.def_id);
if self.tcx.impl_trait_ref(item).is_none() {
//// If it's a type whose items are live, then it's live, too.
//// This is done to handle the case where, for example, the static
@@ -374,7 +363,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
if has_repr_c || (f.is_positional() && has_repr_simd) {
return Some(def_id);
}
- if !tcx.visibility(f.hir_id.owner).is_public() {
+ if !tcx.visibility(f.hir_id.owner.def_id).is_public() {
return None;
}
if tcx.visibility(def_id).is_public() { Some(def_id) } else { None }
@@ -528,10 +517,10 @@ fn check_item<'tcx>(
) {
let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.hir_id());
if allow_dead_code {
- worklist.push(id.def_id);
+ worklist.push(id.owner_id.def_id);
}
- match tcx.def_kind(id.def_id) {
+ match tcx.def_kind(id.owner_id) {
DefKind::Enum => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Enum(ref enum_def, _) = item.kind {
@@ -551,15 +540,15 @@ fn check_item<'tcx>(
}
}
DefKind::Impl => {
- let of_trait = tcx.impl_trait_ref(id.def_id);
+ let of_trait = tcx.impl_trait_ref(id.owner_id);
if of_trait.is_some() {
- worklist.push(id.def_id);
+ worklist.push(id.owner_id.def_id);
}
// get DefIds from another query
let local_def_ids = tcx
- .associated_item_def_ids(id.def_id)
+ .associated_item_def_ids(id.owner_id)
.iter()
.filter_map(|def_id| def_id.as_local());
@@ -577,12 +566,12 @@ fn check_item<'tcx>(
if let hir::ItemKind::Struct(ref variant_data, _) = item.kind
&& let Some(ctor_hir_id) = variant_data.ctor_hir_id()
{
- struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.def_id);
+ struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.owner_id.def_id);
}
}
DefKind::GlobalAsm => {
// global_asm! is always live.
- worklist.push(id.def_id);
+ worklist.push(id.owner_id.def_id);
}
_ => {}
}
@@ -590,12 +579,12 @@ fn check_item<'tcx>(
fn check_trait_item<'tcx>(tcx: TyCtxt<'tcx>, worklist: &mut Vec<LocalDefId>, id: hir::TraitItemId) {
use hir::TraitItemKind::{Const, Fn};
- if matches!(tcx.def_kind(id.def_id), DefKind::AssocConst | DefKind::AssocFn) {
+ 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())
{
- worklist.push(trait_item.def_id);
+ worklist.push(trait_item.owner_id.def_id);
}
}
}
@@ -605,27 +594,24 @@ fn check_foreign_item<'tcx>(
worklist: &mut Vec<LocalDefId>,
id: hir::ForeignItemId,
) {
- if matches!(tcx.def_kind(id.def_id), DefKind::Static(_) | DefKind::Fn)
+ if matches!(tcx.def_kind(id.owner_id), DefKind::Static(_) | DefKind::Fn)
&& has_allow_dead_code_or_lang_attr(tcx, id.hir_id())
{
- worklist.push(id.def_id);
+ worklist.push(id.owner_id.def_id);
}
}
fn create_and_seed_worklist<'tcx>(
tcx: TyCtxt<'tcx>,
) -> (Vec<LocalDefId>, FxHashMap<LocalDefId, LocalDefId>) {
- let access_levels = &tcx.privacy_access_levels(());
+ let effective_visibilities = &tcx.effective_visibilities(());
// see `MarkSymbolVisitor::struct_constructors`
let mut struct_constructors = Default::default();
- let mut worklist = access_levels
- .map
+ let mut worklist = effective_visibilities
.iter()
- .filter_map(
- |(&id, &level)| {
- if level >= privacy::AccessLevel::Reachable { Some(id) } else { None }
- },
- )
+ .filter_map(|(&id, effective_vis)| {
+ effective_vis.is_public_at_level(Level::Reachable).then_some(id)
+ })
// Seed entry point
.chain(tcx.entry_fn(()).and_then(|(def_id, _)| def_id.as_local()))
.collect::<Vec<_>>();
@@ -726,6 +712,26 @@ impl<'tcx> DeadVisitor<'tcx> {
})
.collect();
+ let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
+ let span_len = dead_codes.len();
+ let names = match &names[..] {
+ _ if span_len > 6 => String::new(),
+ [name] => format!("`{name}` "),
+ [names @ .., last] => {
+ format!(
+ "{} and `{last}` ",
+ names.iter().map(|name| format!("`{name}`")).join(", ")
+ )
+ }
+ [] => unreachable!(),
+ };
+ let msg = format!(
+ "{these}{descr}{s} {names}{are} never {participle}",
+ these = if span_len > 6 { "multiple " } else { "" },
+ s = pluralize!(span_len),
+ are = pluralize!("is", span_len),
+ );
+
tcx.struct_span_lint_hir(
if is_positional {
lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS
@@ -734,27 +740,8 @@ impl<'tcx> DeadVisitor<'tcx> {
},
tcx.hir().local_def_id_to_hir_id(first_id),
MultiSpan::from_spans(spans.clone()),
- |lint| {
- let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
- let span_len = dead_codes.len();
- let names = match &names[..] {
- _ if span_len > 6 => String::new(),
- [name] => format!("`{name}` "),
- [names @ .., last] => {
- format!(
- "{} and `{last}` ",
- names.iter().map(|name| format!("`{name}`")).join(", ")
- )
- }
- [] => unreachable!(),
- };
- let mut err = lint.build(&format!(
- "{these}{descr}{s} {names}{are} never {participle}",
- these = if span_len > 6 { "multiple " } else { "" },
- s = pluralize!(span_len),
- are = pluralize!("is", span_len),
- ));
-
+ msg,
+ |err| {
if is_positional {
err.multipart_suggestion(
&format!(
@@ -800,7 +787,7 @@ impl<'tcx> DeadVisitor<'tcx> {
);
err.note(&msg);
}
- err.emit();
+ err
},
);
}
@@ -874,19 +861,19 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
let module_items = tcx.hir_module_items(module);
for item in module_items.items() {
- if !live_symbols.contains(&item.def_id) {
- let parent = tcx.local_parent(item.def_id);
+ if !live_symbols.contains(&item.owner_id.def_id) {
+ let parent = tcx.local_parent(item.owner_id.def_id);
if parent != module && !live_symbols.contains(&parent) {
// We already have diagnosed something.
continue;
}
- visitor.check_definition(item.def_id);
+ visitor.check_definition(item.owner_id.def_id);
continue;
}
- let def_kind = tcx.def_kind(item.def_id);
+ let def_kind = tcx.def_kind(item.owner_id);
if let DefKind::Struct | DefKind::Union | DefKind::Enum = def_kind {
- let adt = tcx.adt_def(item.def_id);
+ let adt = tcx.adt_def(item.owner_id);
let mut dead_variants = Vec::new();
for variant in adt.variants() {
@@ -929,16 +916,21 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
visitor.warn_dead_fields_and_variants(def_id, "read", dead_fields, is_positional)
}
- visitor.warn_dead_fields_and_variants(item.def_id, "constructed", dead_variants, false);
+ visitor.warn_dead_fields_and_variants(
+ item.owner_id.def_id,
+ "constructed",
+ dead_variants,
+ false,
+ );
}
}
for impl_item in module_items.impl_items() {
- visitor.check_definition(impl_item.def_id);
+ visitor.check_definition(impl_item.owner_id.def_id);
}
for foreign_item in module_items.foreign_items() {
- visitor.check_definition(foreign_item.def_id);
+ visitor.check_definition(foreign_item.owner_id.def_id);
}
// We do not warn trait items.
diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs
index e08683fe2..253b0a88e 100644
--- a/compiler/rustc_passes/src/debugger_visualizer.rs
+++ b/compiler/rustc_passes/src/debugger_visualizer.rs
@@ -13,6 +13,8 @@ use rustc_span::{sym, DebuggerVisualizerFile, DebuggerVisualizerType};
use std::sync::Arc;
+use crate::errors::DebugVisualizerUnreadable;
+
fn check_for_debugger_visualizer<'tcx>(
tcx: TyCtxt<'tcx>,
hir_id: HirId,
@@ -54,13 +56,12 @@ fn check_for_debugger_visualizer<'tcx>(
debugger_visualizers
.insert(DebuggerVisualizerFile::new(Arc::from(contents), visualizer_type));
}
- Err(err) => {
- tcx.sess
- .struct_span_err(
- meta_item.span,
- &format!("couldn't read {}: {}", file.display(), err),
- )
- .emit();
+ Err(error) => {
+ tcx.sess.emit_err(DebugVisualizerUnreadable {
+ span: meta_item.span,
+ file: &file,
+ error,
+ });
}
}
}
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index e6b69d898..a72056e00 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -14,7 +14,9 @@ use rustc_hir::diagnostic_items::DiagnosticItems;
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::{sym, Symbol};
+use rustc_span::symbol::{kw::Empty, sym, Symbol};
+
+use crate::errors::{DuplicateDiagnosticItem, DuplicateDiagnosticItemInCrate};
fn observe_item<'tcx>(
tcx: TyCtxt<'tcx>,
@@ -33,25 +35,22 @@ 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 mut err = match tcx.hir().span_if_local(item_def_id) {
- Some(span) => tcx
- .sess
- .struct_span_err(span, &format!("duplicate diagnostic item found: `{name}`.")),
- None => tcx.sess.struct_err(&format!(
- "duplicate diagnostic item in crate `{}`: `{}`.",
- tcx.crate_name(item_def_id.krate),
- name
- )),
- };
- if let Some(span) = tcx.hir().span_if_local(original_def_id) {
- err.span_note(span, "the diagnostic item is first defined here");
+ let orig_span = tcx.hir().span_if_local(original_def_id);
+ let orig_crate_name = if orig_span.is_some() {
+ None
} else {
- err.note(&format!(
- "the diagnostic item is first defined in crate `{}`.",
- tcx.crate_name(original_def_id.krate)
- ));
- }
- err.emit();
+ 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,
+ }),
+ };
}
}
}
@@ -74,19 +73,19 @@ fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> DiagnosticItems
let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
- observe_item(tcx, &mut diagnostic_items, id.def_id);
+ 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.def_id);
+ 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.def_id);
+ 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.def_id);
+ observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
}
diagnostic_items
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index cd10170d3..5885f45ae 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -1,5 +1,5 @@
use rustc_ast::entry::EntryPointType;
-use rustc_errors::struct_span_err;
+use rustc_errors::error_code;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{ItemId, Node, CRATE_HIR_ID};
@@ -8,7 +8,12 @@ use rustc_middle::ty::{DefIdTree, TyCtxt};
use rustc_session::config::{sigpipe, CrateType, EntryFnType};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
-use rustc_span::{Span, Symbol, DUMMY_SP};
+use rustc_span::{Span, Symbol};
+
+use crate::errors::{
+ AttrOnlyInFunctions, AttrOnlyOnMain, AttrOnlyOnRootMain, ExternMain, MultipleRustcMain,
+ MultipleStartFunctions, NoMainErr, UnixSigpipeValues,
+};
struct EntryContext<'tcx> {
tcx: TyCtxt<'tcx>,
@@ -57,7 +62,7 @@ fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> Entry
} else if ctxt.tcx.sess.contains_name(attrs, sym::rustc_main) {
EntryPointType::RustcMainAttr
} else {
- if let Some(name) = ctxt.tcx.opt_item_name(id.def_id.to_def_id())
+ if let Some(name) = ctxt.tcx.opt_item_name(id.owner_id.to_def_id())
&& name == sym::main {
if at_root {
// This is a top-level function so can be `main`.
@@ -71,64 +76,57 @@ fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> Entry
}
}
-fn err_if_attr_found(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol, details: &str) {
+fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Option<Span> {
let attrs = ctxt.tcx.hir().attrs(id.hir_id());
- if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym) {
- ctxt.tcx
- .sess
- .struct_span_err(attr.span, &format!("`{}` attribute {}", sym, details))
- .emit();
- }
+ ctxt.tcx.sess.find_by_name(attrs, sym).map(|attr| attr.span)
}
fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
- let at_root = ctxt.tcx.opt_local_parent(id.def_id) == Some(CRATE_DEF_ID);
+ let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID);
match entry_point_type(ctxt, id, at_root) {
EntryPointType::None => {
- err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`");
+ if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
+ ctxt.tcx.sess.emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
+ }
}
- _ if !matches!(ctxt.tcx.def_kind(id.def_id), DefKind::Fn) => {
- err_if_attr_found(ctxt, id, sym::start, "can only be used on functions");
- err_if_attr_found(ctxt, id, sym::rustc_main, "can only be used on functions");
+ _ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => {
+ for attr in [sym::start, sym::rustc_main] {
+ if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
+ ctxt.tcx.sess.emit_err(AttrOnlyInFunctions { span, attr });
+ }
+ }
}
EntryPointType::MainNamed => (),
EntryPointType::OtherMain => {
- err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on root `fn main()`");
- ctxt.non_main_fns.push(ctxt.tcx.def_span(id.def_id));
+ if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
+ ctxt.tcx.sess.emit_err(AttrOnlyOnRootMain { span, attr: sym::unix_sigpipe });
+ }
+ ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id));
}
EntryPointType::RustcMainAttr => {
if ctxt.attr_main_fn.is_none() {
- ctxt.attr_main_fn = Some((id.def_id, ctxt.tcx.def_span(id.def_id.to_def_id())));
+ ctxt.attr_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
} else {
- struct_span_err!(
- ctxt.tcx.sess,
- ctxt.tcx.def_span(id.def_id.to_def_id()),
- E0137,
- "multiple functions with a `#[rustc_main]` attribute"
- )
- .span_label(
- ctxt.tcx.def_span(id.def_id.to_def_id()),
- "additional `#[rustc_main]` function",
- )
- .span_label(ctxt.attr_main_fn.unwrap().1, "first `#[rustc_main]` function")
- .emit();
+ ctxt.tcx.sess.emit_err(MultipleRustcMain {
+ span: ctxt.tcx.def_span(id.owner_id.to_def_id()),
+ first: ctxt.attr_main_fn.unwrap().1,
+ additional: ctxt.tcx.def_span(id.owner_id.to_def_id()),
+ });
}
}
EntryPointType::Start => {
- err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`");
+ if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
+ ctxt.tcx.sess.emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
+ }
if ctxt.start_fn.is_none() {
- ctxt.start_fn = Some((id.def_id, ctxt.tcx.def_span(id.def_id.to_def_id())));
+ ctxt.start_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
} else {
- struct_span_err!(
- ctxt.tcx.sess,
- ctxt.tcx.def_span(id.def_id.to_def_id()),
- E0138,
- "multiple `start` functions"
- )
- .span_label(ctxt.start_fn.unwrap().1, "previous `#[start]` function here")
- .span_label(ctxt.tcx.def_span(id.def_id.to_def_id()), "multiple `start` functions")
- .emit();
+ ctxt.tcx.sess.emit_err(MultipleStartFunctions {
+ span: ctxt.tcx.def_span(id.owner_id),
+ labeled: ctxt.tcx.def_span(id.owner_id.to_def_id()),
+ previous: ctxt.start_fn.unwrap().1,
+ });
}
}
}
@@ -144,12 +142,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
if let Some(main_def) = tcx.resolutions(()).main_def && let Some(def_id) = main_def.opt_fn_def_id() {
// non-local main imports are handled below
if let Some(def_id) = def_id.as_local() && matches!(tcx.hir().find_by_def_id(def_id), Some(Node::ForeignItem(_))) {
- tcx.sess
- .struct_span_err(
- tcx.def_span(def_id),
- "the `main` function cannot be declared in an `extern` block",
- )
- .emit();
+ tcx.sess.emit_err(ExternMain { span: tcx.def_span(def_id) });
return None;
}
@@ -182,12 +175,7 @@ fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 {
sigpipe::DEFAULT
}
_ => {
- tcx.sess
- .struct_span_err(
- attr.span,
- "valid values for `#[unix_sigpipe = \"...\"]` are `inherit`, `sig_ign`, or `sig_dfl`",
- )
- .emit();
+ tcx.sess.emit_err(UnixSigpipeValues { span: attr.span });
sigpipe::DEFAULT
}
}
@@ -206,52 +194,29 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
}
// There is no main function.
- let mut err = struct_span_err!(
- tcx.sess,
- DUMMY_SP,
- E0601,
- "`main` function not found in crate `{}`",
- tcx.crate_name(LOCAL_CRATE)
- );
- let filename = &tcx.sess.local_crate_source_file;
- let note = if !visitor.non_main_fns.is_empty() {
- for &span in &visitor.non_main_fns {
- err.span_note(span, "here is a function named `main`");
- }
- err.note("you have one or more functions named `main` not defined at the crate level");
- err.help("consider moving the `main` function definitions");
- // There were some functions named `main` though. Try to give the user a hint.
- format!(
- "the main function must be defined at the crate level{}",
- filename.as_ref().map(|f| format!(" (in `{}`)", f.display())).unwrap_or_default()
- )
- } else if let Some(filename) = filename {
- format!("consider adding a `main` function to `{}`", filename.display())
- } else {
- String::from("consider adding a `main` function at the crate level")
- };
+ let mut has_filename = true;
+ let filename = tcx.sess.local_crate_source_file.clone().unwrap_or_else(|| {
+ has_filename = false;
+ Default::default()
+ });
+ let main_def_opt = tcx.resolutions(()).main_def;
+ let diagnostic_id = error_code!(E0601);
+ let add_teach_note = tcx.sess.teach(&diagnostic_id);
// The file may be empty, which leads to the diagnostic machinery not emitting this
// note. This is a relatively simple way to detect that case and emit a span-less
// note instead.
- if tcx.sess.source_map().lookup_line(sp.hi()).is_ok() {
- err.set_span(sp.shrink_to_hi());
- err.span_label(sp.shrink_to_hi(), &note);
- } else {
- err.note(&note);
- }
-
- if let Some(main_def) = tcx.resolutions(()).main_def && main_def.opt_fn_def_id().is_none(){
- // There is something at `crate::main`, but it is not a function definition.
- err.span_label(main_def.span, "non-function item at `crate::main` is found");
- }
-
- if tcx.sess.teach(&err.get_code().unwrap()) {
- err.note(
- "If you don't know the basics of Rust, you can go look to the Rust Book \
- to get started: https://doc.rust-lang.org/book/",
- );
- }
- err.emit();
+ let file_empty = !tcx.sess.source_map().lookup_line(sp.hi()).is_ok();
+
+ tcx.sess.emit_err(NoMainErr {
+ sp,
+ crate_name: tcx.crate_name(LOCAL_CRATE),
+ has_filename,
+ filename,
+ file_empty,
+ non_main_fns: visitor.non_main_fns.clone(),
+ main_def_opt,
+ add_teach_note,
+ });
}
pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 96cc8ae98..adaaf5392 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1,39 +1,49 @@
-use rustc_errors::{Applicability, MultiSpan};
-use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
-use rustc_span::{Span, Symbol};
+use std::{
+ io::Error,
+ path::{Path, PathBuf},
+};
+
+use rustc_ast::Label;
+use rustc_errors::{error_code, Applicability, ErrorGuaranteed, IntoDiagnostic, MultiSpan};
+use rustc_hir::{self as hir, ExprKind, Target};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
+use rustc_middle::ty::{MainDefinition, Ty};
+use rustc_span::{Span, Symbol, DUMMY_SP};
+
+use crate::lang_items::Duplicate;
#[derive(LintDiagnostic)]
-#[diag(passes::outer_crate_level_attr)]
+#[diag(passes_outer_crate_level_attr)]
pub struct OuterCrateLevelAttr;
#[derive(LintDiagnostic)]
-#[diag(passes::inner_crate_level_attr)]
+#[diag(passes_inner_crate_level_attr)]
pub struct InnerCrateLevelAttr;
#[derive(LintDiagnostic)]
-#[diag(passes::ignored_attr_with_macro)]
+#[diag(passes_ignored_attr_with_macro)]
pub struct IgnoredAttrWithMacro<'a> {
pub sym: &'a str,
}
#[derive(LintDiagnostic)]
-#[diag(passes::ignored_attr)]
+#[diag(passes_ignored_attr)]
pub struct IgnoredAttr<'a> {
pub sym: &'a str,
}
#[derive(LintDiagnostic)]
-#[diag(passes::inline_ignored_function_prototype)]
+#[diag(passes_inline_ignored_function_prototype)]
pub struct IgnoredInlineAttrFnProto;
#[derive(LintDiagnostic)]
-#[diag(passes::inline_ignored_constants)]
+#[diag(passes_inline_ignored_constants)]
#[warning]
#[note]
pub struct IgnoredInlineAttrConstants;
-#[derive(SessionDiagnostic)]
-#[diag(passes::inline_not_fn_or_closure, code = "E0518")]
+#[derive(Diagnostic)]
+#[diag(passes_inline_not_fn_or_closure, code = "E0518")]
pub struct InlineNotFnOrClosure {
#[primary_span]
pub attr_span: Span,
@@ -42,19 +52,19 @@ pub struct InlineNotFnOrClosure {
}
#[derive(LintDiagnostic)]
-#[diag(passes::no_coverage_ignored_function_prototype)]
+#[diag(passes_no_coverage_ignored_function_prototype)]
pub struct IgnoredNoCoverageFnProto;
#[derive(LintDiagnostic)]
-#[diag(passes::no_coverage_propagate)]
+#[diag(passes_no_coverage_propagate)]
pub struct IgnoredNoCoveragePropagate;
#[derive(LintDiagnostic)]
-#[diag(passes::no_coverage_fn_defn)]
+#[diag(passes_no_coverage_fn_defn)]
pub struct IgnoredNoCoverageFnDefn;
-#[derive(SessionDiagnostic)]
-#[diag(passes::no_coverage_not_coverable, code = "E0788")]
+#[derive(Diagnostic)]
+#[diag(passes_no_coverage_not_coverable, code = "E0788")]
pub struct IgnoredNoCoverageNotCoverable {
#[primary_span]
pub attr_span: Span,
@@ -62,8 +72,8 @@ pub struct IgnoredNoCoverageNotCoverable {
pub defn_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::should_be_applied_to_fn)]
+#[derive(Diagnostic)]
+#[diag(passes_should_be_applied_to_fn)]
pub struct AttrShouldBeAppliedToFn {
#[primary_span]
pub attr_span: Span,
@@ -71,15 +81,15 @@ pub struct AttrShouldBeAppliedToFn {
pub defn_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::naked_tracked_caller, code = "E0736")]
+#[derive(Diagnostic)]
+#[diag(passes_naked_tracked_caller, code = "E0736")]
pub struct NakedTrackedCaller {
#[primary_span]
pub attr_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::should_be_applied_to_fn, code = "E0739")]
+#[derive(Diagnostic)]
+#[diag(passes_should_be_applied_to_fn, code = "E0739")]
pub struct TrackedCallerWrongLocation {
#[primary_span]
pub attr_span: Span,
@@ -87,8 +97,8 @@ pub struct TrackedCallerWrongLocation {
pub defn_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::should_be_applied_to_struct_enum, code = "E0701")]
+#[derive(Diagnostic)]
+#[diag(passes_should_be_applied_to_struct_enum, code = "E0701")]
pub struct NonExhaustiveWrongLocation {
#[primary_span]
pub attr_span: Span,
@@ -96,8 +106,8 @@ pub struct NonExhaustiveWrongLocation {
pub defn_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::should_be_applied_to_trait)]
+#[derive(Diagnostic)]
+#[diag(passes_should_be_applied_to_trait)]
pub struct AttrShouldBeAppliedToTrait {
#[primary_span]
pub attr_span: Span,
@@ -106,11 +116,11 @@ pub struct AttrShouldBeAppliedToTrait {
}
#[derive(LintDiagnostic)]
-#[diag(passes::target_feature_on_statement)]
+#[diag(passes_target_feature_on_statement)]
pub struct TargetFeatureOnStatement;
-#[derive(SessionDiagnostic)]
-#[diag(passes::should_be_applied_to_static)]
+#[derive(Diagnostic)]
+#[diag(passes_should_be_applied_to_static)]
pub struct AttrShouldBeAppliedToStatic {
#[primary_span]
pub attr_span: Span,
@@ -118,24 +128,24 @@ pub struct AttrShouldBeAppliedToStatic {
pub defn_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_expect_str)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_expect_str)]
pub struct DocExpectStr<'a> {
#[primary_span]
pub attr_span: Span,
pub attr_name: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_empty)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_empty)]
pub struct DocAliasEmpty<'a> {
#[primary_span]
pub span: Span,
pub attr_str: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_bad_char)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_bad_char)]
pub struct DocAliasBadChar<'a> {
#[primary_span]
pub span: Span,
@@ -143,16 +153,16 @@ pub struct DocAliasBadChar<'a> {
pub char_: char,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_start_end)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_start_end)]
pub struct DocAliasStartEnd<'a> {
#[primary_span]
pub span: Span,
pub attr_str: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_bad_location)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_bad_location)]
pub struct DocAliasBadLocation<'a> {
#[primary_span]
pub span: Span,
@@ -160,8 +170,8 @@ pub struct DocAliasBadLocation<'a> {
pub location: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_not_an_alias)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_not_an_alias)]
pub struct DocAliasNotAnAlias<'a> {
#[primary_span]
pub span: Span,
@@ -169,64 +179,64 @@ pub struct DocAliasNotAnAlias<'a> {
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_alias_duplicated)]
+#[diag(passes_doc_alias_duplicated)]
pub struct DocAliasDuplicated {
#[label]
pub first_defn: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_not_string_literal)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_not_string_literal)]
pub struct DocAliasNotStringLiteral {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_malformed)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_malformed)]
pub struct DocAliasMalformed {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_keyword_empty_mod)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_keyword_empty_mod)]
pub struct DocKeywordEmptyMod {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_keyword_not_mod)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_keyword_not_mod)]
pub struct DocKeywordNotMod {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_keyword_invalid_ident)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_keyword_invalid_ident)]
pub struct DocKeywordInvalidIdent {
#[primary_span]
pub span: Span,
pub doc_keyword: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_fake_variadic_not_valid)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_fake_variadic_not_valid)]
pub struct DocFakeVariadicNotValid {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_keyword_only_impl)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_keyword_only_impl)]
pub struct DocKeywordOnlyImpl {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_inline_conflict)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_inline_conflict)]
#[help]
pub struct DocKeywordConflict {
#[primary_span]
@@ -234,17 +244,17 @@ pub struct DocKeywordConflict {
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_inline_only_use)]
+#[diag(passes_doc_inline_only_use)]
#[note]
pub struct DocInlineOnlyUse {
#[label]
pub attr_span: Span,
- #[label(passes::not_a_use_item_label)]
+ #[label(not_a_use_item_label)]
pub item_span: Option<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_attr_not_crate_level)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_attr_not_crate_level)]
pub struct DocAttrNotCrateLevel<'a> {
#[primary_span]
pub span: Span,
@@ -252,29 +262,33 @@ pub struct DocAttrNotCrateLevel<'a> {
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_test_unknown)]
+#[diag(passes_doc_test_unknown)]
pub struct DocTestUnknown {
pub path: String,
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_test_takes_list)]
+#[diag(passes_doc_test_takes_list)]
pub struct DocTestTakesList;
#[derive(LintDiagnostic)]
-#[diag(passes::doc_primitive)]
+#[diag(passes_doc_cfg_hide_takes_list)]
+pub struct DocCfgHideTakesList;
+
+#[derive(LintDiagnostic)]
+#[diag(passes_doc_primitive)]
pub struct DocPrimitive;
#[derive(LintDiagnostic)]
-#[diag(passes::doc_test_unknown_any)]
+#[diag(passes_doc_test_unknown_any)]
pub struct DocTestUnknownAny {
pub path: String,
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_test_unknown_spotlight)]
+#[diag(passes_doc_test_unknown_spotlight)]
#[note]
-#[note(passes::no_op_note)]
+#[note(no_op_note)]
pub struct DocTestUnknownSpotlight {
pub path: String,
#[suggestion_short(applicability = "machine-applicable", code = "notable_trait")]
@@ -282,7 +296,7 @@ pub struct DocTestUnknownSpotlight {
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_test_unknown_include)]
+#[diag(passes_doc_test_unknown_include)]
pub struct DocTestUnknownInclude {
pub path: String,
pub value: String,
@@ -292,11 +306,11 @@ pub struct DocTestUnknownInclude {
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_invalid)]
+#[diag(passes_doc_invalid)]
pub struct DocInvalid;
-#[derive(SessionDiagnostic)]
-#[diag(passes::pass_by_value)]
+#[derive(Diagnostic)]
+#[diag(passes_pass_by_value)]
pub struct PassByValue {
#[primary_span]
pub attr_span: Span,
@@ -304,8 +318,8 @@ pub struct PassByValue {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::allow_incoherent_impl)]
+#[derive(Diagnostic)]
+#[diag(passes_allow_incoherent_impl)]
pub struct AllowIncoherentImpl {
#[primary_span]
pub attr_span: Span,
@@ -313,8 +327,8 @@ pub struct AllowIncoherentImpl {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::has_incoherent_inherent_impl)]
+#[derive(Diagnostic)]
+#[diag(passes_has_incoherent_inherent_impl)]
pub struct HasIncoherentInherentImpl {
#[primary_span]
pub attr_span: Span,
@@ -323,21 +337,21 @@ pub struct HasIncoherentInherentImpl {
}
#[derive(LintDiagnostic)]
-#[diag(passes::must_use_async)]
+#[diag(passes_must_use_async)]
pub struct MustUseAsync {
#[label]
pub span: Span,
}
#[derive(LintDiagnostic)]
-#[diag(passes::must_use_no_effect)]
+#[diag(passes_must_use_no_effect)]
pub struct MustUseNoEffect {
pub article: &'static str,
pub target: rustc_hir::Target,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::must_not_suspend)]
+#[derive(Diagnostic)]
+#[diag(passes_must_not_suspend)]
pub struct MustNotSuspend {
#[primary_span]
pub attr_span: Span,
@@ -346,7 +360,7 @@ pub struct MustNotSuspend {
}
#[derive(LintDiagnostic)]
-#[diag(passes::cold)]
+#[diag(passes_cold)]
#[warning]
pub struct Cold {
#[label]
@@ -354,7 +368,7 @@ pub struct Cold {
}
#[derive(LintDiagnostic)]
-#[diag(passes::link)]
+#[diag(passes_link)]
#[warning]
pub struct Link {
#[label]
@@ -362,7 +376,7 @@ pub struct Link {
}
#[derive(LintDiagnostic)]
-#[diag(passes::link_name)]
+#[diag(passes_link_name)]
#[warning]
pub struct LinkName<'a> {
#[help]
@@ -372,8 +386,8 @@ pub struct LinkName<'a> {
pub value: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::no_link)]
+#[derive(Diagnostic)]
+#[diag(passes_no_link)]
pub struct NoLink {
#[primary_span]
pub attr_span: Span,
@@ -381,8 +395,8 @@ pub struct NoLink {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::export_name)]
+#[derive(Diagnostic)]
+#[diag(passes_export_name)]
pub struct ExportName {
#[primary_span]
pub attr_span: Span,
@@ -390,8 +404,8 @@ pub struct ExportName {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_layout_scalar_valid_range_not_struct)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_layout_scalar_valid_range_not_struct)]
pub struct RustcLayoutScalarValidRangeNotStruct {
#[primary_span]
pub attr_span: Span,
@@ -399,15 +413,15 @@ pub struct RustcLayoutScalarValidRangeNotStruct {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_layout_scalar_valid_range_arg)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_layout_scalar_valid_range_arg)]
pub struct RustcLayoutScalarValidRangeArg {
#[primary_span]
pub attr_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_legacy_const_generics_only)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_legacy_const_generics_only)]
pub struct RustcLegacyConstGenericsOnly {
#[primary_span]
pub attr_span: Span,
@@ -415,8 +429,8 @@ pub struct RustcLegacyConstGenericsOnly {
pub param_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_legacy_const_generics_index)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_legacy_const_generics_index)]
pub struct RustcLegacyConstGenericsIndex {
#[primary_span]
pub attr_span: Span,
@@ -424,8 +438,8 @@ pub struct RustcLegacyConstGenericsIndex {
pub generics_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_legacy_const_generics_index_exceed)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_legacy_const_generics_index_exceed)]
pub struct RustcLegacyConstGenericsIndexExceed {
#[primary_span]
#[label]
@@ -433,22 +447,22 @@ pub struct RustcLegacyConstGenericsIndexExceed {
pub arg_count: usize,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_legacy_const_generics_index_negative)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_legacy_const_generics_index_negative)]
pub struct RustcLegacyConstGenericsIndexNegative {
#[primary_span]
pub invalid_args: Vec<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_dirty_clean)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_dirty_clean)]
pub struct RustcDirtyClean {
#[primary_span]
pub span: Span,
}
#[derive(LintDiagnostic)]
-#[diag(passes::link_section)]
+#[diag(passes_link_section)]
#[warning]
pub struct LinkSection {
#[label]
@@ -456,52 +470,52 @@ pub struct LinkSection {
}
#[derive(LintDiagnostic)]
-#[diag(passes::no_mangle_foreign)]
+#[diag(passes_no_mangle_foreign)]
#[warning]
#[note]
pub struct NoMangleForeign {
#[label]
pub span: Span,
- #[suggestion(applicability = "machine-applicable")]
+ #[suggestion(code = "", applicability = "machine-applicable")]
pub attr_span: Span,
pub foreign_item_kind: &'static str,
}
#[derive(LintDiagnostic)]
-#[diag(passes::no_mangle)]
+#[diag(passes_no_mangle)]
#[warning]
pub struct NoMangle {
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::repr_ident, code = "E0565")]
+#[derive(Diagnostic)]
+#[diag(passes_repr_ident, code = "E0565")]
pub struct ReprIdent {
#[primary_span]
pub span: Span,
}
#[derive(LintDiagnostic)]
-#[diag(passes::repr_conflicting, code = "E0566")]
+#[diag(passes_repr_conflicting, code = "E0566")]
pub struct ReprConflicting;
-#[derive(SessionDiagnostic)]
-#[diag(passes::used_static)]
+#[derive(Diagnostic)]
+#[diag(passes_used_static)]
pub struct UsedStatic {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::used_compiler_linker)]
+#[derive(Diagnostic)]
+#[diag(passes_used_compiler_linker)]
pub struct UsedCompilerLinker {
#[primary_span]
pub spans: Vec<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::allow_internal_unstable)]
+#[derive(Diagnostic)]
+#[diag(passes_allow_internal_unstable)]
pub struct AllowInternalUnstable {
#[primary_span]
pub attr_span: Span,
@@ -509,25 +523,34 @@ pub struct AllowInternalUnstable {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::debug_visualizer_placement)]
+#[derive(Diagnostic)]
+#[diag(passes_debug_visualizer_placement)]
pub struct DebugVisualizerPlacement {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::debug_visualizer_invalid)]
-#[note(passes::note_1)]
-#[note(passes::note_2)]
-#[note(passes::note_3)]
+#[derive(Diagnostic)]
+#[diag(passes_debug_visualizer_invalid)]
+#[note(note_1)]
+#[note(note_2)]
+#[note(note_3)]
pub struct DebugVisualizerInvalid {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_allow_const_fn_unstable)]
+#[derive(Diagnostic)]
+#[diag(passes_debug_visualizer_unreadable)]
+pub struct DebugVisualizerUnreadable<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub file: &'a Path,
+ pub error: Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_rustc_allow_const_fn_unstable)]
pub struct RustcAllowConstFnUnstable {
#[primary_span]
pub attr_span: Span,
@@ -535,8 +558,8 @@ pub struct RustcAllowConstFnUnstable {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_std_internal_symbol)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_std_internal_symbol)]
pub struct RustcStdInternalSymbol {
#[primary_span]
pub attr_span: Span,
@@ -544,66 +567,66 @@ pub struct RustcStdInternalSymbol {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::const_trait)]
+#[derive(Diagnostic)]
+#[diag(passes_const_trait)]
pub struct ConstTrait {
#[primary_span]
pub attr_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::link_ordinal)]
+#[derive(Diagnostic)]
+#[diag(passes_link_ordinal)]
pub struct LinkOrdinal {
#[primary_span]
pub attr_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::stability_promotable)]
+#[derive(Diagnostic)]
+#[diag(passes_stability_promotable)]
pub struct StabilityPromotable {
#[primary_span]
pub attr_span: Span,
}
#[derive(LintDiagnostic)]
-#[diag(passes::deprecated)]
+#[diag(passes_deprecated)]
pub struct Deprecated;
#[derive(LintDiagnostic)]
-#[diag(passes::macro_use)]
+#[diag(passes_macro_use)]
pub struct MacroUse {
pub name: Symbol,
}
#[derive(LintDiagnostic)]
-#[diag(passes::macro_export)]
+#[diag(passes_macro_export)]
pub struct MacroExport;
#[derive(LintDiagnostic)]
-#[diag(passes::plugin_registrar)]
+#[diag(passes_plugin_registrar)]
pub struct PluginRegistrar;
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum UnusedNote {
- #[note(passes::unused_empty_lints_note)]
+ #[note(passes_unused_empty_lints_note)]
EmptyList { name: Symbol },
- #[note(passes::unused_no_lints_note)]
+ #[note(passes_unused_no_lints_note)]
NoLints { name: Symbol },
- #[note(passes::unused_default_method_body_const_note)]
+ #[note(passes_unused_default_method_body_const_note)]
DefaultMethodBodyConst,
}
#[derive(LintDiagnostic)]
-#[diag(passes::unused)]
+#[diag(passes_unused)]
pub struct Unused {
- #[suggestion(applicability = "machine-applicable")]
+ #[suggestion(code = "", applicability = "machine-applicable")]
pub attr_span: Span,
#[subdiagnostic]
pub note: UnusedNote,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::non_exported_macro_invalid_attrs, code = "E0518")]
+#[derive(Diagnostic)]
+#[diag(passes_non_exported_macro_invalid_attrs, code = "E0518")]
pub struct NonExportedMacroInvalidAttrs {
#[primary_span]
#[label]
@@ -611,7 +634,7 @@ pub struct NonExportedMacroInvalidAttrs {
}
#[derive(LintDiagnostic)]
-#[diag(passes::unused_duplicate)]
+#[diag(passes_unused_duplicate)]
pub struct UnusedDuplicate {
#[suggestion(code = "", applicability = "machine-applicable")]
pub this: Span,
@@ -621,8 +644,8 @@ pub struct UnusedDuplicate {
pub warning: Option<()>,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::unused_multiple)]
+#[derive(Diagnostic)]
+#[diag(passes_unused_multiple)]
pub struct UnusedMultiple {
#[primary_span]
#[suggestion(code = "", applicability = "machine-applicable")]
@@ -632,8 +655,8 @@ pub struct UnusedMultiple {
pub name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_lint_opt_ty)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_lint_opt_ty)]
pub struct RustcLintOptTy {
#[primary_span]
pub attr_span: Span,
@@ -641,8 +664,8 @@ pub struct RustcLintOptTy {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_lint_opt_deny_field_access)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_lint_opt_deny_field_access)]
pub struct RustcLintOptDenyFieldAccess {
#[primary_span]
pub attr_span: Span,
@@ -650,11 +673,779 @@ pub struct RustcLintOptDenyFieldAccess {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::collapse_debuginfo)]
+#[derive(Diagnostic)]
+#[diag(passes_collapse_debuginfo)]
pub struct CollapseDebuginfo {
#[primary_span]
pub attr_span: Span,
#[label]
pub defn_span: Span,
}
+
+#[derive(LintDiagnostic)]
+#[diag(passes_deprecated_annotation_has_no_effect)]
+pub struct DeprecatedAnnotationHasNoEffect {
+ #[suggestion(applicability = "machine-applicable", code = "")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unknown_external_lang_item, code = "E0264")]
+pub struct UnknownExternLangItem {
+ #[primary_span]
+ pub span: Span,
+ pub lang_item: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_missing_panic_handler)]
+pub struct MissingPanicHandler;
+
+#[derive(Diagnostic)]
+#[diag(passes_alloc_func_required)]
+pub struct AllocFuncRequired;
+
+#[derive(Diagnostic)]
+#[diag(passes_missing_alloc_error_handler)]
+pub struct MissingAllocErrorHandler;
+
+#[derive(Diagnostic)]
+#[diag(passes_missing_lang_item)]
+#[note]
+#[help]
+pub struct MissingLangItem {
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_lang_item_on_incorrect_target, code = "E0718")]
+pub struct LangItemOnIncorrectTarget {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub name: Symbol,
+ pub expected_target: Target,
+ pub actual_target: Target,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unknown_lang_item, code = "E0522")]
+pub struct UnknownLangItem {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+pub struct InvalidAttrAtCrateLevel {
+ pub span: Span,
+ pub snippet: Option<String>,
+ pub name: Symbol,
+}
+
+impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
+ fn into_diagnostic(
+ self,
+ handler: &'_ rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = handler.struct_err(rustc_errors::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
+ // of the attribute span
+ if let Some(src) = self.snippet {
+ let replacement = src.replace("#!", "#");
+ diag.span_suggestion_verbose(
+ self.span,
+ rustc_errors::fluent::suggestion,
+ replacement,
+ rustc_errors::Applicability::MachineApplicable,
+ );
+ }
+ diag
+ }
+}
+
+#[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 {
+ #[note(passes_diagnostic_item_first_defined)]
+ pub span: Option<Span>,
+ pub orig_crate_name: Symbol,
+ #[note]
+ pub have_orig_crate_name: Option<()>,
+ pub crate_name: Symbol,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_abi)]
+pub struct Abi {
+ #[primary_span]
+ pub span: Span,
+ pub abi: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_align)]
+pub struct Align {
+ #[primary_span]
+ pub span: Span,
+ pub align: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_size)]
+pub struct Size {
+ #[primary_span]
+ pub span: Span,
+ pub size: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_homogeneous_aggregate)]
+pub struct HomogeneousAggregate {
+ #[primary_span]
+ pub span: Span,
+ pub homogeneous_aggregate: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_layout_of)]
+pub struct LayoutOf {
+ #[primary_span]
+ pub span: Span,
+ pub normalized_ty: String,
+ pub ty_layout: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unrecognized_field)]
+pub struct UnrecognizedField {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_feature_stable_twice, code = "E0711")]
+pub struct FeatureStableTwice {
+ #[primary_span]
+ pub span: Span,
+ pub feature: Symbol,
+ pub since: Symbol,
+ pub prev_since: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_feature_previously_declared, code = "E0711")]
+pub struct FeaturePreviouslyDeclared<'a, 'b> {
+ #[primary_span]
+ pub span: Span,
+ pub feature: Symbol,
+ pub declared: &'a str,
+ pub prev_declared: &'b str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_expr_not_allowed_in_context, code = "E0744")]
+pub struct ExprNotAllowedInContext<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub expr: String,
+ pub context: &'a str,
+}
+
+pub struct BreakNonLoop<'a> {
+ pub span: Span,
+ pub head: Option<Span>,
+ pub kind: &'a str,
+ pub suggestion: String,
+ pub loop_label: Option<Label>,
+ pub break_label: Option<Label>,
+ pub break_expr_kind: &'a ExprKind<'a>,
+ pub break_expr_span: Span,
+}
+
+impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> {
+ fn into_diagnostic(
+ self,
+ handler: &rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = handler.struct_span_err_with_code(
+ self.span,
+ rustc_errors::fluent::passes_break_non_loop,
+ error_code!(E0571),
+ );
+ diag.set_arg("kind", self.kind);
+ diag.span_label(self.span, rustc_errors::fluent::label);
+ if let Some(head) = self.head {
+ diag.span_label(head, rustc_errors::fluent::label2);
+ }
+ diag.span_suggestion(
+ self.span,
+ rustc_errors::fluent::suggestion,
+ self.suggestion,
+ Applicability::MaybeIncorrect,
+ );
+ if let (Some(label), None) = (self.loop_label, self.break_label) {
+ match self.break_expr_kind {
+ ExprKind::Path(hir::QPath::Resolved(
+ None,
+ hir::Path { segments: [segment], res: hir::def::Res::Err, .. },
+ )) if label.ident.to_string() == format!("'{}", segment.ident) => {
+ // This error is redundant, we will have already emitted a
+ // suggestion to use the label when `segment` wasn't found
+ // (hence the `Res::Err` check).
+ diag.delay_as_bug();
+ }
+ _ => {
+ diag.span_suggestion(
+ self.break_expr_span,
+ rustc_errors::fluent::break_expr_suggestion,
+ label.ident,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
+ diag
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_continue_labeled_block, code = "E0696")]
+pub struct ContinueLabeledBlock {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(block_label)]
+ pub block_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_break_inside_closure, code = "E0267")]
+pub struct BreakInsideClosure<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(closure_label)]
+ pub closure_span: Span,
+ pub name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_break_inside_async_block, code = "E0267")]
+pub struct BreakInsideAsyncBlock<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(async_block_label)]
+ pub closure_span: Span,
+ pub name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_outside_loop, code = "E0268")]
+pub struct OutsideLoop<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unlabeled_in_labeled_block, code = "E0695")]
+pub struct UnlabeledInLabeledBlock<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub cf_type: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unlabeled_cf_in_while_condition, code = "E0590")]
+pub struct UnlabeledCfInWhileCondition<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub cf_type: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_cannot_inline_naked_function)]
+pub struct CannotInlineNakedFunction {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(passes_undefined_naked_function_abi)]
+pub struct UndefinedNakedFunctionAbi;
+
+#[derive(Diagnostic)]
+#[diag(passes_no_patterns)]
+pub struct NoPatterns {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_params_not_allowed)]
+#[help]
+pub struct ParamsNotAllowed {
+ #[primary_span]
+ pub span: Span,
+}
+
+pub struct NakedFunctionsAsmBlock {
+ pub span: Span,
+ pub multiple_asms: Vec<Span>,
+ pub non_asms: Vec<Span>,
+}
+
+impl IntoDiagnostic<'_> for NakedFunctionsAsmBlock {
+ fn into_diagnostic(
+ self,
+ handler: &rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = handler.struct_span_err_with_code(
+ self.span,
+ rustc_errors::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);
+ }
+ for span in self.non_asms.iter() {
+ diag.span_label(*span, rustc_errors::fluent::label_non_asm);
+ }
+ diag
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_naked_functions_operands, code = "E0787")]
+pub struct NakedFunctionsOperands {
+ #[primary_span]
+ pub unsupported_operands: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_naked_functions_asm_options, code = "E0787")]
+pub struct NakedFunctionsAsmOptions {
+ #[primary_span]
+ pub span: Span,
+ pub unsupported_options: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_naked_functions_must_use_noreturn, code = "E0787")]
+pub struct NakedFunctionsMustUseNoreturn {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(code = ", options(noreturn)", applicability = "machine-applicable")]
+ pub last_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_attr_only_on_main)]
+pub struct AttrOnlyOnMain {
+ #[primary_span]
+ pub span: Span,
+ pub attr: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_attr_only_on_root_main)]
+pub struct AttrOnlyOnRootMain {
+ #[primary_span]
+ pub span: Span,
+ pub attr: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_attr_only_in_functions)]
+pub struct AttrOnlyInFunctions {
+ #[primary_span]
+ pub span: Span,
+ pub attr: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_multiple_rustc_main, code = "E0137")]
+pub struct MultipleRustcMain {
+ #[primary_span]
+ pub span: Span,
+ #[label(first)]
+ pub first: Span,
+ #[label(additional)]
+ pub additional: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_multiple_start_functions, code = "E0138")]
+pub struct MultipleStartFunctions {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub labeled: Span,
+ #[label(previous)]
+ pub previous: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_extern_main)]
+pub struct ExternMain {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unix_sigpipe_values)]
+pub struct UnixSigpipeValues {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_no_main_function, code = "E0601")]
+pub struct NoMainFunction {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: String,
+}
+
+pub struct NoMainErr {
+ pub sp: Span,
+ pub crate_name: Symbol,
+ pub has_filename: bool,
+ pub filename: PathBuf,
+ pub file_empty: bool,
+ pub non_main_fns: Vec<Span>,
+ pub main_def_opt: Option<MainDefinition>,
+ pub add_teach_note: bool,
+}
+
+impl<'a> IntoDiagnostic<'a> for NoMainErr {
+ fn into_diagnostic(
+ self,
+ handler: &'a rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> {
+ let mut diag = handler.struct_span_err_with_code(
+ DUMMY_SP,
+ rustc_errors::fluent::passes_no_main_function,
+ error_code!(E0601),
+ );
+ diag.set_arg("crate_name", self.crate_name);
+ diag.set_arg("filename", self.filename);
+ 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.note(rustc_errors::fluent::one_or_more_possible_main);
+ diag.help(rustc_errors::fluent::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
+ } else if self.has_filename {
+ rustc_errors::fluent::consider_adding_main_to_file
+ } else {
+ rustc_errors::fluent::consider_adding_main_at_crate
+ };
+ if self.file_empty {
+ diag.note(note);
+ } else {
+ diag.set_span(self.sp.shrink_to_hi());
+ diag.span_label(self.sp.shrink_to_hi(), note);
+ }
+
+ 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);
+ }
+
+ if self.add_teach_note {
+ diag.note(rustc_errors::fluent::teach_note);
+ }
+ diag
+ }
+}
+
+pub struct DuplicateLangItem {
+ pub local_span: Option<Span>,
+ pub lang_item_name: Symbol,
+ pub crate_name: Symbol,
+ pub dependency_of: Symbol,
+ pub is_local: bool,
+ pub path: String,
+ pub first_defined_span: Option<Span>,
+ pub orig_crate_name: Symbol,
+ pub orig_dependency_of: Symbol,
+ pub orig_is_local: bool,
+ pub orig_path: String,
+ pub(crate) duplicate: Duplicate,
+}
+
+impl IntoDiagnostic<'_> for DuplicateLangItem {
+ fn into_diagnostic(
+ self,
+ handler: &rustc_errors::Handler,
+ ) -> 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
+ }
+ },
+ error_code!(E0152),
+ );
+ diag.set_arg("lang_item_name", self.lang_item_name);
+ diag.set_arg("crate_name", self.crate_name);
+ diag.set_arg("dependency_of", self.dependency_of);
+ diag.set_arg("path", self.path);
+ diag.set_arg("orig_crate_name", self.orig_crate_name);
+ diag.set_arg("orig_dependency_of", self.orig_dependency_of);
+ diag.set_arg("orig_path", self.orig_path);
+ if let Some(span) = self.local_span {
+ diag.set_span(span);
+ }
+ if let Some(span) = self.first_defined_span {
+ diag.span_note(span, rustc_errors::fluent::first_defined_span);
+ } else {
+ if self.orig_dependency_of.is_empty() {
+ diag.note(rustc_errors::fluent::first_defined_crate);
+ } else {
+ diag.note(rustc_errors::fluent::first_defined_crate_depends);
+ }
+
+ if self.orig_is_local {
+ diag.note(rustc_errors::fluent::first_definition_local);
+ } else {
+ diag.note(rustc_errors::fluent::first_definition_path);
+ }
+
+ if self.is_local {
+ diag.note(rustc_errors::fluent::second_definition_local);
+ } else {
+ diag.note(rustc_errors::fluent::second_definition_path);
+ }
+ }
+ diag
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_incorrect_target, code = "E0718")]
+pub struct IncorrectTarget<'a> {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub generics_span: Span,
+ pub name: &'a str, // cannot be symbol because it renders e.g. `r#fn` instead of `fn`
+ pub kind: &'static str,
+ pub num: usize,
+ pub actual_num: usize,
+ pub at_least: bool,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(passes_useless_assignment)]
+pub struct UselessAssignment<'a> {
+ pub is_field_assign: bool,
+ pub ty: Ty<'a>,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(passes_only_has_effect_on)]
+pub struct OnlyHasEffectOn {
+ pub attr_name: Symbol,
+ pub target_name: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_object_lifetime_err)]
+pub struct ObjectLifetimeErr {
+ #[primary_span]
+ pub span: Span,
+ pub repr: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unrecognized_repr_hint, code = "E0552")]
+#[help]
+pub struct UnrecognizedReprHint {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+pub enum AttrApplication {
+ #[diag(passes_attr_application_enum, code = "E0517")]
+ Enum {
+ #[primary_span]
+ hint_span: Span,
+ #[label]
+ span: Span,
+ },
+ #[diag(passes_attr_application_struct, code = "E0517")]
+ Struct {
+ #[primary_span]
+ hint_span: Span,
+ #[label]
+ span: Span,
+ },
+ #[diag(passes_attr_application_struct_union, code = "E0517")]
+ StructUnion {
+ #[primary_span]
+ hint_span: Span,
+ #[label]
+ span: Span,
+ },
+ #[diag(passes_attr_application_struct_enum_union, code = "E0517")]
+ StructEnumUnion {
+ #[primary_span]
+ hint_span: Span,
+ #[label]
+ span: Span,
+ },
+ #[diag(passes_attr_application_struct_enum_function_union, code = "E0517")]
+ StructEnumFunctionUnion {
+ #[primary_span]
+ hint_span: Span,
+ #[label]
+ span: Span,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_transparent_incompatible, code = "E0692")]
+pub struct TransparentIncompatible {
+ #[primary_span]
+ pub hint_spans: Vec<Span>,
+ pub target: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_deprecated_attribute, code = "E0549")]
+pub struct DeprecatedAttribute {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_useless_stability)]
+pub struct UselessStability {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(item)]
+ pub item_sp: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_invalid_stability)]
+pub struct InvalidStability {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(item)]
+ pub item_sp: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_cannot_stabilize_deprecated)]
+pub struct CannotStabilizeDeprecated {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(item)]
+ pub item_sp: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_invalid_deprecation_version)]
+pub struct InvalidDeprecationVersion {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(item)]
+ pub item_sp: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_missing_stability_attr)]
+pub struct MissingStabilityAttr<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub descr: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_missing_const_stab_attr)]
+pub struct MissingConstStabAttr<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub descr: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_trait_impl_const_stable)]
+#[note]
+pub struct TraitImplConstStable {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_feature_only_on_nightly, code = "E0554")]
+pub struct FeatureOnlyOnNightly {
+ #[primary_span]
+ pub span: Span,
+ pub release_channel: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unknown_feature, code = "E0635")]
+pub struct UnknownFeature {
+ #[primary_span]
+ pub span: Span,
+ pub feature: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_implied_feature_not_exist)]
+pub struct ImpliedFeatureNotExist {
+ #[primary_span]
+ pub span: Span,
+ pub feature: Symbol,
+ pub implied_by: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_duplicate_feature_err, code = "E0636")]
+pub struct DuplicateFeatureErr {
+ #[primary_span]
+ pub span: Span,
+ pub feature: Symbol,
+}
+#[derive(Diagnostic)]
+#[diag(passes_missing_const_err)]
+pub struct MissingConstErr {
+ #[primary_span]
+ #[help]
+ pub fn_sig_span: Span,
+ #[label]
+ pub const_span: Span,
+}
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index 3bb8c0bb4..88bb39deb 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -1,6 +1,5 @@
use rustc_data_structures::sync::Lock;
use rustc_hir as hir;
-use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::intravisit;
use rustc_hir::{HirId, ItemLocalId};
use rustc_index::bit_set::GrowableBitSet;
@@ -42,7 +41,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
struct HirIdValidator<'a, 'hir> {
hir_map: Map<'hir>,
- owner: Option<LocalDefId>,
+ owner: Option<hir::OwnerId>,
hir_ids_seen: GrowableBitSet<ItemLocalId>,
errors: &'a Lock<Vec<String>>,
}
@@ -63,12 +62,12 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
self.errors.lock().push(f());
}
- fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, owner: LocalDefId, walk: F) {
+ fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, owner: hir::OwnerId, walk: F) {
assert!(self.owner.is_none());
self.owner = Some(owner);
walk(self);
- if owner == CRATE_DEF_ID {
+ if owner == hir::CRATE_OWNER_ID {
return;
}
@@ -97,14 +96,14 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
missing_items.push(format!(
"[local_id: {}, owner: {}]",
local_id,
- self.hir_map.def_path(owner).to_string_no_crate_verbose()
+ self.hir_map.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.hir_map.def_path(owner).to_string_no_crate_verbose(),
+ self.hir_map.def_path(owner.def_id).to_string_no_crate_verbose(),
max,
missing_items,
self.hir_ids_seen
@@ -127,7 +126,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
fn visit_item(&mut self, i: &'hir hir::Item<'hir>) {
let mut inner_visitor = self.new_visitor(self.hir_map);
- inner_visitor.check(i.def_id, |this| intravisit::walk_item(this, i));
+ inner_visitor.check(i.owner_id, |this| intravisit::walk_item(this, i));
}
fn visit_id(&mut self, hir_id: HirId) {
@@ -138,8 +137,8 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
format!(
"HirIdValidator: The recorded owner of {} is {} instead of {}",
self.hir_map.node_to_string(hir_id),
- self.hir_map.def_path(hir_id.owner).to_string_no_crate_verbose(),
- self.hir_map.def_path(owner).to_string_no_crate_verbose()
+ self.hir_map.def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
+ self.hir_map.def_path(owner.def_id).to_string_no_crate_verbose()
)
});
}
@@ -149,16 +148,16 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
fn visit_foreign_item(&mut self, i: &'hir hir::ForeignItem<'hir>) {
let mut inner_visitor = self.new_visitor(self.hir_map);
- inner_visitor.check(i.def_id, |this| intravisit::walk_foreign_item(this, i));
+ inner_visitor.check(i.owner_id, |this| intravisit::walk_foreign_item(this, i));
}
fn visit_trait_item(&mut self, i: &'hir hir::TraitItem<'hir>) {
let mut inner_visitor = self.new_visitor(self.hir_map);
- inner_visitor.check(i.def_id, |this| intravisit::walk_trait_item(this, i));
+ inner_visitor.check(i.owner_id, |this| intravisit::walk_trait_item(this, i));
}
fn visit_impl_item(&mut self, i: &'hir hir::ImplItem<'hir>) {
let mut inner_visitor = self.new_visitor(self.hir_map);
- inner_visitor.check(i.def_id, |this| intravisit::walk_impl_item(this, i));
+ inner_visitor.check(i.owner_id, |this| intravisit::walk_impl_item(this, i));
}
}
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 0be2fc053..33220fd2b 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -391,7 +391,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
record_variants!(
(self, ii, ii.kind, Id::Node(ii.hir_id()), hir, ImplItem, ImplItemKind),
- [Const, Fn, TyAlias]
+ [Const, Fn, Type]
);
hir_visit::walk_impl_item(self, ii)
}
@@ -620,7 +620,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
record_variants!(
(self, i, i.kind, Id::None, ast, AssocItem, AssocItemKind),
- [Const, Fn, TyAlias, MacCall]
+ [Const, Fn, Type, MacCall]
);
ast_visit::walk_assoc_item(self, i, ctxt);
}
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 79900a90a..df811be2a 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -8,9 +8,11 @@
//! * Functions called by the compiler itself.
use crate::check_attr::target_from_impl_item;
+use crate::errors::{
+ DuplicateLangItem, IncorrectTarget, LangItemOnIncorrectTarget, UnknownLangItem,
+};
use crate::weak_lang_items;
-use rustc_errors::{pluralize, struct_span_err};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
@@ -18,10 +20,16 @@ use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS};
use rustc_hir::{HirId, LangItem, LanguageItems, Target};
use rustc_middle::ty::TyCtxt;
use rustc_session::cstore::ExternCrate;
-use rustc_span::Span;
+use rustc_span::{symbol::kw::Empty, Span};
use rustc_middle::ty::query::Providers;
+pub(crate) enum Duplicate {
+ Plain,
+ Crate,
+ CrateDepends,
+}
+
struct LanguageItemCollector<'tcx> {
items: LanguageItems,
tcx: TyCtxt<'tcx>,
@@ -34,42 +42,24 @@ impl<'tcx> LanguageItemCollector<'tcx> {
fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId) {
let attrs = self.tcx.hir().attrs(hir_id);
- if let Some((value, span)) = extract(&attrs) {
- match ITEM_REFS.get(&value).cloned() {
+ if let Some((name, span)) = extract(&attrs) {
+ match ITEM_REFS.get(&name).cloned() {
// Known lang item with attribute on correct target.
Some((item_index, expected_target)) if actual_target == expected_target => {
self.collect_item_extended(item_index, hir_id, span);
}
// Known lang item with attribute on incorrect target.
Some((_, expected_target)) => {
- struct_span_err!(
- self.tcx.sess,
+ self.tcx.sess.emit_err(LangItemOnIncorrectTarget {
span,
- E0718,
- "`{}` language item must be applied to a {}",
- value,
+ name,
expected_target,
- )
- .span_label(
- span,
- format!(
- "attribute should be applied to a {}, not a {}",
- expected_target, actual_target,
- ),
- )
- .emit();
+ actual_target,
+ });
}
// Unknown lang item.
_ => {
- struct_span_err!(
- self.tcx.sess,
- span,
- E0522,
- "definition of an unknown language item: `{}`",
- value
- )
- .span_label(span, format!("definition of unknown language item `{}`", value))
- .emit();
+ self.tcx.sess.emit_err(UnknownLangItem { span, name });
}
}
}
@@ -79,74 +69,72 @@ impl<'tcx> LanguageItemCollector<'tcx> {
// Check for duplicates.
if let Some(original_def_id) = self.items.items[item_index] {
if original_def_id != item_def_id {
- let lang_item = LangItem::from_u32(item_index as u32).unwrap();
- let name = lang_item.name();
- let mut err = match self.tcx.hir().span_if_local(item_def_id) {
- Some(span) => struct_span_err!(
- self.tcx.sess,
- span,
- E0152,
- "found duplicate lang item `{}`",
- name
- ),
- None => match self.tcx.extern_crate(item_def_id) {
- Some(ExternCrate { dependency_of, .. }) => {
- self.tcx.sess.struct_err(&format!(
- "duplicate lang item in crate `{}` (which `{}` depends on): `{}`.",
- self.tcx.crate_name(item_def_id.krate),
- self.tcx.crate_name(*dependency_of),
- name
- ))
- }
- _ => self.tcx.sess.struct_err(&format!(
- "duplicate lang item in crate `{}`: `{}`.",
- self.tcx.crate_name(item_def_id.krate),
- name
- )),
- },
+ let local_span = self.tcx.hir().span_if_local(item_def_id);
+ let lang_item_name = LangItem::from_u32(item_index as u32).unwrap().name();
+ let crate_name = self.tcx.crate_name(item_def_id.krate);
+ let mut dependency_of = Empty;
+ let is_local = item_def_id.is_local();
+ let path = if is_local {
+ String::new()
+ } else {
+ self.tcx
+ .crate_extern_paths(item_def_id.krate)
+ .iter()
+ .map(|p| p.display().to_string())
+ .collect::<Vec<_>>()
+ .join(", ")
+ .into()
};
- if let Some(span) = self.tcx.hir().span_if_local(original_def_id) {
- err.span_note(span, "the lang item is first defined here");
+ let first_defined_span = self.tcx.hir().span_if_local(original_def_id);
+ let mut orig_crate_name = Empty;
+ let mut orig_dependency_of = Empty;
+ let orig_is_local = original_def_id.is_local();
+ let orig_path = if orig_is_local {
+ String::new()
} else {
- match self.tcx.extern_crate(original_def_id) {
- Some(ExternCrate { dependency_of, .. }) => {
- err.note(&format!(
- "the lang item is first defined in crate `{}` (which `{}` depends on)",
- self.tcx.crate_name(original_def_id.krate),
- self.tcx.crate_name(*dependency_of)
- ));
- }
- _ => {
- err.note(&format!(
- "the lang item is first defined in crate `{}`.",
- self.tcx.crate_name(original_def_id.krate)
- ));
- }
+ self.tcx
+ .crate_extern_paths(original_def_id.krate)
+ .iter()
+ .map(|p| p.display().to_string())
+ .collect::<Vec<_>>()
+ .join(", ")
+ .into()
+ };
+ if first_defined_span.is_none() {
+ orig_crate_name = self.tcx.crate_name(original_def_id.krate);
+ if let Some(ExternCrate { dependency_of: inner_dependency_of, .. }) =
+ self.tcx.extern_crate(original_def_id)
+ {
+ orig_dependency_of = self.tcx.crate_name(*inner_dependency_of);
}
- let mut note_def = |which, def_id: DefId| {
- let crate_name = self.tcx.crate_name(def_id.krate);
- let note = if def_id.is_local() {
- format!("{} definition in the local crate (`{}`)", which, crate_name)
- } else {
- let paths: Vec<_> = self
- .tcx
- .crate_extern_paths(def_id.krate)
- .iter()
- .map(|p| p.display().to_string())
- .collect();
- format!(
- "{} definition in `{}` loaded from {}",
- which,
- crate_name,
- paths.join(", ")
- )
- };
- err.note(&note);
- };
- note_def("first", original_def_id);
- note_def("second", item_def_id);
}
- err.emit();
+
+ let duplicate = if local_span.is_some() {
+ Duplicate::Plain
+ } else {
+ match self.tcx.extern_crate(item_def_id) {
+ Some(ExternCrate { dependency_of: inner_dependency_of, .. }) => {
+ dependency_of = self.tcx.crate_name(*inner_dependency_of);
+ Duplicate::CrateDepends
+ }
+ _ => Duplicate::Crate,
+ }
+ };
+
+ self.tcx.sess.emit_err(DuplicateLangItem {
+ local_span,
+ lang_item_name,
+ crate_name,
+ dependency_of,
+ is_local,
+ path,
+ first_defined_span,
+ orig_crate_name,
+ orig_dependency_of,
+ orig_is_local,
+ orig_path,
+ duplicate,
+ });
}
}
@@ -179,41 +167,30 @@ impl<'tcx> LanguageItemCollector<'tcx> {
None => (0, *item_span),
};
+ let mut at_least = false;
let required = match lang_item.required_generics() {
- GenericRequirement::Exact(num) if num != actual_num => {
- Some((format!("{}", num), pluralize!(num)))
- }
+ GenericRequirement::Exact(num) if num != actual_num => Some(num),
GenericRequirement::Minimum(num) if actual_num < num => {
- Some((format!("at least {}", num), pluralize!(num)))
- }
+ at_least = true;
+ Some(num)}
+ ,
// If the number matches, or there is no requirement, handle it normally
_ => None,
};
- if let Some((range_str, pluralized)) = required {
+ if let Some(num) = required {
// We are issuing E0718 "incorrect target" here, because while the
// item kind of the target is correct, the target is still wrong
// because of the wrong number of generic arguments.
- struct_span_err!(
- self.tcx.sess,
+ self.tcx.sess.emit_err(IncorrectTarget {
span,
- E0718,
- "`{}` language item must be applied to a {} with {} generic argument{}",
- name,
- kind.descr(),
- range_str,
- pluralized,
- )
- .span_label(
generics_span,
- format!(
- "this {} has {} generic argument{}",
- kind.descr(),
- actual_num,
- pluralize!(actual_num),
- ),
- )
- .emit();
+ name: name.as_str(),
+ kind: kind.descr(),
+ num,
+ actual_num,
+ at_least,
+ });
// return early to not collect the lang item
return;
@@ -240,9 +217,9 @@ 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.def_id)), id.hir_id());
+ collector.check_for_lang(Target::from_def_kind(tcx.def_kind(id.owner_id)), id.hir_id());
- if matches!(tcx.def_kind(id.def_id), DefKind::Enum) {
+ 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 {
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index fd03f6571..5322baee7 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -3,20 +3,23 @@ use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
+use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
+use crate::errors::{Abi, Align, HomogeneousAggregate, LayoutOf, Size, UnrecognizedField};
+
pub fn test_layout(tcx: TyCtxt<'_>) {
if tcx.features().rustc_attrs {
// if the `rustc_attrs` feature is not enabled, don't bother testing layout
for id in tcx.hir().items() {
if matches!(
- tcx.def_kind(id.def_id),
+ tcx.def_kind(id.owner_id),
DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union
) {
- for attr in tcx.get_attrs(id.def_id.to_def_id(), sym::rustc_layout) {
- dump_layout_of(tcx, id.def_id, attr);
+ for attr in tcx.get_attrs(id.owner_id.to_def_id(), sym::rustc_layout) {
+ dump_layout_of(tcx, id.owner_id.def_id, attr);
}
}
}
@@ -35,62 +38,64 @@ fn dump_layout_of<'tcx>(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId, attr: &Attri
for meta_item in meta_items {
match meta_item.name_or_empty() {
sym::abi => {
- tcx.sess.span_err(
- tcx.def_span(item_def_id.to_def_id()),
- &format!("abi: {:?}", ty_layout.abi),
- );
+ tcx.sess.emit_err(Abi {
+ span: tcx.def_span(item_def_id.to_def_id()),
+ abi: format!("{:?}", ty_layout.abi),
+ });
}
sym::align => {
- tcx.sess.span_err(
- tcx.def_span(item_def_id.to_def_id()),
- &format!("align: {:?}", ty_layout.align),
- );
+ tcx.sess.emit_err(Align {
+ span: tcx.def_span(item_def_id.to_def_id()),
+ align: format!("{:?}", ty_layout.align),
+ });
}
sym::size => {
- tcx.sess.span_err(
- tcx.def_span(item_def_id.to_def_id()),
- &format!("size: {:?}", ty_layout.size),
- );
+ tcx.sess.emit_err(Size {
+ span: tcx.def_span(item_def_id.to_def_id()),
+ size: format!("{:?}", ty_layout.size),
+ });
}
sym::homogeneous_aggregate => {
- tcx.sess.span_err(
- tcx.def_span(item_def_id.to_def_id()),
- &format!(
- "homogeneous_aggregate: {:?}",
- ty_layout.homogeneous_aggregate(&UnwrapLayoutCx { tcx, param_env }),
+ tcx.sess.emit_err(HomogeneousAggregate {
+ span: tcx.def_span(item_def_id.to_def_id()),
+ homogeneous_aggregate: format!(
+ "{:?}",
+ ty_layout.homogeneous_aggregate(&UnwrapLayoutCx { tcx, param_env })
),
- );
+ });
}
sym::debug => {
- let normalized_ty = tcx.normalize_erasing_regions(
- param_env.with_reveal_all_normalized(tcx),
- ty,
- );
- tcx.sess.span_err(
- tcx.def_span(item_def_id.to_def_id()),
- &format!("layout_of({:?}) = {:#?}", normalized_ty, *ty_layout),
+ let normalized_ty = format!(
+ "{:?}",
+ tcx.normalize_erasing_regions(
+ param_env.with_reveal_all_normalized(tcx),
+ ty,
+ )
);
+ let ty_layout = format!("{:#?}", *ty_layout);
+ tcx.sess.emit_err(LayoutOf {
+ span: tcx.def_span(item_def_id.to_def_id()),
+ normalized_ty,
+ ty_layout,
+ });
}
name => {
- tcx.sess.span_err(
- meta_item.span(),
- &format!("unrecognized field name `{}`", name),
- );
+ tcx.sess.emit_err(UnrecognizedField { span: meta_item.span(), name });
}
}
}
}
Err(layout_error) => {
- tcx.sess.span_err(
- tcx.def_span(item_def_id.to_def_id()),
- &format!("layout error: {:?}", layout_error),
- );
+ tcx.sess.emit_fatal(Spanned {
+ node: layout_error,
+ span: tcx.def_span(item_def_id.to_def_id()),
+ });
}
}
}
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 39ebb8db2..15f60f626 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -5,10 +5,11 @@
//! This API is completely unstable and subject to change.
#![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(iter_intersperse)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(map_try_insert)]
#![feature(min_specialization)]
#![feature(try_blocks)]
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index 04173c792..b5843c0ae 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -6,7 +6,6 @@
use rustc_ast::{Attribute, MetaItemKind};
use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER};
-use rustc_errors::struct_span_err;
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::lib_features::LibFeatures;
@@ -15,6 +14,8 @@ use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::Symbol;
use rustc_span::{sym, Span};
+use crate::errors::{FeaturePreviouslyDeclared, FeatureStableTwice};
+
fn new_lib_features() -> LibFeatures {
LibFeatures { stable: Default::default(), unstable: Default::default() }
}
@@ -92,14 +93,12 @@ impl<'tcx> LibFeatureCollector<'tcx> {
(Some(since), _, false) => {
if let Some((prev_since, _)) = self.lib_features.stable.get(&feature) {
if *prev_since != since {
- self.span_feature_error(
+ self.tcx.sess.emit_err(FeatureStableTwice {
span,
- &format!(
- "feature `{}` is declared stable since {}, \
- but was previously declared stable since {}",
- feature, since, prev_since,
- ),
- );
+ feature,
+ since,
+ prev_since: *prev_since,
+ });
return;
}
}
@@ -110,22 +109,17 @@ impl<'tcx> LibFeatureCollector<'tcx> {
self.lib_features.unstable.insert(feature, span);
}
(Some(_), _, true) | (None, true, _) => {
- self.span_feature_error(
+ let declared = if since.is_some() { "stable" } else { "unstable" };
+ let prev_declared = if since.is_none() { "stable" } else { "unstable" };
+ self.tcx.sess.emit_err(FeaturePreviouslyDeclared {
span,
- &format!(
- "feature `{}` is declared {}, but was previously declared {}",
- feature,
- if since.is_some() { "stable" } else { "unstable" },
- if since.is_none() { "stable" } else { "unstable" },
- ),
- );
+ feature,
+ declared,
+ prev_declared,
+ });
}
}
}
-
- fn span_feature_error(&self, span: Span, msg: &str) {
- struct_span_err!(self.tcx.sess, span, E0711, "{}", &msg).emit();
- }
}
impl<'tcx> Visitor<'tcx> for LibFeatureCollector<'tcx> {
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 6a4cd79cd..c6fe40f72 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -1319,14 +1319,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// that we do not emit the same warning twice if the uninhabited type
// is indeed `!`.
+ let msg = format!("unreachable {}", descr);
self.ir.tcx.struct_span_lint_hir(
lint::builtin::UNREACHABLE_CODE,
expr_id,
expr_span,
- |lint| {
- let msg = format!("unreachable {}", descr);
- lint.build(&msg)
- .span_label(expr_span, &msg)
+ &msg,
+ |diag| {
+ diag.span_label(expr_span, &msg)
.span_label(orig_span, "any code following this expression is unreachable")
.span_note(
orig_span,
@@ -1335,7 +1335,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
orig_ty
),
)
- .emit();
},
);
}
@@ -1491,14 +1490,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
lint::builtin::UNUSED_ASSIGNMENTS,
var_hir_id,
vec![span],
- |lint| {
- lint.build(&format!(
- "value captured by `{}` is never read",
- name
- ))
- .help("did you mean to capture by reference instead?")
- .emit();
- },
+ format!("value captured by `{}` is never read", name),
+ |lint| lint.help("did you mean to capture by reference instead?"),
);
}
}
@@ -1508,11 +1501,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
lint::builtin::UNUSED_VARIABLES,
var_hir_id,
vec![span],
- |lint| {
- lint.build(&format!("unused variable: `{}`", name))
- .help("did you mean to capture by reference instead?")
- .emit();
- },
+ format!("unused variable: `{}`", name),
+ |lint| lint.help("did you mean to capture by reference instead?"),
);
}
}
@@ -1601,20 +1591,17 @@ impl<'tcx> Liveness<'_, 'tcx> {
.into_iter()
.map(|(_, _, ident_span)| ident_span)
.collect::<Vec<_>>(),
- |lint| {
- lint.build(&format!("variable `{}` is assigned to, but never used", name))
- .note(&format!("consider using `_{}` instead", name))
- .emit();
- },
+ format!("variable `{}` is assigned to, but never used", name),
+ |lint| lint.note(&format!("consider using `_{}` instead", name)),
)
} else if can_remove {
self.ir.tcx.struct_span_lint_hir(
lint::builtin::UNUSED_VARIABLES,
first_hir_id,
hir_ids_and_spans.iter().map(|(_, pat_span, _)| *pat_span).collect::<Vec<_>>(),
+ format!("unused variable: `{}`", name),
|lint| {
- let mut err = lint.build(&format!("unused variable: `{}`", name));
- err.multipart_suggestion(
+ lint.multipart_suggestion(
"try removing the field",
hir_ids_and_spans
.iter()
@@ -1629,8 +1616,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
})
.collect(),
Applicability::MachineApplicable,
- );
- err.emit();
+ )
},
);
} else {
@@ -1661,14 +1647,13 @@ impl<'tcx> Liveness<'_, 'tcx> {
.iter()
.map(|(_, pat_span, _)| *pat_span)
.collect::<Vec<_>>(),
+ format!("unused variable: `{}`", name),
|lint| {
- let mut err = lint.build(&format!("unused variable: `{}`", name));
- err.multipart_suggestion(
+ lint.multipart_suggestion(
"try ignoring the field",
shorthands,
Applicability::MachineApplicable,
- );
- err.emit();
+ )
},
);
} else {
@@ -1684,17 +1669,16 @@ impl<'tcx> Liveness<'_, 'tcx> {
.iter()
.map(|(_, _, ident_span)| *ident_span)
.collect::<Vec<_>>(),
+ format!("unused variable: `{}`", name),
|lint| {
- let mut err = lint.build(&format!("unused variable: `{}`", name));
- if self.has_added_lit_match_name_span(&name, opt_body, &mut err) {
- err.span_label(pat.span, "unused variable");
+ if self.has_added_lit_match_name_span(&name, opt_body, lint) {
+ lint.span_label(pat.span, "unused variable");
}
- err.multipart_suggestion(
+ lint.multipart_suggestion(
"if this is intentional, prefix it with an underscore",
non_shorthands,
Applicability::MachineApplicable,
- );
- err.emit();
+ )
},
);
}
@@ -1758,11 +1742,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
lint::builtin::UNUSED_ASSIGNMENTS,
hir_id,
spans,
- |lint| {
- lint.build(&message(&name))
- .help("maybe it is overwritten before being read?")
- .emit();
- },
+ message(&name),
+ |lint| lint.help("maybe it is overwritten before being read?"),
)
}
}
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index cdda0e388..077194ec6 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -1,6 +1,5 @@
use Context::*;
-use rustc_errors::{struct_span_err, Applicability};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
@@ -13,6 +12,11 @@ use rustc_session::Session;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::Span;
+use crate::errors::{
+ BreakInsideAsyncBlock, BreakInsideClosure, BreakNonLoop, ContinueLabeledBlock, OutsideLoop,
+ UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock,
+};
+
#[derive(Clone, Copy, Debug, PartialEq)]
enum Context {
Normal,
@@ -90,7 +94,10 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
Ok(loop_id) => Some(loop_id),
Err(hir::LoopIdError::OutsideLoopScope) => None,
Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
- self.emit_unlabled_cf_in_while_condition(e.span, "break");
+ self.sess.emit_err(UnlabeledCfInWhileCondition {
+ span: e.span,
+ cf_type: "break",
+ });
None
}
Err(hir::LoopIdError::UnresolvedLabel) => None,
@@ -116,69 +123,22 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
match loop_kind {
None | Some(hir::LoopSource::Loop) => (),
Some(kind) => {
- let mut err = struct_span_err!(
- self.sess,
- e.span,
- E0571,
- "`break` with value from a `{}` loop",
- kind.name()
- );
- err.span_label(
- e.span,
- "can only break with a value inside `loop` or breakable block",
+ let suggestion = format!(
+ "break{}",
+ break_label
+ .label
+ .map_or_else(String::new, |l| format!(" {}", l.ident))
);
- if let Some(head) = head {
- err.span_label(
- head,
- &format!(
- "you can't `break` with a value in a `{}` loop",
- kind.name()
- ),
- );
- }
- err.span_suggestion(
- e.span,
- &format!(
- "use `break` on its own without a value inside this `{}` loop",
- kind.name(),
- ),
- format!(
- "break{}",
- break_label
- .label
- .map_or_else(String::new, |l| format!(" {}", l.ident))
- ),
- Applicability::MaybeIncorrect,
- );
- if let (Some(label), None) = (loop_label, break_label.label) {
- match break_expr.kind {
- hir::ExprKind::Path(hir::QPath::Resolved(
- None,
- hir::Path {
- segments: [segment],
- res: hir::def::Res::Err,
- ..
- },
- )) if label.ident.to_string()
- == format!("'{}", segment.ident) =>
- {
- // This error is redundant, we will have already emitted a
- // suggestion to use the label when `segment` wasn't found
- // (hence the `Res::Err` check).
- err.delay_as_bug();
- }
- _ => {
- err.span_suggestion(
- break_expr.span,
- "alternatively, you might have meant to use the \
- available loop label",
- label.ident,
- Applicability::MaybeIncorrect,
- );
- }
- }
- }
- err.emit();
+ self.sess.emit_err(BreakNonLoop {
+ span: e.span,
+ head,
+ kind: kind.name(),
+ suggestion,
+ loop_label,
+ break_label: break_label.label,
+ break_expr_kind: &break_expr.kind,
+ break_expr_span: break_expr.span,
+ });
}
}
}
@@ -191,19 +151,17 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
match destination.target_id {
Ok(loop_id) => {
if let Node::Block(block) = self.hir_map.find(loop_id).unwrap() {
- struct_span_err!(
- self.sess,
- e.span,
- E0696,
- "`continue` pointing to a labeled block"
- )
- .span_label(e.span, "labeled blocks cannot be `continue`'d")
- .span_label(block.span, "labeled block the `continue` points to")
- .emit();
+ self.sess.emit_err(ContinueLabeledBlock {
+ span: e.span,
+ block_span: block.span,
+ });
}
}
Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
- self.emit_unlabled_cf_in_while_condition(e.span, "continue");
+ self.sess.emit_err(UnlabeledCfInWhileCondition {
+ span: e.span,
+ cf_type: "continue",
+ });
}
Err(_) => {}
}
@@ -226,21 +184,16 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
}
fn require_break_cx(&self, name: &str, span: Span) {
- let err_inside_of = |article, ty, closure_span| {
- struct_span_err!(self.sess, span, E0267, "`{}` inside of {} {}", name, article, ty)
- .span_label(span, format!("cannot `{}` inside of {} {}", name, article, ty))
- .span_label(closure_span, &format!("enclosing {}", ty))
- .emit();
- };
-
match self.cx {
LabeledBlock | Loop(_) => {}
- Closure(closure_span) => err_inside_of("a", "closure", closure_span),
- AsyncClosure(closure_span) => err_inside_of("an", "`async` block", closure_span),
+ Closure(closure_span) => {
+ self.sess.emit_err(BreakInsideClosure { span, closure_span, name });
+ }
+ AsyncClosure(closure_span) => {
+ self.sess.emit_err(BreakInsideAsyncBlock { span, closure_span, name });
+ }
Normal | AnonConst => {
- struct_span_err!(self.sess, span, E0268, "`{}` outside of a loop", name)
- .span_label(span, format!("cannot `{}` outside of a loop", name))
- .emit();
+ self.sess.emit_err(OutsideLoop { span, name });
}
}
}
@@ -251,37 +204,13 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
label: &Destination,
cf_type: &str,
) -> bool {
- if !span.is_desugaring(DesugaringKind::QuestionMark) && self.cx == LabeledBlock {
- if label.label.is_none() {
- struct_span_err!(
- self.sess,
- span,
- E0695,
- "unlabeled `{}` inside of a labeled block",
- cf_type
- )
- .span_label(
- span,
- format!(
- "`{}` statements that would diverge to or through \
- a labeled block need to bear a label",
- cf_type
- ),
- )
- .emit();
- return true;
- }
+ if !span.is_desugaring(DesugaringKind::QuestionMark)
+ && self.cx == LabeledBlock
+ && label.label.is_none()
+ {
+ self.sess.emit_err(UnlabeledInLabeledBlock { span, cf_type });
+ return true;
}
false
}
- fn emit_unlabled_cf_in_while_condition(&mut self, span: Span, cf_type: &str) {
- struct_span_err!(
- self.sess,
- span,
- E0590,
- "`break` or `continue` with no label in the condition of a `while` loop"
- )
- .span_label(span, format!("unlabeled `{}` in the condition of a `while` loop", cf_type))
- .emit();
- }
}
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index 607973446..acc54e7e1 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -1,7 +1,6 @@
//! Checks validity of naked functions.
use rustc_ast::InlineAsmOptions;
-use rustc_errors::{struct_span_err, Applicability};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
@@ -14,6 +13,12 @@ use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
+use crate::errors::{
+ CannotInlineNakedFunction, NakedFunctionsAsmBlock, NakedFunctionsAsmOptions,
+ NakedFunctionsMustUseNoreturn, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed,
+ UndefinedNakedFunctionAbi,
+};
+
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { check_mod_naked_functions, ..*providers };
}
@@ -56,7 +61,7 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
fn check_inline(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let attrs = tcx.get_attrs(def_id.to_def_id(), sym::inline);
for attr in attrs {
- tcx.sess.struct_span_err(attr.span, "naked functions cannot be inlined").emit();
+ tcx.sess.emit_err(CannotInlineNakedFunction { span: attr.span });
}
}
@@ -65,9 +70,12 @@ fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: Abi) {
if abi == Abi::Rust {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let span = tcx.def_span(def_id);
- tcx.struct_span_lint_hir(UNDEFINED_NAKED_FUNCTION_ABI, hir_id, span, |lint| {
- lint.build("Rust ABI is unsupported in naked functions").emit();
- });
+ tcx.emit_spanned_lint(
+ UNDEFINED_NAKED_FUNCTION_ABI,
+ hir_id,
+ span,
+ UndefinedNakedFunctionAbi,
+ );
}
}
@@ -78,12 +86,7 @@ fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) {
hir::PatKind::Wild
| hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, _, None) => {}
_ => {
- tcx.sess
- .struct_span_err(
- param.pat.span,
- "patterns not allowed in naked function parameters",
- )
- .emit();
+ tcx.sess.emit_err(NoPatterns { span: param.pat.span });
}
}
}
@@ -113,14 +116,7 @@ impl<'tcx> Visitor<'tcx> for CheckParameters<'tcx> {
)) = expr.kind
{
if self.params.contains(var_hir_id) {
- self.tcx
- .sess
- .struct_span_err(
- expr.span,
- "referencing function parameters is not allowed in naked functions",
- )
- .help("follow the calling convention in asm block to use parameters")
- .emit();
+ self.tcx.sess.emit_err(ParamsNotAllowed { span: expr.span });
return;
}
}
@@ -135,26 +131,21 @@ fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<
if let [(ItemKind::Asm | ItemKind::Err, _)] = this.items[..] {
// Ok.
} else {
- let mut diag = struct_span_err!(
- tcx.sess,
- tcx.def_span(def_id),
- E0787,
- "naked functions must contain a single asm block"
- );
-
let mut must_show_error = false;
let mut has_asm = false;
let mut has_err = false;
+ let mut multiple_asms = vec![];
+ let mut non_asms = vec![];
for &(kind, span) in &this.items {
match kind {
ItemKind::Asm if has_asm => {
must_show_error = true;
- diag.span_label(span, "multiple asm blocks are unsupported in naked functions");
+ multiple_asms.push(span);
}
ItemKind::Asm => has_asm = true,
ItemKind::NonAsm => {
must_show_error = true;
- diag.span_label(span, "non-asm is unsupported in naked functions");
+ non_asms.push(span);
}
ItemKind::Err => has_err = true,
}
@@ -164,9 +155,11 @@ fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<
// errors, then don't show an additional error. This allows for appending/prepending
// `compile_error!("...")` statements and reduces error noise.
if must_show_error || !has_err {
- diag.emit();
- } else {
- diag.cancel();
+ tcx.sess.emit_err(NakedFunctionsAsmBlock {
+ span: tcx.def_span(def_id),
+ multiple_asms,
+ non_asms,
+ });
}
}
}
@@ -247,13 +240,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
})
.collect();
if !unsupported_operands.is_empty() {
- struct_span_err!(
- self.tcx.sess,
- unsupported_operands,
- E0787,
- "only `const` and `sym` operands are supported in naked functions",
- )
- .emit();
+ self.tcx.sess.emit_err(NakedFunctionsOperands { unsupported_operands });
}
let unsupported_options: Vec<&'static str> = [
@@ -269,14 +256,10 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
.collect();
if !unsupported_options.is_empty() {
- struct_span_err!(
- self.tcx.sess,
+ self.tcx.sess.emit_err(NakedFunctionsAsmOptions {
span,
- E0787,
- "asm options unsupported in naked functions: {}",
- unsupported_options.join(", ")
- )
- .emit();
+ unsupported_options: unsupported_options.join(", "),
+ });
}
if !asm.options.contains(InlineAsmOptions::NORETURN) {
@@ -286,20 +269,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
.map_or_else(|| asm.template_strs.last().unwrap().2, |op| op.1)
.shrink_to_hi();
- struct_span_err!(
- self.tcx.sess,
- span,
- E0787,
- "asm in naked functions must use `noreturn` option"
- )
- .span_suggestion(
- last_span,
- "consider specifying that the asm block is responsible \
- for returning from the function",
- ", options(noreturn)",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.tcx.sess.emit_err(NakedFunctionsMustUseNoreturn { span, last_span });
}
}
}
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index f7e3fac6b..50070869a 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -12,7 +12,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::Node;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
-use rustc_middle::middle::privacy;
+use rustc_middle::middle::privacy::{self, Level};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_session::config::CrateType;
@@ -29,7 +29,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'_>, item: &hir::Item<'_>, attrs: &CodegenF
match item.kind {
hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => true,
hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => {
- let generics = tcx.generics_of(item.def_id);
+ let generics = tcx.generics_of(item.owner_id);
generics.requires_monomorphization(tcx)
}
_ => false,
@@ -42,7 +42,7 @@ fn method_might_be_inlined(
impl_src: LocalDefId,
) -> bool {
let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id().owner.to_def_id());
- let generics = tcx.generics_of(impl_item.def_id);
+ let generics = tcx.generics_of(impl_item.owner_id);
if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) {
return true;
}
@@ -116,6 +116,17 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
intravisit::walk_expr(self, expr)
}
+
+ fn visit_inline_asm(&mut self, asm: &'tcx hir::InlineAsm<'tcx>, id: hir::HirId) {
+ for (op, _) in asm.operands {
+ if let hir::InlineAsmOperand::SymStatic { def_id, .. } = op {
+ if let Some(def_id) = def_id.as_local() {
+ self.reachable_symbols.insert(def_id);
+ }
+ }
+ }
+ intravisit::walk_inline_asm(self, asm, id);
+ }
}
impl<'tcx> ReachableContext<'tcx> {
@@ -153,9 +164,9 @@ impl<'tcx> ReachableContext<'tcx> {
hir::ImplItemKind::Fn(..) => {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let impl_did = self.tcx.hir().get_parent_item(hir_id);
- method_might_be_inlined(self.tcx, impl_item, impl_did)
+ method_might_be_inlined(self.tcx, impl_item, impl_did.def_id)
}
- hir::ImplItemKind::TyAlias(_) => false,
+ hir::ImplItemKind::Type(_) => false,
},
Some(_) => false,
None => false, // This will happen for default methods.
@@ -216,7 +227,7 @@ impl<'tcx> ReachableContext<'tcx> {
if item_might_be_inlined(
self.tcx,
&item,
- self.tcx.codegen_fn_attrs(item.def_id),
+ self.tcx.codegen_fn_attrs(item.owner_id),
) {
self.visit_nested_body(body);
}
@@ -271,7 +282,7 @@ impl<'tcx> ReachableContext<'tcx> {
self.visit_nested_body(body)
}
}
- hir::ImplItemKind::TyAlias(_) => {}
+ hir::ImplItemKind::Type(_) => {}
},
Node::Expr(&hir::Expr {
kind: hir::ExprKind::Closure(&hir::Closure { body, .. }),
@@ -303,13 +314,13 @@ fn check_item<'tcx>(
tcx: TyCtxt<'tcx>,
id: hir::ItemId,
worklist: &mut Vec<LocalDefId>,
- access_levels: &privacy::AccessLevels,
+ effective_visibilities: &privacy::EffectiveVisibilities,
) {
- if has_custom_linkage(tcx, id.def_id) {
- worklist.push(id.def_id);
+ if has_custom_linkage(tcx, id.owner_id.def_id) {
+ worklist.push(id.owner_id.def_id);
}
- if !matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
+ if !matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
return;
}
@@ -318,8 +329,8 @@ fn check_item<'tcx>(
if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) =
item.kind
{
- if !access_levels.is_reachable(item.def_id) {
- worklist.extend(items.iter().map(|ii_ref| ii_ref.id.def_id));
+ if !effective_visibilities.is_reachable(item.owner_id.def_id) {
+ worklist.extend(items.iter().map(|ii_ref| ii_ref.id.owner_id.def_id));
let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res else {
unreachable!();
@@ -354,7 +365,7 @@ fn has_custom_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
}
fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> {
- let access_levels = &tcx.privacy_access_levels(());
+ let effective_visibilities = &tcx.effective_visibilities(());
let any_library =
tcx.sess.crate_types().iter().any(|ty| {
@@ -373,7 +384,13 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> {
// If other crates link to us, they're going to expect to be able to
// use the lang items, so we need to be sure to mark them as
// exported.
- reachable_context.worklist.extend(access_levels.map.keys());
+ reachable_context.worklist = effective_visibilities
+ .iter()
+ .filter_map(|(&id, effective_vis)| {
+ effective_vis.is_public_at_level(Level::ReachableThroughImplTrait).then_some(id)
+ })
+ .collect::<Vec<_>>();
+
for item in tcx.lang_items().items().iter() {
if let Some(def_id) = *item {
if let Some(def_id) = def_id.as_local() {
@@ -393,12 +410,12 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> {
let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
- check_item(tcx, id, &mut reachable_context.worklist, access_levels);
+ check_item(tcx, id, &mut reachable_context.worklist, effective_visibilities);
}
for id in crate_items.impl_items() {
- if has_custom_linkage(tcx, id.def_id) {
- reachable_context.worklist.push(id.def_id);
+ if has_custom_linkage(tcx, id.owner_id.def_id) {
+ reachable_context.worklist.push(id.owner_id.def_id);
}
}
}
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 9ba127609..78afa2f25 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -1,12 +1,18 @@
//! 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 rustc_attr::{
self as attr, rust_version_symbol, ConstStability, Stability, StabilityLevel, Unstable,
UnstableReason, VERSION_PLACEHOLDER,
};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
-use rustc_errors::{struct_span_err, Applicability};
+use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
@@ -14,12 +20,11 @@ use rustc_hir::hir_id::CRATE_HIR_ID;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::privacy::AccessLevels;
+use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
use rustc_middle::ty::{query::Providers, TyCtxt};
use rustc_session::lint;
use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
-use rustc_session::Session;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
@@ -122,16 +127,12 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if kind == AnnotationKind::Prohibited || kind == AnnotationKind::DeprecationProhibited {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
- self.tcx.struct_span_lint_hir(USELESS_DEPRECATED, hir_id, *span, |lint| {
- lint.build("this `#[deprecated]` annotation has no effect")
- .span_suggestion_short(
- *span,
- "remove the unnecessary deprecation attribute",
- "",
- rustc_errors::Applicability::MachineApplicable,
- )
- .emit();
- });
+ self.tcx.emit_spanned_lint(
+ USELESS_DEPRECATED,
+ hir_id,
+ *span,
+ errors::DeprecatedAnnotationHasNoEffect { span: *span },
+ );
}
// `Deprecation` is just two pointers, no need to intern it
@@ -182,7 +183,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if !self.in_trait_impl
|| (self.in_trait_impl && !self.tcx.is_const_fn_raw(def_id.to_def_id()))
{
- missing_const_err(&self.tcx.sess, fn_sig.span, const_span);
+ self.tcx
+ .sess
+ .emit_err(MissingConstErr { fn_sig_span: fn_sig.span, const_span });
}
}
}
@@ -200,14 +203,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if let Some((rustc_attr::Deprecation { is_since_rustc_version: true, .. }, span)) = &depr {
if stab.is_none() {
- struct_span_err!(
- self.tcx.sess,
- *span,
- E0549,
- "deprecated attribute must be paired with \
- either stable or unstable attribute"
- )
- .emit();
+ self.tcx.sess.emit_err(DeprecatedAttribute { span: *span });
}
}
@@ -223,10 +219,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if kind == AnnotationKind::Prohibited
|| (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated)
{
- self.tcx.sess.struct_span_err(span,"this stability annotation is useless")
- .span_label(span, "useless stability annotation")
- .span_label(item_sp, "the stability attribute annotates this item")
- .emit();
+ self.tcx.sess.emit_err(UselessStability { span, item_sp });
}
debug!("annotate: found {:?}", stab);
@@ -242,19 +235,15 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
{
match stab_v.parse::<u64>() {
Err(_) => {
- self.tcx.sess.struct_span_err(span, "invalid stability version found")
- .span_label(span, "invalid stability version")
- .span_label(item_sp, "the stability attribute annotates this item")
- .emit();
+ self.tcx.sess.emit_err(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.struct_span_err(span, "an API can't be stabilized after it is deprecated")
- .span_label(span, "invalid version")
- .span_label(item_sp, "the stability attribute annotates this item")
- .emit();
+ self.tcx
+ .sess
+ .emit_err(CannotStabilizeDeprecated { span, item_sp });
break;
}
Ordering::Equal => continue,
@@ -262,10 +251,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
},
Err(_) => {
if dep_v != "TBD" {
- self.tcx.sess.struct_span_err(span, "invalid deprecation version found")
- .span_label(span, "invalid deprecation version")
- .span_label(item_sp, "the stability attribute annotates this item")
- .emit();
+ self.tcx
+ .sess
+ .emit_err(InvalidDeprecationVersion { span, item_sp });
}
break;
}
@@ -274,7 +262,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
}
}
- if let Stability { level: Unstable { implied_by: Some(implied_by), .. }, feature } = stab {
+ if let Stability { level: Unstable { implied_by: Some(implied_by), .. }, feature } =
+ stab
+ {
self.index.implications.insert(implied_by, feature);
}
@@ -388,7 +378,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
}
self.annotate(
- i.def_id,
+ i.owner_id.def_id,
i.span,
fn_sig,
kind,
@@ -407,7 +397,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
};
self.annotate(
- ti.def_id,
+ ti.owner_id.def_id,
ti.span,
fn_sig,
AnnotationKind::Required,
@@ -430,7 +420,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
};
self.annotate(
- ii.def_id,
+ ii.owner_id.def_id,
ii.span,
fn_sig,
kind,
@@ -488,7 +478,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
self.annotate(
- i.def_id,
+ i.owner_id.def_id,
i.span,
None,
AnnotationKind::Required,
@@ -526,15 +516,18 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
struct MissingStabilityAnnotations<'tcx> {
tcx: TyCtxt<'tcx>,
- access_levels: &'tcx AccessLevels,
+ effective_visibilities: &'tcx EffectiveVisibilities,
}
impl<'tcx> MissingStabilityAnnotations<'tcx> {
fn check_missing_stability(&self, def_id: LocalDefId, span: Span) {
let stab = self.tcx.stability().local_stability(def_id);
- if !self.tcx.sess.opts.test && stab.is_none() && self.access_levels.is_reachable(def_id) {
+ if !self.tcx.sess.opts.test
+ && 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.span_err(span, &format!("{} has missing stability attribute", descr));
+ self.tcx.sess.emit_err(MissingStabilityAttr { span, descr });
}
}
@@ -550,11 +543,11 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
.lookup_stability(def_id)
.map_or(false, |stability| stability.level.is_stable());
let missing_const_stability_attribute = self.tcx.lookup_const_stability(def_id).is_none();
- let is_reachable = self.access_levels.is_reachable(def_id);
+ 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.span_err(span, &format!("{descr} has missing const stability attribute"));
+ self.tcx.sess.emit_err(MissingConstStabAttr { span, descr });
}
}
}
@@ -576,25 +569,25 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
hir::ItemKind::Impl(hir::Impl { of_trait: None, .. })
| hir::ItemKind::ForeignMod { .. }
) {
- self.check_missing_stability(i.def_id, i.span);
+ self.check_missing_stability(i.owner_id.def_id, i.span);
}
// Ensure stable `const fn` have a const stability attribute.
- self.check_missing_const_stability(i.def_id, i.span);
+ self.check_missing_const_stability(i.owner_id.def_id, i.span);
intravisit::walk_item(self, i)
}
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
- self.check_missing_stability(ti.def_id, ti.span);
+ self.check_missing_stability(ti.owner_id.def_id, ti.span);
intravisit::walk_trait_item(self, ti);
}
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id());
if self.tcx.impl_trait_ref(impl_def_id).is_none() {
- self.check_missing_stability(ii.def_id, ii.span);
- self.check_missing_const_stability(ii.def_id, ii.span);
+ self.check_missing_stability(ii.owner_id.def_id, ii.span);
+ self.check_missing_const_stability(ii.owner_id.def_id, ii.span);
}
intravisit::walk_impl_item(self, ii);
}
@@ -613,7 +606,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
}
fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
- self.check_missing_stability(i.def_id, i.span);
+ self.check_missing_stability(i.owner_id.def_id, i.span);
intravisit::walk_foreign_item(self, i);
}
// Note that we don't need to `check_missing_stability` for default generic parameters,
@@ -719,7 +712,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
return;
}
- let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.def_id) else {
+ let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.owner_id.def_id) else {
return;
};
let def_id = cnum.as_def_id();
@@ -755,10 +748,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
item.hir_id(),
span,
- |lint| {lint
- .build("an `#[unstable]` annotation here has no effect")
- .note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information")
- .emit();}
+ "an `#[unstable]` annotation here has no effect",
+ |lint| lint.note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information")
);
}
}
@@ -769,16 +760,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
&& *constness == hir::Constness::Const
&& const_stab.map_or(false, |(stab, _)| stab.is_const_stable())
{
- self.tcx
- .sess
- .struct_span_err(item.span, "trait implementations cannot be const stable yet")
- .note("see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information")
- .emit();
+ self.tcx.sess.emit_err(TraitImplConstStable { span: item.span });
}
}
for impl_item_ref in *items {
- let impl_item = self.tcx.associated_item(impl_item_ref.id.def_id);
+ let impl_item = self.tcx.associated_item(impl_item_ref.id.owner_id);
if let Some(def_id) = impl_item.trait_item_def_id {
// Pass `None` to skip deprecation warnings.
@@ -872,7 +859,7 @@ fn is_unstable_reexport<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId) -> bool {
}
// If this is a path that isn't a use, we don't need to do anything special
- if !matches!(tcx.hir().item(hir::ItemId { def_id }).kind, ItemKind::Use(..)) {
+ if !matches!(tcx.hir().expect_item(def_id).kind, ItemKind::Use(..)) {
return false;
}
@@ -907,8 +894,25 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> {
if let TyKind::Never = t.kind {
self.fully_stable = false;
}
+ if let TyKind::BareFn(f) = t.kind {
+ if rustc_target::spec::abi::is_stable(f.abi.name()).is_err() {
+ self.fully_stable = false;
+ }
+ }
intravisit::walk_ty(self, t)
}
+
+ fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl<'tcx>) {
+ for ty in fd.inputs {
+ self.visit_ty(ty)
+ }
+ if let hir::FnRetTy::Return(output_ty) = fd.output {
+ match output_ty.kind {
+ TyKind::Never => {} // `-> !` is stable
+ _ => self.visit_ty(output_ty),
+ }
+ }
+ }
}
/// Given the list of enabled features that were not language features (i.e., that
@@ -918,8 +922,8 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
let is_staged_api =
tcx.sess.opts.unstable_opts.force_unstable_if_unmarked || tcx.features().staged_api;
if is_staged_api {
- let access_levels = &tcx.privacy_access_levels(());
- let mut missing = MissingStabilityAnnotations { tcx, access_levels };
+ let effective_visibilities = &tcx.effective_visibilities(());
+ let mut missing = MissingStabilityAnnotations { tcx, effective_visibilities };
missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID));
tcx.hir().walk_toplevel_module(&mut missing);
tcx.hir().visit_all_item_likes_in_crate(&mut missing);
@@ -934,7 +938,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.
- duplicate_feature_err(tcx.sess, span, feature);
+ tcx.sess.emit_err(DuplicateFeatureErr { span, feature });
}
}
@@ -942,18 +946,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() {
- struct_span_err!(
- tcx.sess,
- *span,
- E0554,
- "`#![feature]` may not be used on the {} release channel",
- env!("CFG_RELEASE_CHANNEL")
- )
- .emit();
+ tcx.sess.emit_err(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.
- duplicate_feature_err(tcx.sess, *span, *feature);
+ tcx.sess.emit_err(DuplicateFeatureErr { span: *span, feature: *feature });
}
remaining_lib_features.insert(feature, *span);
}
@@ -1054,23 +1054,18 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
}
for (feature, span) in remaining_lib_features {
- struct_span_err!(tcx.sess, span, E0635, "unknown feature `{}`", feature).emit();
+ tcx.sess.emit_err(UnknownFeature { span, feature: *feature });
}
for (implied_by, feature) in remaining_implications {
let local_defined_features = tcx.lib_features(());
- let span = local_defined_features
+ let span = *local_defined_features
.stable
.get(&feature)
.map(|(_, span)| span)
.or_else(|| local_defined_features.unstable.get(&feature))
.expect("feature that implied another does not exist");
- tcx.sess
- .struct_span_err(
- *span,
- format!("feature `{implied_by}` implying `{feature}` does not exist"),
- )
- .emit();
+ tcx.sess.emit_err(ImpliedFeatureNotExist { span, feature, implied_by });
}
// FIXME(#44232): the `used_features` table no longer exists, so we
@@ -1084,27 +1079,31 @@ fn unnecessary_partially_stable_feature_lint(
implies: Symbol,
since: Symbol,
) {
- tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| {
- lint.build(&format!(
+ tcx.struct_span_lint_hir(
+ lint::builtin::STABLE_FEATURES,
+ hir::CRATE_HIR_ID,
+ span,
+ format!(
"the feature `{feature}` has been partially stabilized since {since} and is succeeded \
by the feature `{implies}`"
- ))
- .span_suggestion(
- span,
- &format!(
+ ),
+ |lint| {
+ lint.span_suggestion(
+ span,
+ &format!(
"if you are using features which are still unstable, change to using `{implies}`"
),
- implies,
- Applicability::MaybeIncorrect,
- )
- .span_suggestion(
- tcx.sess.source_map().span_extend_to_line(span),
- "if you are using features which are now stable, remove this line",
- "",
- Applicability::MaybeIncorrect,
- )
- .emit();
- });
+ implies,
+ Applicability::MaybeIncorrect,
+ )
+ .span_suggestion(
+ tcx.sess.source_map().span_extend_to_line(span),
+ "if you are using features which are now stable, remove this line",
+ "",
+ Applicability::MaybeIncorrect,
+ )
+ },
+ );
}
fn unnecessary_stable_feature_lint(
@@ -1116,28 +1115,7 @@ fn unnecessary_stable_feature_lint(
if since.as_str() == VERSION_PLACEHOLDER {
since = rust_version_symbol();
}
- tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| {
- lint.build(&format!(
- "the feature `{feature}` has been stable since {since} and no longer requires an \
- attribute to enable",
- ))
- .emit();
+ tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, format!("the feature `{feature}` has been stable since {since} and no longer requires an attribute to enable"), |lint| {
+ lint
});
}
-
-fn duplicate_feature_err(sess: &Session, span: Span, feature: Symbol) {
- struct_span_err!(sess, span, E0636, "the feature `{}` has already been declared", feature)
- .emit();
-}
-
-fn missing_const_err(session: &Session, fn_sig_span: Span, const_span: Span) {
- const ERROR_MSG: &'static str = "attributes `#[rustc_const_unstable]` \
- and `#[rustc_const_stable]` require \
- the function or method to be `const`";
-
- session
- .struct_span_err(fn_sig_span, ERROR_MSG)
- .span_help(fn_sig_span, "make the function or method const")
- .span_label(const_span, "attribute specified here")
- .emit();
-}
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index c48b4ecf8..959ee600c 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -1,13 +1,17 @@
//! Validity checking for weak lang items
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::struct_span_err;
use rustc_hir::lang_items::{self, LangItem};
use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS;
use rustc_middle::middle::lang_items::required;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::CrateType;
+use crate::errors::{
+ AllocFuncRequired, MissingAllocErrorHandler, MissingLangItem, MissingPanicHandler,
+ UnknownExternLangItem,
+};
+
/// Checks the crate for usage of weak lang items, returning a vector of all the
/// language items required by this crate, but not defined yet.
pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItems) {
@@ -30,15 +34,8 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
items.missing.push(item);
}
} else {
- let span = tcx.def_span(id.def_id);
- struct_span_err!(
- tcx.sess,
- span,
- E0264,
- "unknown external lang item: `{}`",
- lang_item
- )
- .emit();
+ let span = tcx.def_span(id.owner_id);
+ tcx.sess.emit_err(UnknownExternLangItem { span, lang_item });
}
}
}
@@ -71,20 +68,14 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
for (name, &item) in WEAK_ITEMS_REFS.iter() {
if missing.contains(&item) && required(tcx, item) && items.require(item).is_err() {
if item == LangItem::PanicImpl {
- tcx.sess.err("`#[panic_handler]` function required, but not found");
+ tcx.sess.emit_err(MissingPanicHandler);
} else if item == LangItem::Oom {
if !tcx.features().default_alloc_error_handler {
- tcx.sess.err("`#[alloc_error_handler]` function required, but not found");
- tcx.sess.note_without_error("use `#![feature(default_alloc_error_handler)]` for a default error handler");
+ tcx.sess.emit_err(AllocFuncRequired);
+ tcx.sess.emit_note(MissingAllocErrorHandler);
}
} else {
- tcx
- .sess
- .diagnostic()
- .struct_err(&format!("language item required, but not found: `{}`", name))
- .note(&format!("this can occur when a binary crate with `#![no_std]` is compiled for a target where `{}` is defined in the standard library", name))
- .help(&format!("you may be able to compile for a target that doesn't need `{}`, specify a target with `--target` or in `.cargo/config`", name))
- .emit();
+ tcx.sess.emit_err(MissingLangItem { name: *name });
}
}
}