Skip to content

Commit dd49c39

Browse files
authored
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.
2 parents 92aba63 + 1e8c095 commit dd49c39

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

compiler/rustc_hir_typeck/src/demand.rs

+54
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
3131
}
3232

3333
self.annotate_alternative_method_deref(err, expr, error);
34+
self.explain_self_literal(err, expr, expected, expr_ty);
3435

3536
// Use `||` to give these suggestions a precedence
3637
let suggested = self.suggest_missing_parentheses(err, expr)
@@ -1027,6 +1028,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10271028
return false;
10281029
}
10291030

1031+
fn explain_self_literal(
1032+
&self,
1033+
err: &mut Diagnostic,
1034+
expr: &hir::Expr<'tcx>,
1035+
expected: Ty<'tcx>,
1036+
found: Ty<'tcx>,
1037+
) {
1038+
match expr.peel_drop_temps().kind {
1039+
hir::ExprKind::Struct(
1040+
hir::QPath::Resolved(
1041+
None,
1042+
hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, span, .. },
1043+
),
1044+
..,
1045+
)
1046+
| hir::ExprKind::Call(
1047+
hir::Expr {
1048+
kind:
1049+
hir::ExprKind::Path(hir::QPath::Resolved(
1050+
None,
1051+
hir::Path {
1052+
res: hir::def::Res::SelfTyAlias { alias_to, .. },
1053+
span,
1054+
..
1055+
},
1056+
)),
1057+
..
1058+
},
1059+
..,
1060+
) => {
1061+
if let Some(hir::Node::Item(hir::Item {
1062+
kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }),
1063+
..
1064+
})) = self.tcx.hir().get_if_local(*alias_to)
1065+
{
1066+
err.span_label(self_ty.span, "this is the type of the `Self` literal");
1067+
}
1068+
if let ty::Adt(e_def, e_args) = expected.kind()
1069+
&& let ty::Adt(f_def, _f_args) = found.kind()
1070+
&& e_def == f_def
1071+
{
1072+
err.span_suggestion_verbose(
1073+
*span,
1074+
"use the type name directly",
1075+
self.tcx.value_path_str_with_args(*alias_to, e_args),
1076+
Applicability::MaybeIncorrect,
1077+
);
1078+
}
1079+
}
1080+
_ => {}
1081+
}
1082+
}
1083+
10301084
fn note_wrong_return_ty_due_to_generic_arg(
10311085
&self,
10321086
err: &mut Diagnostic,

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ error[E0308]: mismatched types
2424
--> $DIR/struct-path-self-type-mismatch.rs:13:9
2525
|
2626
LL | impl<T> Foo<T> {
27-
| - found type parameter
27+
| - ------ this is the type of the `Self` literal
28+
| |
29+
| found type parameter
2830
LL | fn new<U>(u: U) -> Foo<U> {
2931
| - ------ expected `Foo<U>` because of return type
3032
| |
@@ -40,6 +42,10 @@ LL | | }
4042
found struct `Foo<T>`
4143
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
4244
= 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+
| ~~~~~~~~
4349

4450
error: aborting due to 3 previous errors
4551

0 commit comments

Comments
 (0)