Skip to content

Commit 990bce4

Browse files
authored
Rollup merge of #99974 - TaKO8Ki:suggest-removing-semicolon-and-boxing-the-expressions, r=compiler-errors
Suggest removing a semicolon and boxing the expressions for if-else `InferCtxt::suggest_remove_semi_or_return_binding` was not working well, so I fixed it and added a ui test.
2 parents 8b2637f + f6908be commit 990bce4

File tree

3 files changed

+210
-6
lines changed

3 files changed

+210
-6
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
712712
opt_suggest_box_span,
713713
}) => {
714714
let then_span = self.find_block_span_from_hir_id(then_id);
715-
let else_span = self.find_block_span_from_hir_id(then_id);
715+
let else_span = self.find_block_span_from_hir_id(else_id);
716716
err.span_label(then_span, "expected because of this");
717717
if let Some(sp) = outer_span {
718718
err.span_label(sp, "`if` and `else` have incompatible types");
@@ -760,11 +760,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
760760
second_ty: Ty<'tcx>,
761761
second_span: Span,
762762
) {
763-
let remove_semicolon =
764-
[(first_id, second_ty), (second_id, first_ty)].into_iter().find_map(|(id, ty)| {
765-
let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None };
766-
self.could_remove_semicolon(blk, ty)
767-
});
763+
let remove_semicolon = [
764+
(first_id, self.resolve_vars_if_possible(second_ty)),
765+
(second_id, self.resolve_vars_if_possible(first_ty)),
766+
]
767+
.into_iter()
768+
.find_map(|(id, ty)| {
769+
let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None };
770+
self.could_remove_semicolon(blk, ty)
771+
});
768772
match remove_semicolon {
769773
Some((sp, StatementAsExpression::NeedsBoxing)) => {
770774
err.multipart_suggestion(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// edition:2018
2+
3+
fn dummy() -> i32 {
4+
42
5+
}
6+
7+
fn extra_semicolon() {
8+
let _ = if true {
9+
//~^ NOTE `if` and `else` have incompatible types
10+
dummy(); //~ NOTE expected because of this
11+
//~^ HELP consider removing this semicolon
12+
} else {
13+
dummy() //~ ERROR `if` and `else` have incompatible types
14+
//~^ NOTE expected `()`, found `i32`
15+
};
16+
}
17+
18+
async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
19+
//~| NOTE while checking the return type of the `async fn`
20+
//~| NOTE in this expansion of desugaring of `async` block or function
21+
//~| NOTE checked the `Output` of this `async fn`, expected opaque type
22+
//~| NOTE while checking the return type of the `async fn`
23+
//~| NOTE in this expansion of desugaring of `async` block or function
24+
async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type
25+
//~| NOTE checked the `Output` of this `async fn`, found opaque type
26+
//~| NOTE while checking the return type of the `async fn`
27+
//~| NOTE in this expansion of desugaring of `async` block or function
28+
//~| NOTE while checking the return type of the `async fn`
29+
//~| NOTE in this expansion of desugaring of `async` block or function
30+
31+
async fn async_extra_semicolon_same() {
32+
let _ = if true {
33+
//~^ NOTE `if` and `else` have incompatible types
34+
async_dummy(); //~ NOTE expected because of this
35+
//~^ HELP consider removing this semicolon
36+
} else {
37+
async_dummy() //~ ERROR `if` and `else` have incompatible types
38+
//~^ NOTE expected `()`, found opaque type
39+
//~| NOTE expected unit type `()`
40+
//~| HELP consider `await`ing on the `Future`
41+
};
42+
}
43+
44+
async fn async_extra_semicolon_different() {
45+
let _ = if true {
46+
//~^ NOTE `if` and `else` have incompatible types
47+
async_dummy(); //~ NOTE expected because of this
48+
//~^ HELP consider removing this semicolon
49+
} else {
50+
async_dummy2() //~ ERROR `if` and `else` have incompatible types
51+
//~^ NOTE expected `()`, found opaque type
52+
//~| NOTE expected unit type `()`
53+
//~| HELP consider `await`ing on the `Future`
54+
};
55+
}
56+
57+
async fn async_different_futures() {
58+
let _ = if true {
59+
//~^ NOTE `if` and `else` have incompatible types
60+
async_dummy() //~ NOTE expected because of this
61+
//~| HELP consider `await`ing on both `Future`s
62+
} else {
63+
async_dummy2() //~ ERROR `if` and `else` have incompatible types
64+
//~^ NOTE expected opaque type, found a different opaque type
65+
//~| NOTE expected opaque type `impl Future<Output = ()>`
66+
//~| NOTE distinct uses of `impl Trait` result in different opaque types
67+
};
68+
}
69+
70+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
error[E0308]: `if` and `else` have incompatible types
2+
--> $DIR/if-then-neeing-semi.rs:37:9
3+
|
4+
LL | let _ = if true {
5+
| _____________-
6+
LL | |
7+
LL | | async_dummy();
8+
| | -------------- expected because of this
9+
LL | |
10+
LL | | } else {
11+
LL | | async_dummy()
12+
| | ^^^^^^^^^^^^^ expected `()`, found opaque type
13+
... |
14+
LL | |
15+
LL | | };
16+
| |_____- `if` and `else` have incompatible types
17+
|
18+
note: while checking the return type of the `async fn`
19+
--> $DIR/if-then-neeing-semi.rs:18:24
20+
|
21+
LL | async fn async_dummy() {}
22+
| ^ checked the `Output` of this `async fn`, found opaque type
23+
= note: expected unit type `()`
24+
found opaque type `impl Future<Output = ()>`
25+
help: consider `await`ing on the `Future`
26+
|
27+
LL | async_dummy().await
28+
| ++++++
29+
help: consider removing this semicolon
30+
|
31+
LL - async_dummy();
32+
LL + async_dummy()
33+
|
34+
35+
error[E0308]: `if` and `else` have incompatible types
36+
--> $DIR/if-then-neeing-semi.rs:50:9
37+
|
38+
LL | let _ = if true {
39+
| _____________-
40+
LL | |
41+
LL | | async_dummy();
42+
| | -------------- expected because of this
43+
LL | |
44+
LL | | } else {
45+
LL | | async_dummy2()
46+
| | ^^^^^^^^^^^^^^ expected `()`, found opaque type
47+
... |
48+
LL | |
49+
LL | | };
50+
| |_____- `if` and `else` have incompatible types
51+
|
52+
note: while checking the return type of the `async fn`
53+
--> $DIR/if-then-neeing-semi.rs:24:25
54+
|
55+
LL | async fn async_dummy2() {}
56+
| ^ checked the `Output` of this `async fn`, found opaque type
57+
= note: expected unit type `()`
58+
found opaque type `impl Future<Output = ()>`
59+
help: consider `await`ing on the `Future`
60+
|
61+
LL | async_dummy2().await
62+
| ++++++
63+
help: consider removing this semicolon and boxing the expressions
64+
|
65+
LL ~ Box::new(async_dummy())
66+
LL |
67+
LL | } else {
68+
LL ~ Box::new(async_dummy2())
69+
|
70+
71+
error[E0308]: `if` and `else` have incompatible types
72+
--> $DIR/if-then-neeing-semi.rs:63:9
73+
|
74+
LL | let _ = if true {
75+
| _____________-
76+
LL | |
77+
LL | | async_dummy()
78+
| | ------------- expected because of this
79+
LL | |
80+
LL | | } else {
81+
LL | | async_dummy2()
82+
| | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
83+
... |
84+
LL | |
85+
LL | | };
86+
| |_____- `if` and `else` have incompatible types
87+
|
88+
note: while checking the return type of the `async fn`
89+
--> $DIR/if-then-neeing-semi.rs:18:24
90+
|
91+
LL | async fn async_dummy() {}
92+
| ^ checked the `Output` of this `async fn`, expected opaque type
93+
note: while checking the return type of the `async fn`
94+
--> $DIR/if-then-neeing-semi.rs:24:25
95+
|
96+
LL | async fn async_dummy2() {}
97+
| ^ checked the `Output` of this `async fn`, found opaque type
98+
= note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:18:24>)
99+
found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:24:25>)
100+
= note: distinct uses of `impl Trait` result in different opaque types
101+
help: consider `await`ing on both `Future`s
102+
|
103+
LL ~ async_dummy().await
104+
LL |
105+
LL | } else {
106+
LL ~ async_dummy2().await
107+
|
108+
109+
error[E0308]: `if` and `else` have incompatible types
110+
--> $DIR/if-then-neeing-semi.rs:13:9
111+
|
112+
LL | let _ = if true {
113+
| _____________-
114+
LL | |
115+
LL | | dummy();
116+
| | --------
117+
| | | |
118+
| | | help: consider removing this semicolon
119+
| | expected because of this
120+
LL | |
121+
LL | | } else {
122+
LL | | dummy()
123+
| | ^^^^^^^ expected `()`, found `i32`
124+
LL | |
125+
LL | | };
126+
| |_____- `if` and `else` have incompatible types
127+
128+
error: aborting due to 4 previous errors
129+
130+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)