about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/check/coercion.rs1
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs16
-rw-r--r--src/test/ui/extern/extern-types-distinct-types.stderr2
-rw-r--r--src/test/ui/retslot-cast.stderr3
-rw-r--r--src/test/ui/typeck/issue-84160.rs9
-rw-r--r--src/test/ui/typeck/issue-84160.stderr15
6 files changed, 43 insertions, 3 deletions
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index 236fec94bdb..afa4d0f1c4d 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -1481,6 +1481,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                     expected,
                     found,
                     can_suggest,
+                    fcx.tcx.hir().get_parent_item(id),
                 );
             }
             if !pointing_at_return_type {
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
index d6b1e56316b..54aab271fdb 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
@@ -52,9 +52,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
         let mut pointing_at_return_type = false;
         if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
-            pointing_at_return_type =
-                self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
             let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap();
+            pointing_at_return_type = self.suggest_missing_return_type(
+                err,
+                &fn_decl,
+                expected,
+                found,
+                can_suggest,
+                fn_id,
+            );
             self.suggest_missing_break_or_return_expr(
                 err, expr, &fn_decl, expected, found, blk_id, fn_id,
             );
@@ -433,6 +439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
         can_suggest: bool,
+        fn_id: hir::HirId,
     ) -> bool {
         // Only suggest changing the return type for methods that
         // haven't set a return type at all (and aren't `fn main()` or an impl).
@@ -465,7 +472,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
                 debug!("suggest_missing_return_type: return type {:?}", ty);
                 debug!("suggest_missing_return_type: expected type {:?}", ty);
-                if ty.kind() == expected.kind() {
+                let bound_vars = self.tcx.late_bound_vars(fn_id);
+                let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
+                let ty = self.normalize_associated_types_in(sp, ty);
+                if self.can_coerce(expected, ty) {
                     err.span_label(sp, format!("expected `{}` because of return type", expected));
                     return true;
                 }
diff --git a/src/test/ui/extern/extern-types-distinct-types.stderr b/src/test/ui/extern/extern-types-distinct-types.stderr
index 32b45ee10ad..f69629232ae 100644
--- a/src/test/ui/extern/extern-types-distinct-types.stderr
+++ b/src/test/ui/extern/extern-types-distinct-types.stderr
@@ -6,6 +6,8 @@ LL |     type A;
 LL |     type B;
    |     ------- the expected foreign type
 ...
+LL | fn foo(r: &A) -> &B {
+   |                  -- expected `&B` because of return type
 LL |     r
    |     ^ expected extern type `B`, found extern type `A`
    |
diff --git a/src/test/ui/retslot-cast.stderr b/src/test/ui/retslot-cast.stderr
index 9b5f11ce667..798ce1199a9 100644
--- a/src/test/ui/retslot-cast.stderr
+++ b/src/test/ui/retslot-cast.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/retslot-cast.rs:13:5
    |
+LL |             -> Option<&Iterator<Item=()>> {
+   |                -------------------------- expected `Option<&dyn Iterator<Item = ()>>` because of return type
+...
 LL |     inner(x)
    |     ^^^^^^^^ expected trait `Iterator<Item = ()>`, found trait `Iterator<Item = ()> + Send`
    |
diff --git a/src/test/ui/typeck/issue-84160.rs b/src/test/ui/typeck/issue-84160.rs
new file mode 100644
index 00000000000..7b444df8528
--- /dev/null
+++ b/src/test/ui/typeck/issue-84160.rs
@@ -0,0 +1,9 @@
+fn mismatched_types_with_reference(x: &u32) -> &u32 {
+    if false {
+        return x;
+    }
+    return "test";
+    //~^ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-84160.stderr b/src/test/ui/typeck/issue-84160.stderr
new file mode 100644
index 00000000000..24c188b3fcb
--- /dev/null
+++ b/src/test/ui/typeck/issue-84160.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-84160.rs:5:12
+   |
+LL | fn mismatched_types_with_reference(x: &u32) -> &u32 {
+   |                                                ---- expected `&u32` because of return type
+...
+LL |     return "test";
+   |            ^^^^^^ expected `u32`, found `str`
+   |
+   = note: expected reference `&u32`
+              found reference `&'static str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.