about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2021-07-01 11:15:42 +0200
committerGitHub <noreply@github.com>2021-07-01 11:15:42 +0200
commit7e27209ff83ffd6b94b6d9833b28644587ec3207 (patch)
tree62043387a2676b77099a9e65f2fd1ea020688af0
parentdfd30d7b705f858603ef6d21bdb893297aea37ba (diff)
parent61554bc9d72472332aac8cad341d77aa40cfb733 (diff)
downloadrust-7e27209ff83ffd6b94b6d9833b28644587ec3207.tar.gz
rust-7e27209ff83ffd6b94b6d9833b28644587ec3207.zip
Rollup merge of #86666 - ptrojahn:compare_kinds, r=petrochenkov
Fix misleading "impl Trait" error

The kinds can't be compared directly, as types with references are treated as different because the lifetimes aren't bound in ty, but are in expected.
Closes #84160
-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`.