about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs60
-rw-r--r--tests/ui/mismatched_types/mismatched-types-issue-126222.fixed34
-rw-r--r--tests/ui/mismatched_types/mismatched-types-issue-126222.rs34
-rw-r--r--tests/ui/mismatched_types/mismatched-types-issue-126222.stderr51
4 files changed, 170 insertions, 9 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 7cefe189bd6..92de2475764 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -27,10 +27,8 @@ use rustc_middle::lint::in_external_macro;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::span_bug;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{
-    self, suggest_constraining_type_params, Article, Binder, IsSuggestable, Ty, TypeVisitableExt,
-    Upcast,
-};
+use rustc_middle::ty::{self, suggest_constraining_type_params, Article, Binder};
+use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Upcast};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Ident};
@@ -1125,12 +1123,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.tcx.hir().span_with_body(self.tcx.local_def_id_to_hir_id(fn_id)),
             )
         {
-            err.multipart_suggestion(
+            // When the expr is in a match arm's body, we shouldn't add semicolon ';' at the end.
+            // For example:
+            // fn mismatch_types() -> i32 {
+            //     match 1 {
+            //         x => dbg!(x),
+            //     }
+            //     todo!()
+            // }
+            // -------------^^^^^^^-
+            // Don't add semicolon `;` at the end of `dbg!(x)` expr
+            fn is_in_arm<'tcx>(expr: &'tcx hir::Expr<'tcx>, tcx: TyCtxt<'tcx>) -> bool {
+                for (_, node) in tcx.hir().parent_iter(expr.hir_id) {
+                    match node {
+                        hir::Node::Block(block) => {
+                            if let Some(ret) = block.expr
+                                && ret.hir_id == expr.hir_id
+                            {
+                                continue;
+                            }
+                        }
+                        hir::Node::Arm(arm) => {
+                            if let hir::ExprKind::Block(block, _) = arm.body.kind
+                                && let Some(ret) = block.expr
+                                && ret.hir_id == expr.hir_id
+                            {
+                                return true;
+                            }
+                        }
+                        hir::Node::Expr(e) if let hir::ExprKind::Block(block, _) = e.kind => {
+                            if let Some(ret) = block.expr
+                                && ret.hir_id == expr.hir_id
+                            {
+                                continue;
+                            }
+                        }
+                        _ => {
+                            return false;
+                        }
+                    }
+                }
+
+                false
+            }
+            let mut suggs = vec![(span.shrink_to_lo(), "return ".to_string())];
+            if !is_in_arm(expr, self.tcx) {
+                suggs.push((span.shrink_to_hi(), ";".to_string()));
+            }
+            err.multipart_suggestion_verbose(
                 "you might have meant to return this value",
-                vec![
-                    (span.shrink_to_lo(), "return ".to_string()),
-                    (span.shrink_to_hi(), ";".to_string()),
-                ],
+                suggs,
                 Applicability::MaybeIncorrect,
             );
         }
diff --git a/tests/ui/mismatched_types/mismatched-types-issue-126222.fixed b/tests/ui/mismatched_types/mismatched-types-issue-126222.fixed
new file mode 100644
index 00000000000..30fd0028f19
--- /dev/null
+++ b/tests/ui/mismatched_types/mismatched-types-issue-126222.fixed
@@ -0,0 +1,34 @@
+//@ run-rustfix
+#![allow(unreachable_code, dead_code)]
+
+fn main() {
+    fn mismatch_types1() -> i32 {
+        match 1 {
+            x => return dbg!(x), //~ ERROR mismatched types
+        }
+        todo!()
+    }
+
+    fn mismatch_types2() -> i32 {
+        match 2 {
+            x => {
+                return dbg!(x) //~ ERROR mismatched types
+            }
+        }
+        todo!()
+    }
+
+    fn mismatch_types3() -> i32 {
+        match 1 {
+            _ => return dbg!(1) //~ ERROR mismatched types
+        }
+        todo!()
+    }
+
+    fn mismatch_types4() -> i32 {
+        match 1 {
+            _ => {return dbg!(1)} //~ ERROR mismatched types
+        }
+        todo!()
+    }
+}
diff --git a/tests/ui/mismatched_types/mismatched-types-issue-126222.rs b/tests/ui/mismatched_types/mismatched-types-issue-126222.rs
new file mode 100644
index 00000000000..59178702489
--- /dev/null
+++ b/tests/ui/mismatched_types/mismatched-types-issue-126222.rs
@@ -0,0 +1,34 @@
+//@ run-rustfix
+#![allow(unreachable_code, dead_code)]
+
+fn main() {
+    fn mismatch_types1() -> i32 {
+        match 1 {
+            x => dbg!(x), //~ ERROR mismatched types
+        }
+        todo!()
+    }
+
+    fn mismatch_types2() -> i32 {
+        match 2 {
+            x => {
+                dbg!(x) //~ ERROR mismatched types
+            }
+        }
+        todo!()
+    }
+
+    fn mismatch_types3() -> i32 {
+        match 1 {
+            _ => dbg!(1) //~ ERROR mismatched types
+        }
+        todo!()
+    }
+
+    fn mismatch_types4() -> i32 {
+        match 1 {
+            _ => {dbg!(1)} //~ ERROR mismatched types
+        }
+        todo!()
+    }
+}
diff --git a/tests/ui/mismatched_types/mismatched-types-issue-126222.stderr b/tests/ui/mismatched_types/mismatched-types-issue-126222.stderr
new file mode 100644
index 00000000000..2a8f9867abb
--- /dev/null
+++ b/tests/ui/mismatched_types/mismatched-types-issue-126222.stderr
@@ -0,0 +1,51 @@
+error[E0308]: mismatched types
+  --> $DIR/mismatched-types-issue-126222.rs:7:18
+   |
+LL |             x => dbg!(x),
+   |                  ^^^^^^^ expected `()`, found integer
+   |
+   = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you might have meant to return this value
+   |
+LL |             x => return dbg!(x),
+   |                  ++++++
+
+error[E0308]: mismatched types
+  --> $DIR/mismatched-types-issue-126222.rs:15:17
+   |
+LL |                 dbg!(x)
+   |                 ^^^^^^^ expected `()`, found integer
+   |
+   = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you might have meant to return this value
+   |
+LL |                 return dbg!(x)
+   |                 ++++++
+
+error[E0308]: mismatched types
+  --> $DIR/mismatched-types-issue-126222.rs:23:18
+   |
+LL |             _ => dbg!(1)
+   |                  ^^^^^^^ expected `()`, found integer
+   |
+   = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you might have meant to return this value
+   |
+LL |             _ => return dbg!(1)
+   |                  ++++++
+
+error[E0308]: mismatched types
+  --> $DIR/mismatched-types-issue-126222.rs:30:19
+   |
+LL |             _ => {dbg!(1)}
+   |                   ^^^^^^^ expected `()`, found integer
+   |
+   = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you might have meant to return this value
+   |
+LL |             _ => {return dbg!(1)}
+   |                   ++++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.