diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 5560d087e96f0..47d5976be09ef 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -387,6 +387,8 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args +hir_analysis_no_variant_named = no variant named `{$ident}` found for enum `{$ty}` + hir_analysis_not_supported_delegation = {$descr} .label = callee defined here diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 14ea10461cbea..1a0b0edb25703 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1417,6 +1417,15 @@ pub(crate) struct CrossCrateTraitsDefined { pub traits: String, } +#[derive(Diagnostic)] +#[diag(hir_analysis_no_variant_named, code = E0599)] +pub struct NoVariantNamed<'tcx> { + #[primary_span] + pub span: Span, + pub ident: Ident, + pub ty: Ty<'tcx>, +} + // FIXME(fmease): Deduplicate: #[derive(Diagnostic)] diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index ec8343bb2bfe6..e9b99caf737b4 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -53,7 +53,9 @@ use rustc_type_ir::Upcast; use tracing::{debug, instrument}; use crate::check::check_abi_fn_ptr; -use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType}; +use crate::errors::{ + AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, NoVariantNamed, +}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; use crate::middle::resolve_bound_vars as rbv; @@ -1205,14 +1207,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let msg = format!("expected type, found variant `{assoc_ident}`"); self.dcx().span_err(span, msg) } else if qself_ty.is_enum() { - let mut err = struct_span_code_err!( - self.dcx(), - assoc_ident.span, - E0599, - "no variant named `{}` found for enum `{}`", - assoc_ident, - qself_ty, - ); + let mut err = self.dcx().create_err(NoVariantNamed { + span: assoc_ident.span, + ident: assoc_ident, + ty: qself_ty, + }); let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT"); if let Some(variant_name) = find_best_match_for_name( diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 66d7c9377edd8..0859a39b15566 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -92,6 +92,7 @@ mod impl_wf_check; mod outlives; mod variance; +pub use errors::NoVariantNamed; use rustc_abi::ExternAbi; use rustc_hir as hir; use rustc_hir::def::DefKind; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b46d7c4906390..1c63b8b365594 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -19,6 +19,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, HirId, QPath}; +use rustc_hir_analysis::NoVariantNamed; use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _}; use rustc_infer::infer; use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; @@ -3837,15 +3838,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter_enumerated() .find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident) else { - type_error_struct!( - self.dcx(), - ident.span, - container, - E0599, - "no variant named `{ident}` found for enum `{container}`", - ) - .with_span_label(field.span, "variant not found") - .emit(); + self.dcx() + .create_err(NoVariantNamed { span: ident.span, ident, ty: container }) + .with_span_label(field.span, "variant not found") + .emit_unless(container.references_error()); break; }; let Some(&subfield) = fields.next() else {