Rollup merge of #117959 - estebank:issue-76086, r=compiler-errors
Better handle type errors involving `Self` literals When encountering a type error involving a `Self` literal, point at the self type of the enclosing `impl` and 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.
This commit is contained in:
commit
dd49c39e02
@ -31,6 +31,7 @@ pub fn emit_type_mismatch_suggestions(
|
||||
}
|
||||
|
||||
self.annotate_alternative_method_deref(err, expr, error);
|
||||
self.explain_self_literal(err, expr, expected, expr_ty);
|
||||
|
||||
// Use `||` to give these suggestions a precedence
|
||||
let suggested = self.suggest_missing_parentheses(err, expr)
|
||||
@ -1027,6 +1028,59 @@ pub(crate) fn is_destruct_assignment_desugaring(&self, expr: &hir::Expr<'_>) ->
|
||||
return false;
|
||||
}
|
||||
|
||||
fn explain_self_literal(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
expr: &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, .. }, span, .. },
|
||||
),
|
||||
..,
|
||||
)
|
||||
| hir::ExprKind::Call(
|
||||
hir::Expr {
|
||||
kind:
|
||||
hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
hir::Path {
|
||||
res: hir::def::Res::SelfTyAlias { alias_to, .. },
|
||||
span,
|
||||
..
|
||||
},
|
||||
)),
|
||||
..
|
||||
},
|
||||
..,
|
||||
) => {
|
||||
if let Some(hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }),
|
||||
..
|
||||
})) = self.tcx.hir().get_if_local(*alias_to)
|
||||
{
|
||||
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",
|
||||
self.tcx.value_path_str_with_args(*alias_to, e_args),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn note_wrong_return_ty_due_to_generic_arg(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
|
@ -24,7 +24,9 @@ error[E0308]: mismatched types
|
||||
--> $DIR/struct-path-self-type-mismatch.rs:13:9
|
||||
|
|
||||
LL | impl<T> Foo<T> {
|
||||
| - found type parameter
|
||||
| - ------ 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
|
||||
| |
|
||||
@ -40,6 +42,10 @@ LL | | }
|
||||
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> {
|
||||
| ~~~~~~~~
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user