Skip to content

Commit d845685

Browse files
committed
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<T> Foo<T> { | - ------ this is the type of the `Self` literal | | | found type parameter LL | fn new<U>(u: U) -> Foo<U> { | - ------ expected `Foo<U>` because of return type | | | expected type parameter LL | / Self { LL | | LL | | inner: u LL | | LL | | } | |_________^ expected `Foo<U>`, found `Foo<T>` | = note: expected struct `Foo<U>` found struct `Foo<T>` = 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::<U> { | ~~~~~~~~ ``` Fix #76086.
1 parent a7e035a commit d845685

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@
3636
//! ```
3737
3838
use crate::FnCtxt;
39-
use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
39+
use rustc_errors::{
40+
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
41+
};
4042
use rustc_hir as hir;
4143
use rustc_hir::def_id::DefId;
4244
use rustc_hir::intravisit::{self, Visitor};
@@ -1738,7 +1740,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17381740
// label pointing out the cause for the type coercion will be wrong
17391741
// as prior return coercions would not be relevant (#57664).
17401742
let fn_decl = if let (Some(expr), Some(blk_id)) = (expression, blk_id) {
1741-
self.explain_self_literal(fcx, &mut err, expr);
1743+
self.explain_self_literal(fcx, &mut err, expr, expected, found);
17421744
let pointing_at_return_type =
17431745
fcx.suggest_mismatched_types_on_tail(&mut err, expr, expected, found, blk_id);
17441746
if let (Some(cond_expr), true, false) = (
@@ -1816,12 +1818,14 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
18161818
fcx: &FnCtxt<'_, 'tcx>,
18171819
err: &mut Diagnostic,
18181820
expr: &'tcx hir::Expr<'tcx>,
1821+
expected: Ty<'tcx>,
1822+
found: Ty<'tcx>,
18191823
) {
18201824
match expr.peel_drop_temps().kind {
18211825
hir::ExprKind::Struct(
18221826
hir::QPath::Resolved(
18231827
None,
1824-
hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, .. },
1828+
hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, span, .. },
18251829
),
18261830
..,
18271831
)
@@ -1830,7 +1834,11 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
18301834
kind:
18311835
hir::ExprKind::Path(hir::QPath::Resolved(
18321836
None,
1833-
hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, .. },
1837+
hir::Path {
1838+
res: hir::def::Res::SelfTyAlias { alias_to, .. },
1839+
span,
1840+
..
1841+
},
18341842
)),
18351843
..
18361844
},
@@ -1843,6 +1851,17 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
18431851
{
18441852
err.span_label(self_ty.span, "this is the type of the `Self` literal");
18451853
}
1854+
if let ty::Adt(e_def, e_args) = expected.kind()
1855+
&& let ty::Adt(f_def, _f_args) = found.kind()
1856+
&& e_def == f_def
1857+
{
1858+
err.span_suggestion_verbose(
1859+
*span,
1860+
"use the type name directly",
1861+
fcx.tcx.value_path_str_with_args(*alias_to, e_args),
1862+
Applicability::MaybeIncorrect,
1863+
);
1864+
}
18461865
}
18471866
_ => {}
18481867
}

tests/ui/structs/struct-path-self-type-mismatch.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ LL | | }
4242
found struct `Foo<T>`
4343
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
4444
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
45+
help: use the type name directly
46+
|
47+
LL | Foo::<U> {
48+
| ~~~~~~~~
4549

4650
error: aborting due to 3 previous errors
4751

0 commit comments

Comments
 (0)