Skip to content

Commit e8b5ba1

Browse files
committed
For [E0308]: mismatched types, when expr is in an arm's body, not add semicolon ';' at the end of it.
fixes #126222
1 parent f3ff2f1 commit e8b5ba1

File tree

4 files changed

+170
-9
lines changed

4 files changed

+170
-9
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+51-9
Original file line numberDiff line numberDiff line change
@@ -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
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//@ run-rustfix
2+
#![allow(unreachable_code, dead_code)]
3+
4+
fn main() {
5+
fn mismatch_types1() -> i32 {
6+
match 1 {
7+
x => return dbg!(x), //~ ERROR mismatched types
8+
}
9+
todo!()
10+
}
11+
12+
fn mismatch_types2() -> i32 {
13+
match 2 {
14+
x => {
15+
return dbg!(x) //~ ERROR mismatched types
16+
}
17+
}
18+
todo!()
19+
}
20+
21+
fn mismatch_types3() -> i32 {
22+
match 1 {
23+
_ => return dbg!(1) //~ ERROR mismatched types
24+
}
25+
todo!()
26+
}
27+
28+
fn mismatch_types4() -> i32 {
29+
match 1 {
30+
_ => {return dbg!(1)} //~ ERROR mismatched types
31+
}
32+
todo!()
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//@ run-rustfix
2+
#![allow(unreachable_code, dead_code)]
3+
4+
fn main() {
5+
fn mismatch_types1() -> i32 {
6+
match 1 {
7+
x => dbg!(x), //~ ERROR mismatched types
8+
}
9+
todo!()
10+
}
11+
12+
fn mismatch_types2() -> i32 {
13+
match 2 {
14+
x => {
15+
dbg!(x) //~ ERROR mismatched types
16+
}
17+
}
18+
todo!()
19+
}
20+
21+
fn mismatch_types3() -> i32 {
22+
match 1 {
23+
_ => dbg!(1) //~ ERROR mismatched types
24+
}
25+
todo!()
26+
}
27+
28+
fn mismatch_types4() -> i32 {
29+
match 1 {
30+
_ => {dbg!(1)} //~ ERROR mismatched types
31+
}
32+
todo!()
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/mismatched-types-issue-126222.rs:7:18
3+
|
4+
LL | x => dbg!(x),
5+
| ^^^^^^^ expected `()`, found integer
6+
|
7+
= note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
8+
help: you might have meant to return this value
9+
|
10+
LL | x => return dbg!(x),
11+
| ++++++
12+
13+
error[E0308]: mismatched types
14+
--> $DIR/mismatched-types-issue-126222.rs:15:17
15+
|
16+
LL | dbg!(x)
17+
| ^^^^^^^ expected `()`, found integer
18+
|
19+
= note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
20+
help: you might have meant to return this value
21+
|
22+
LL | return dbg!(x)
23+
| ++++++
24+
25+
error[E0308]: mismatched types
26+
--> $DIR/mismatched-types-issue-126222.rs:23:18
27+
|
28+
LL | _ => dbg!(1)
29+
| ^^^^^^^ expected `()`, found integer
30+
|
31+
= note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
32+
help: you might have meant to return this value
33+
|
34+
LL | _ => return dbg!(1)
35+
| ++++++
36+
37+
error[E0308]: mismatched types
38+
--> $DIR/mismatched-types-issue-126222.rs:30:19
39+
|
40+
LL | _ => {dbg!(1)}
41+
| ^^^^^^^ expected `()`, found integer
42+
|
43+
= note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
44+
help: you might have meant to return this value
45+
|
46+
LL | _ => {return dbg!(1)}
47+
| ++++++
48+
49+
error: aborting due to 4 previous errors
50+
51+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)