For [E0308]: mismatched types, when expr is in an arm's body, not add… · rust-lang/rust@e8b5ba1

@@ -27,10 +27,8 @@ use rustc_middle::lint::in_external_macro;

2727

use rustc_middle::middle::stability::EvalResult;

2828

use rustc_middle::span_bug;

2929

use rustc_middle::ty::print::with_no_trimmed_paths;

30-

use rustc_middle::ty::{

31-

self, suggest_constraining_type_params, Article, Binder, IsSuggestable, Ty, TypeVisitableExt,

32-

Upcast,

33-

};

30+

use rustc_middle::ty::{self, suggest_constraining_type_params, Article, Binder};

31+

use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Upcast};

3432

use rustc_session::errors::ExprParenthesesNeeded;

3533

use rustc_span::source_map::Spanned;

3634

use rustc_span::symbol::{sym, Ident};

@@ -1125,12 +1123,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

11251123

self.tcx.hir().span_with_body(self.tcx.local_def_id_to_hir_id(fn_id)),

11261124

)

11271125

{

1128-

err.multipart_suggestion(

1126+

// When the expr is in a match arm's body, we shouldn't add semicolon ';' at the end.

1127+

// For example:

1128+

// fn mismatch_types() -> i32 {

1129+

// match 1 {

1130+

// x => dbg!(x),

1131+

// }

1132+

// todo!()

1133+

// }

1134+

// -------------^^^^^^^-

1135+

// Don't add semicolon `;` at the end of `dbg!(x)` expr

1136+

fn is_in_arm<'tcx>(expr: &'tcx hir::Expr<'tcx>, tcx: TyCtxt<'tcx>) -> bool {

1137+

for (_, node) in tcx.hir().parent_iter(expr.hir_id) {

1138+

match node {

1139+

hir::Node::Block(block) => {

1140+

if let Some(ret) = block.expr

1141+

&& ret.hir_id == expr.hir_id

1142+

{

1143+

continue;

1144+

}

1145+

}

1146+

hir::Node::Arm(arm) => {

1147+

if let hir::ExprKind::Block(block, _) = arm.body.kind

1148+

&& let Some(ret) = block.expr

1149+

&& ret.hir_id == expr.hir_id

1150+

{

1151+

return true;

1152+

}

1153+

}

1154+

hir::Node::Expr(e) if let hir::ExprKind::Block(block, _) = e.kind => {

1155+

if let Some(ret) = block.expr

1156+

&& ret.hir_id == expr.hir_id

1157+

{

1158+

continue;

1159+

}

1160+

}

1161+

_ => {

1162+

return false;

1163+

}

1164+

}

1165+

}

1166+1167+

false

1168+

}

1169+

let mut suggs = vec![(span.shrink_to_lo(), "return ".to_string())];

1170+

if !is_in_arm(expr, self.tcx) {

1171+

suggs.push((span.shrink_to_hi(), ";".to_string()));

1172+

}

1173+

err.multipart_suggestion_verbose(

11291174

"you might have meant to return this value",

1130-

vec![

1131-

(span.shrink_to_lo(), "return ".to_string()),

1132-

(span.shrink_to_hi(), ";".to_string()),

1133-

],

1175+

suggs,

11341176

Applicability::MaybeIncorrect,

11351177

);

11361178

}