about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs38
-rw-r--r--tests/ui/structs/struct-path-self-type-mismatch.stderr4
2 files changed, 41 insertions, 1 deletions
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 6c03bc3b57a..58f4e07e944 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1738,6 +1738,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);
             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) = (
@@ -1810,6 +1811,43 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         err
     }
 
+    fn explain_self_literal(
+        &self,
+        fcx: &FnCtxt<'_, 'tcx>,
+        err: &mut Diagnostic,
+        expr: &'tcx hir::Expr<'tcx>,
+    ) {
+        match expr.peel_drop_temps().kind {
+            hir::ExprKind::Struct(
+                hir::QPath::Resolved(
+                    None,
+                    hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, .. },
+                ),
+                ..,
+            )
+            | hir::ExprKind::Call(
+                hir::Expr {
+                    kind:
+                        hir::ExprKind::Path(hir::QPath::Resolved(
+                            None,
+                            hir::Path { res: hir::def::Res::SelfTyAlias { alias_to, .. }, .. },
+                        )),
+                    ..
+                },
+                ..,
+            ) => {
+                if let Some(hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }),
+                    ..
+                })) = fcx.tcx.hir().get_if_local(*alias_to)
+                {
+                    err.span_label(self_ty.span, "this is the type of the `Self` literal");
+                }
+            }
+            _ => {}
+        }
+    }
+
     /// Checks whether the return type is unsized via an obligation, which makes
     /// sure we consider `dyn Trait: Sized` where clauses, which are trivially
     /// false but technically valid for typeck.
diff --git a/tests/ui/structs/struct-path-self-type-mismatch.stderr b/tests/ui/structs/struct-path-self-type-mismatch.stderr
index cddc1356194..f4ca4851083 100644
--- a/tests/ui/structs/struct-path-self-type-mismatch.stderr
+++ b/tests/ui/structs/struct-path-self-type-mismatch.stderr
@@ -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
    |              |