From d8456855f5d65a2ed26b09a82c750535a09becdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 16 Nov 2023 02:27:55 +0000 Subject: [PATCH] Suggest replacing `Self` with the right type on type error When encountering a type error caused by the use of `Self`, suggest using the actual type name instead. ``` error[E0308]: mismatched types --> $DIR/struct-path-self-type-mismatch.rs:13:9 | LL | impl Foo { | - ------ this is the type of the `Self` literal | | | found type parameter LL | fn new(u: U) -> Foo { | - ------ expected `Foo` because of return type | | | expected type parameter LL | / Self { LL | | LL | | inner: u LL | | LL | | } | |_________^ expected `Foo`, found `Foo` | = note: expected struct `Foo` 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:: { | ~~~~~~~~ ``` Fix #76086. --- compiler/rustc_hir_typeck/src/coercion.rs | 27 ++++++++++++++++--- .../struct-path-self-type-mismatch.stderr | 4 +++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 58f4e07e9446..8dbf01e97354 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 f4ca48510830..bbe5bae29bbe 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