Skip to content

Commit d1d8fa4

Browse files
authored
Rollup merge of rust-lang#95758 - compiler-errors:issue-54771, r=estebank
Only suggest removing semicolon when expression is compatible with `impl Trait` rust-lang#54771 (comment) > It still needs checking that the last statement's expr can actually conform to the trait, but the naïve behavior is there. Only suggest removing a semicolon when the type behind the semicolon actually implements the trait in an RPIT `-> impl Trait`. Also upgrade the label that suggests removing the semicolon to a suggestion (should it be verbose?). cc rust-lang#54771
2 parents b51979a + dfe13db commit d1d8fa4

15 files changed

+97
-32
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+21-10
Original file line numberDiff line numberDiff line change
@@ -1083,20 +1083,31 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
10831083
let parent_node = hir.get_parent_node(obligation.cause.body_id);
10841084
let node = hir.find(parent_node);
10851085
if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })) = node
1086-
&& let body = hir.body(*body_id)
1087-
&& let hir::ExprKind::Block(blk, _) = &body.value.kind
1086+
&& let hir::ExprKind::Block(blk, _) = &hir.body(*body_id).value.kind
10881087
&& sig.decl.output.span().overlaps(span)
10891088
&& blk.expr.is_none()
1090-
&& *trait_pred.self_ty().skip_binder().kind() == ty::Tuple(ty::List::empty())
1091-
// FIXME(estebank): When encountering a method with a trait
1092-
// bound not satisfied in the return type with a body that has
1093-
// no return, suggest removal of semicolon on last statement.
1094-
// Once that is added, close #54771.
1089+
&& trait_pred.self_ty().skip_binder().is_unit()
10951090
&& let Some(stmt) = blk.stmts.last()
1096-
&& let hir::StmtKind::Semi(_) = stmt.kind
1091+
&& let hir::StmtKind::Semi(expr) = stmt.kind
1092+
// Only suggest this if the expression behind the semicolon implements the predicate
1093+
&& let Some(typeck_results) = self.in_progress_typeck_results
1094+
&& let Some(ty) = typeck_results.borrow().expr_ty_opt(expr)
1095+
&& self.predicate_may_hold(&self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred, ty))
10971096
{
1098-
let sp = self.tcx.sess.source_map().end_point(stmt.span);
1099-
err.span_label(sp, "consider removing this semicolon");
1097+
err.span_label(
1098+
expr.span,
1099+
&format!(
1100+
"this expression has type `{}`, which implements `{}`",
1101+
ty,
1102+
trait_pred.print_modifiers_and_trait_path()
1103+
)
1104+
);
1105+
err.span_suggestion(
1106+
self.tcx.sess.source_map().end_point(stmt.span),
1107+
"remove this semicolon",
1108+
String::new(),
1109+
Applicability::MachineApplicable
1110+
);
11001111
return true;
11011112
}
11021113
false

compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
936936
} else {
937937
err.span_suggestion_short(
938938
span_semi,
939-
"consider removing this semicolon",
939+
"remove this semicolon",
940940
String::new(),
941941
Applicability::MachineApplicable,
942942
);

src/test/ui/block-result/consider-removing-last-semi.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | pub fn f() -> String {
77
| implicitly returns `()` as its body has no tail or `return` expression
88
LL | 0u8;
99
LL | "bla".to_string();
10-
| - help: consider removing this semicolon
10+
| - help: remove this semicolon
1111

1212
error[E0308]: mismatched types
1313
--> $DIR/consider-removing-last-semi.rs:8:15
@@ -18,7 +18,7 @@ LL | pub fn g() -> String {
1818
| implicitly returns `()` as its body has no tail or `return` expression
1919
LL | "this won't work".to_string();
2020
LL | "removeme".to_string();
21-
| - help: consider removing this semicolon
21+
| - help: remove this semicolon
2222

2323
error[E0308]: mismatched types
2424
--> $DIR/consider-removing-last-semi.rs:13:25
@@ -29,7 +29,7 @@ LL | pub fn macro_tests() -> u32 {
2929
| implicitly returns `()` as its body has no tail or `return` expression
3030
...
3131
LL | mac!();
32-
| - help: consider removing this semicolon
32+
| - help: remove this semicolon
3333

3434
error: aborting due to 3 previous errors
3535

src/test/ui/block-result/issue-11714.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | fn blah() -> i32 {
77
| implicitly returns `()` as its body has no tail or `return` expression
88
...
99
LL | ;
10-
| - help: consider removing this semicolon
10+
| - help: remove this semicolon
1111

1212
error: aborting due to previous error
1313

src/test/ui/block-result/issue-13428.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ LL | fn bar() -> String {
1515
| implicitly returns `()` as its body has no tail or `return` expression
1616
LL | "foobar".to_string()
1717
LL | ;
18-
| - help: consider removing this semicolon
18+
| - help: remove this semicolon
1919

2020
error: aborting due to 2 previous errors
2121

src/test/ui/closures/old-closure-expression-remove-semicolon.fixed

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ fn foo() -> i32 {
77
fn main() {
88
let _x: i32 = {
99
//~^ ERROR mismatched types
10-
foo() //~ HELP consider removing this semicolon
10+
foo() //~ HELP remove this semicolon
1111
};
1212
}

src/test/ui/closures/old-closure-expression-remove-semicolon.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ fn foo() -> i32 {
77
fn main() {
88
let _x: i32 = {
99
//~^ ERROR mismatched types
10-
foo(); //~ HELP consider removing this semicolon
10+
foo(); //~ HELP remove this semicolon
1111
};
1212
}

src/test/ui/closures/old-closure-expression-remove-semicolon.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | let _x: i32 = {
55
| ___________________^
66
LL | |
77
LL | | foo();
8-
| | - help: consider removing this semicolon
8+
| | - help: remove this semicolon
99
LL | | };
1010
| |_____^ expected `i32`, found `()`
1111

src/test/ui/coercion/coercion-missing-tail-expected-type.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | fn plus_one(x: i32) -> i32 {
66
| |
77
| implicitly returns `()` as its body has no tail or `return` expression
88
LL | x + 1;
9-
| - help: consider removing this semicolon
9+
| - help: remove this semicolon
1010

1111
error[E0308]: mismatched types
1212
--> $DIR/coercion-missing-tail-expected-type.rs:8:13
@@ -16,7 +16,7 @@ LL | fn foo() -> Result<u8, u64> {
1616
| |
1717
| implicitly returns `()` as its body has no tail or `return` expression
1818
LL | Ok(1);
19-
| - help: consider removing this semicolon
19+
| - help: remove this semicolon
2020
|
2121
= note: expected enum `Result<u8, u64>`
2222
found unit type `()`

src/test/ui/issues/issue-6458-4.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | fn foo(b: bool) -> Result<bool,String> {
66
| |
77
| implicitly returns `()` as its body has no tail or `return` expression
88
LL | Err("bar".to_string());
9-
| - help: consider removing this semicolon
9+
| - help: remove this semicolon
1010
|
1111
= note: expected enum `Result<bool, String>`
1212
found unit type `()`

src/test/ui/liveness/liveness-return-last-stmt-semi.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ LL | fn bar(x: u32) -> u32 {
1414
| |
1515
| implicitly returns `()` as its body has no tail or `return` expression
1616
LL | x * 2;
17-
| - help: consider removing this semicolon
17+
| - help: remove this semicolon
1818

1919
error[E0308]: mismatched types
2020
--> $DIR/liveness-return-last-stmt-semi.rs:13:19
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
11
trait Bar {}
2-
impl Bar for u8 {}
2+
3+
impl Bar for i32 {}
4+
5+
struct Qux;
6+
7+
impl Bar for Qux {}
8+
39
fn foo() -> impl Bar {
4-
5; //~^ ERROR the trait bound `(): Bar` is not satisfied
10+
//~^ ERROR the trait bound `(): Bar` is not satisfied
11+
//~| ERROR the trait bound `(): Bar` is not satisfied
12+
//~| HELP the following other types implement trait `Bar`:
13+
5;
14+
//~^ HELP remove this semicolon
15+
}
16+
17+
fn bar() -> impl Bar {
18+
//~^ ERROR the trait bound `(): Bar` is not satisfied
519
//~| ERROR the trait bound `(): Bar` is not satisfied
20+
//~| HELP the following other types implement trait `Bar`:
21+
//~| HELP the following other types implement trait `Bar`:
22+
"";
623
}
724

825
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,58 @@
11
error[E0277]: the trait bound `(): Bar` is not satisfied
2-
--> $DIR/impl-trait-return-trailing-semicolon.rs:3:13
2+
--> $DIR/impl-trait-return-trailing-semicolon.rs:9:13
33
|
44
LL | fn foo() -> impl Bar {
55
| ^^^^^^^^ the trait `Bar` is not implemented for `()`
6+
...
67
LL | 5;
7-
| - consider removing this semicolon
8+
| -- help: remove this semicolon
9+
| |
10+
| this expression has type `{integer}`, which implements `Bar`
811

912
error[E0277]: the trait bound `(): Bar` is not satisfied
10-
--> $DIR/impl-trait-return-trailing-semicolon.rs:3:22
13+
--> $DIR/impl-trait-return-trailing-semicolon.rs:9:22
1114
|
1215
LL | fn foo() -> impl Bar {
1316
| ______________________^
17+
LL | |
18+
LL | |
19+
LL | |
1420
LL | | 5;
1521
LL | |
1622
LL | | }
1723
| |_^ the trait `Bar` is not implemented for `()`
1824
|
19-
= help: the trait `Bar` is implemented for `u8`
25+
= help: the following other types implement trait `Bar`:
26+
Qux
27+
i32
28+
29+
error[E0277]: the trait bound `(): Bar` is not satisfied
30+
--> $DIR/impl-trait-return-trailing-semicolon.rs:17:13
31+
|
32+
LL | fn bar() -> impl Bar {
33+
| ^^^^^^^^ the trait `Bar` is not implemented for `()`
34+
|
35+
= help: the following other types implement trait `Bar`:
36+
Qux
37+
i32
38+
39+
error[E0277]: the trait bound `(): Bar` is not satisfied
40+
--> $DIR/impl-trait-return-trailing-semicolon.rs:17:22
41+
|
42+
LL | fn bar() -> impl Bar {
43+
| ______________________^
44+
LL | |
45+
LL | |
46+
LL | |
47+
LL | |
48+
LL | | "";
49+
LL | | }
50+
| |_^ the trait `Bar` is not implemented for `()`
51+
|
52+
= help: the following other types implement trait `Bar`:
53+
Qux
54+
i32
2055

21-
error: aborting due to 2 previous errors
56+
error: aborting due to 4 previous errors
2257

2358
For more information about this error, try `rustc --explain E0277`.

src/test/ui/suggestions/issue-81098.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ LL | fn ok() -> impl core::fmt::Display {
2727
| ^^^^^^^^^^^^^^^^^^^^^^^ `()` cannot be formatted with the default formatter
2828
LL |
2929
LL | 1;
30-
| - consider removing this semicolon
30+
| -- help: remove this semicolon
31+
| |
32+
| this expression has type `{integer}`, which implements `std::fmt::Display`
3133
|
3234
= help: the trait `std::fmt::Display` is not implemented for `()`
3335
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead

src/test/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | fn not_all_paths(a: &str) -> u32 {
77
| implicitly returns `()` as its body has no tail or `return` expression
88
...
99
LL | };
10-
| - help: consider removing this semicolon
10+
| - help: remove this semicolon
1111

1212
error[E0308]: `match` arms have incompatible types
1313
--> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:26:14

0 commit comments

Comments
 (0)