about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-10-26 22:26:10 +0200
committerGitHub <noreply@github.com>2023-10-26 22:26:10 +0200
commit934cbe4637d832ec36f22981d33dc549d19d6d39 (patch)
tree1193b4417f85361cb346ec1a279ce7a1bacd4b84
parent8396efecf7d30ca9f7edcf76aba2ea388300f6ab (diff)
parent24cdb27e2842e5abab2875ce29c365ac5503773e (diff)
downloadrust-934cbe4637d832ec36f22981d33dc549d19d6d39.tar.gz
rust-934cbe4637d832ec36f22981d33dc549d19d6d39.zip
Rollup merge of #116968 - eopb:116967, r=petrochenkov
Invalid `?` suggestion on mismatched `Ok(T)`

fixes: #116967
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs53
-rw-r--r--tests/ui/type/type-check/issue-116967-cannot-coerce-returned-result.rs6
-rw-r--r--tests/ui/type/type-check/issue-116967-cannot-coerce-returned-result.stderr15
3 files changed, 43 insertions, 31 deletions
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index f379e8477e3..abb83228030 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -962,38 +962,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
     ) -> bool {
-        let ty::Adt(e, args_e) = expected.kind() else {
-            return false;
-        };
-        let ty::Adt(f, args_f) = found.kind() else {
-            return false;
-        };
-        if e.did() != f.did() {
-            return false;
-        }
-        if Some(e.did()) != self.tcx.get_diagnostic_item(sym::Result) {
-            return false;
-        }
         let map = self.tcx.hir();
-        if let Some(hir::Node::Expr(expr)) = map.find_parent(expr.hir_id)
-            && let hir::ExprKind::Ret(_) = expr.kind
-        {
-            // `return foo;`
-        } else if map.get_return_block(expr.hir_id).is_some() {
-            // Function's tail expression.
-        } else {
-            return false;
-        }
-        let e = args_e.type_at(1);
-        let f = args_f.type_at(1);
-        if self
-            .infcx
-            .type_implements_trait(
-                self.tcx.get_diagnostic_item(sym::Into).unwrap(),
-                [f, e],
-                self.param_env,
-            )
-            .must_apply_modulo_regions()
+        let returned = matches!(
+            map.find_parent(expr.hir_id),
+            Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. }))
+        ) || map.get_return_block(expr.hir_id).is_some();
+        if returned
+            && let ty::Adt(e, args_e) = expected.kind()
+            && let ty::Adt(f, args_f) = found.kind()
+            && e.did() == f.did()
+            && Some(e.did()) == self.tcx.get_diagnostic_item(sym::Result)
+            && let e_ok = args_e.type_at(0)
+            && let f_ok = args_f.type_at(0)
+            && self.infcx.can_eq(self.param_env, f_ok, e_ok)
+            && let e_err = args_e.type_at(1)
+            && let f_err = args_f.type_at(1)
+            && self
+                .infcx
+                .type_implements_trait(
+                    self.tcx.get_diagnostic_item(sym::Into).unwrap(),
+                    [f_err, e_err],
+                    self.param_env,
+                )
+                .must_apply_modulo_regions()
         {
             err.multipart_suggestion(
                 "use `?` to coerce and return an appropriate `Err`, and wrap the resulting value \
diff --git a/tests/ui/type/type-check/issue-116967-cannot-coerce-returned-result.rs b/tests/ui/type/type-check/issue-116967-cannot-coerce-returned-result.rs
new file mode 100644
index 00000000000..adf3049b4ba
--- /dev/null
+++ b/tests/ui/type/type-check/issue-116967-cannot-coerce-returned-result.rs
@@ -0,0 +1,6 @@
+fn foo() -> Result<String, ()> {
+    let out: Result<(), ()> = Ok(());
+    out //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/type/type-check/issue-116967-cannot-coerce-returned-result.stderr b/tests/ui/type/type-check/issue-116967-cannot-coerce-returned-result.stderr
new file mode 100644
index 00000000000..447b22a152d
--- /dev/null
+++ b/tests/ui/type/type-check/issue-116967-cannot-coerce-returned-result.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-116967-cannot-coerce-returned-result.rs:3:5
+   |
+LL | fn foo() -> Result<String, ()> {
+   |             ------------------ expected `Result<String, ()>` because of return type
+LL |     let out: Result<(), ()> = Ok(());
+LL |     out
+   |     ^^^ expected `Result<String, ()>`, found `Result<(), ()>`
+   |
+   = note: expected enum `Result<String, _>`
+              found enum `Result<(), _>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.