diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 58f4e07e944..8dbf01e9735 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -36,7 +36,9 @@ //! ``` use crate::FnCtxt; -use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{ + struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, +}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; @@ -1738,7 +1740,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { // label pointing out the cause for the type coercion will be wrong // as prior return coercions would not be relevant (#57664). let fn_decl = if let (Some(expr), Some(blk_id)) = (expression, blk_id) { - self.explain_self_literal(fcx, &mut err, expr); + self.explain_self_literal(fcx, &mut err, expr, expected, found); let pointing_at_return_type = fcx.suggest_mismatched_types_on_tail(&mut err, expr, expected, found, blk_id); if let (Some(cond_expr), true, false) = ( @@ -1816,12 +1818,14 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { fcx: &FnCtxt<'_, 'tcx>, err: &mut Diagnostic, expr: &'tcx hir::Expr<'tcx>, + expected: Ty<'tcx>, + found: Ty<'tcx>, ) { match expr.peel_drop_temps().kind { hir::ExprKind::Struct( hir::QPath::Resolved( None, - hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, .. }, + hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, span, .. }, ), .., ) @@ -1830,7 +1834,11 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { kind: hir::ExprKind::Path(hir::QPath::Resolved( None, - hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, .. }, + hir::Path { + res: hir::def::Res::SelfTyAlias { alias_to, .. }, + span, + .. + }, )), .. }, @@ -1843,6 +1851,17 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { { err.span_label(self_ty.span, "this is the type of the `Self` literal"); } + if let ty::Adt(e_def, e_args) = expected.kind() + && let ty::Adt(f_def, _f_args) = found.kind() + && e_def == f_def + { + err.span_suggestion_verbose( + *span, + "use the type name directly", + fcx.tcx.value_path_str_with_args(*alias_to, e_args), + Applicability::MaybeIncorrect, + ); + } } _ => {} } diff --git a/tests/ui/structs/struct-path-self-type-mismatch.stderr b/tests/ui/structs/struct-path-self-type-mismatch.stderr index f4ca4851083..bbe5bae29bb 100644 --- a/tests/ui/structs/struct-path-self-type-mismatch.stderr +++ b/tests/ui/structs/struct-path-self-type-mismatch.stderr @@ -42,6 +42,10 @@ LL | | } found struct `Foo` = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters +help: use the type name directly + | +LL | Foo:: { + | ~~~~~~~~ error: aborting due to 3 previous errors