diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 9dd82868adc54..b3ebc0621cbd6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -26,10 +26,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}; @@ -1111,12 +1109,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 0000000000000..30fd0028f198f --- /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 0000000000000..59178702489e9 --- /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 0000000000000..2a8f9867abb89 --- /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`.