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

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

`

27

27

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

`

28

28

`use rustc_middle::span_bug;

`

29

29

`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};

`

34

32

`use rustc_session::errors::ExprParenthesesNeeded;

`

35

33

`use rustc_span::source_map::Spanned;

`

36

34

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

`

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

`

1125

1123

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

`

1126

1124

`)

`

1127

1125

`{

`

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(

`

1129

1174

`"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,

`

1134

1176

`Applicability::MaybeIncorrect,

`

1135

1177

`);

`

1136

1178

`}

`