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.annotate_alternative_method_deref(err, expr, error);
|
||||||
|
self.explain_self_literal(err, expr, expected, expr_ty);
|
||||||
|
|
||||||
// Use `||` to give these suggestions a precedence
|
// Use `||` to give these suggestions a precedence
|
||||||
let suggested = self.suggest_missing_parentheses(err, expr)
|
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;
|
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(
|
fn note_wrong_return_ty_due_to_generic_arg(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
|
@ -24,7 +24,9 @@ error[E0308]: mismatched types
|
|||||||
--> $DIR/struct-path-self-type-mismatch.rs:13:9
|
--> $DIR/struct-path-self-type-mismatch.rs:13:9
|
||||||
|
|
|
|
||||||
LL | impl<T> Foo<T> {
|
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> {
|
LL | fn new<U>(u: U) -> Foo<U> {
|
||||||
| - ------ expected `Foo<U>` because of return type
|
| - ------ expected `Foo<U>` because of return type
|
||||||
| |
|
| |
|
||||||
@ -40,6 +42,10 @@ LL | | }
|
|||||||
found struct `Foo<T>`
|
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: 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
|
= 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
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user