diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index a57f398784916..1d7965ff5f66e 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -189,3 +189,39 @@ hir_analysis_return_type_notation_equality_bound =
hir_analysis_return_type_notation_missing_method =
cannot find associated function `{$assoc_name}` in trait `{$trait_name}`
+
+hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
+ .label = not allowed in type signatures
+
+hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
+ .suggestion = use a fully qualified path with inferred lifetimes
+
+hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
+
+hir_analysis_enum_discriminant_overflowed = enum discriminant overflowed
+ .label = overflowed on value after {$discr}
+ .note = explicitly set `{$item_name} = {$wrapped_discr}` if that is desired outcome
+
+hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
+ .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
+
+hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
+
+hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
+
+hir_analysis_function_not_have_default_implementation = function doesn't have a default implementation
+ .note = required by this annotation
+
+hir_analysis_must_implement_not_function = not a function
+
+hir_analysis_must_implement_not_function_span_note = required by this annotation
+
+hir_analysis_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` arguments must be associated function names
+
+hir_analysis_function_not_found_in_trait = function not found in this trait
+
+hir_analysis_functions_names_duplicated = functions names are duplicated
+ .note = all `#[rustc_must_implement_one_of]` arguments must be unique
+
+hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is highly experimental and may result in invalid code
+ .help = add `#![feature(simd_ffi)]` to the crate attributes to enable
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index c41e96290df16..50862e3426238 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -20,7 +20,7 @@ use crate::errors;
use hir::def::DefKind;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
+use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
@@ -333,17 +333,7 @@ fn bad_placeholder<'tcx>(
let kind = if kind.ends_with('s') { format!("{}es", kind) } else { format!("{}s", kind) };
spans.sort();
- let mut err = struct_span_err!(
- tcx.sess,
- spans.clone(),
- E0121,
- "the placeholder `_` is not allowed within types on item signatures for {}",
- kind
- );
- for span in spans {
- err.span_label(span, "not allowed in type signatures");
- }
- err
+ tcx.sess.create_err(errors::PlaceholderNotAllowedItemSignatures { spans, kind })
}
impl<'tcx> ItemCtxt<'tcx> {
@@ -419,13 +409,8 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
self.tcx().mk_projection(item_def_id, item_substs)
} else {
// There are no late-bound regions; we can just ignore the binder.
- let mut err = struct_span_err!(
- self.tcx().sess,
- span,
- E0212,
- "cannot use the associated type of a trait \
- with uninferred generic parameters"
- );
+ let (mut mpart_sugg, mut inferred_sugg) = (None, None);
+ let mut bound = String::new();
match self.node() {
hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
@@ -444,31 +429,25 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
(bound.span.shrink_to_lo(), format!("{}, ", lt_name))
}
};
- let suggestions = vec![
- (lt_sp, sugg),
- (
- span.with_hi(item_segment.ident.span.lo()),
- format!(
- "{}::",
- // Replace the existing lifetimes with a new named lifetime.
- self.tcx.replace_late_bound_regions_uncached(
- poly_trait_ref,
- |_| {
- self.tcx.mk_re_early_bound(ty::EarlyBoundRegion {
- def_id: item_def_id,
- index: 0,
- name: Symbol::intern(<_name),
- })
- }
- ),
+ mpart_sugg = Some(errors::AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
+ fspan: lt_sp,
+ first: sugg,
+ sspan: span.with_hi(item_segment.ident.span.lo()),
+ second: format!(
+ "{}::",
+ // Replace the existing lifetimes with a new named lifetime.
+ self.tcx.replace_late_bound_regions_uncached(
+ poly_trait_ref,
+ |_| {
+ self.tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+ def_id: item_def_id,
+ index: 0,
+ name: Symbol::intern(<_name),
+ })
+ }
),
),
- ];
- err.multipart_suggestion(
- "use a fully qualified path with explicit lifetimes",
- suggestions,
- Applicability::MaybeIncorrect,
- );
+ });
}
_ => {}
}
@@ -482,20 +461,23 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
| hir::Node::ForeignItem(_)
| hir::Node::TraitItem(_)
| hir::Node::ImplItem(_) => {
- err.span_suggestion_verbose(
- span.with_hi(item_segment.ident.span.lo()),
- "use a fully qualified path with inferred lifetimes",
- format!(
- "{}::",
- // Erase named lt, we want `::C`, not `::C`.
- self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
- ),
- Applicability::MaybeIncorrect,
+ inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo()));
+ bound = format!(
+ "{}::",
+ // Erase named lt, we want `::C`, not `::C`.
+ self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
);
}
_ => {}
}
- self.tcx().ty_error(err.emit())
+ self.tcx().ty_error(self.tcx().sess.emit_err(
+ errors::AssociatedTypeTraitUninferredGenericParams {
+ span,
+ inferred_sugg,
+ bound,
+ mpart_sugg,
+ },
+ ))
}
}
@@ -763,14 +745,12 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
Some(discr)
} else {
let span = tcx.def_span(variant.def_id);
- struct_span_err!(tcx.sess, span, E0370, "enum discriminant overflowed")
- .span_label(span, format!("overflowed on value after {}", prev_discr.unwrap()))
- .note(&format!(
- "explicitly set `{} = {}` if that is desired outcome",
- tcx.item_name(variant.def_id),
- wrapped_discr
- ))
- .emit();
+ tcx.sess.emit_err(errors::EnumDiscriminantOverflowed {
+ span,
+ discr: prev_discr.unwrap().to_string(),
+ item_name: tcx.item_name(variant.def_id),
+ wrapped_discr: wrapped_discr.to_string(),
+ });
None
}
.unwrap_or(wrapped_discr),
@@ -915,14 +895,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
if paren_sugar && !tcx.features().unboxed_closures {
- tcx.sess
- .struct_span_err(
- item.span,
- "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
- which traits can use parenthetical notation",
- )
- .help("add `#![feature(unboxed_closures)]` to the crate attributes to use it")
- .emit();
+ tcx.sess.emit_err(errors::ParenSugarAttribute { span: item.span });
}
let is_marker = tcx.has_attr(def_id, sym::marker);
@@ -942,13 +915,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
// and that they are all identifiers
.and_then(|attr| match attr.meta_item_list() {
Some(items) if items.len() < 2 => {
- tcx.sess
- .struct_span_err(
- attr.span,
- "the `#[rustc_must_implement_one_of]` attribute must be \
- used with at least 2 args",
- )
- .emit();
+ tcx.sess.emit_err(errors::MustImplementOneOfAttribute { span: attr.span });
None
}
@@ -957,9 +924,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
.map(|item| item.ident().ok_or(item.span()))
.collect::, _>>()
.map_err(|span| {
- tcx.sess
- .struct_span_err(span, "must be a name of an associated function")
- .emit();
+ tcx.sess.emit_err(errors::MustBeNameOfAssociatedFunction { span });
})
.ok()
.zip(Some(attr.span)),
@@ -975,13 +940,10 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
match item {
Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => {
if !tcx.impl_defaultness(item.id.owner_id).has_value() {
- tcx.sess
- .struct_span_err(
- item.span,
- "function doesn't have a default implementation",
- )
- .span_note(attr_span, "required by this annotation")
- .emit();
+ tcx.sess.emit_err(errors::FunctionNotHaveDefaultImplementation {
+ span: item.span,
+ note_span: attr_span,
+ });
return Some(());
}
@@ -989,19 +951,14 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
return None;
}
Some(item) => {
- tcx.sess
- .struct_span_err(item.span, "not a function")
- .span_note(attr_span, "required by this annotation")
- .note(
- "all `#[rustc_must_implement_one_of]` arguments must be associated \
- function names",
- )
- .emit();
+ tcx.sess.emit_err(errors::MustImplementNotFunction {
+ span: item.span,
+ span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span },
+ note: errors::MustImplementNotFunctionNote {},
+ });
}
None => {
- tcx.sess
- .struct_span_err(ident.span, "function not found in this trait")
- .emit();
+ tcx.sess.emit_err(errors::FunctionNotFoundInTrait { span: ident.span });
}
}
@@ -1018,9 +975,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
for ident in &*list {
if let Some(dup) = set.insert(ident.name, ident.span) {
tcx.sess
- .struct_span_err(vec![dup, ident.span], "functions names are duplicated")
- .note("all `#[rustc_must_implement_one_of]` arguments must be unique")
- .emit();
+ .emit_err(errors::FunctionNamesDuplicated { spans: vec![dup, ident.span] });
no_dups = false;
}
@@ -1485,17 +1440,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
.source_map()
.span_to_snippet(ast_ty.span)
.map_or_else(|_| String::new(), |s| format!(" `{}`", s));
- tcx.sess
- .struct_span_err(
- ast_ty.span,
- &format!(
- "use of SIMD type{} in FFI is highly experimental and \
- may result in invalid code",
- snip
- ),
- )
- .help("add `#![feature(simd_ffi)]` to the crate attributes to enable")
- .emit();
+ tcx.sess.emit_err(errors::SIMDFFIHighlyExperimental { span: ast_ty.span, snip });
}
};
for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index c71ce9a0bc7cd..2a3a683489ddd 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -507,3 +507,127 @@ pub(crate) struct ReturnTypeNotationMissingMethod {
pub trait_name: Symbol,
pub assoc_name: Symbol,
}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")]
+pub(crate) struct PlaceholderNotAllowedItemSignatures {
+ #[primary_span]
+ #[label]
+ pub spans: Vec,
+ pub kind: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = "E0212")]
+pub(crate) struct AssociatedTypeTraitUninferredGenericParams {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "{bound}")]
+ pub inferred_sugg: Option,
+ pub bound: String,
+ #[subdiagnostic]
+ pub mpart_sugg: Option,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+ hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion,
+ applicability = "maybe-incorrect"
+)]
+pub(crate) struct AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
+ #[suggestion_part(code = "{first}")]
+ pub fspan: Span,
+ pub first: String,
+ #[suggestion_part(code = "{second}")]
+ pub sspan: Span,
+ pub second: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_enum_discriminant_overflowed, code = "E0370")]
+#[note]
+pub(crate) struct EnumDiscriminantOverflowed {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub discr: String,
+ pub item_name: Symbol,
+ pub wrapped_discr: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_paren_sugar_attribute)]
+#[help]
+pub(crate) struct ParenSugarAttribute {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_must_implement_one_of_attribute)]
+pub(crate) struct MustImplementOneOfAttribute {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_must_be_name_of_associated_function)]
+pub(crate) struct MustBeNameOfAssociatedFunction {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_function_not_have_default_implementation)]
+pub(crate) struct FunctionNotHaveDefaultImplementation {
+ #[primary_span]
+ pub span: Span,
+ #[note]
+ pub note_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_must_implement_not_function)]
+pub(crate) struct MustImplementNotFunction {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub span_note: MustImplementNotFunctionSpanNote,
+ #[subdiagnostic]
+ pub note: MustImplementNotFunctionNote,
+}
+
+#[derive(Subdiagnostic)]
+#[note(hir_analysis_must_implement_not_function_span_note)]
+pub(crate) struct MustImplementNotFunctionSpanNote {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[note(hir_analysis_must_implement_not_function_note)]
+pub(crate) struct MustImplementNotFunctionNote {}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_function_not_found_in_trait)]
+pub(crate) struct FunctionNotFoundInTrait {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_functions_names_duplicated)]
+#[note]
+pub(crate) struct FunctionNamesDuplicated {
+ #[primary_span]
+ pub spans: Vec,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_simd_ffi_highly_experimental)]
+#[help]
+pub(crate) struct SIMDFFIHighlyExperimental {
+ #[primary_span]
+ pub span: Span,
+ pub snip: String,
+}