Skip to content

Commit 472a874

Browse files
authored
Rollup merge of #103142 - fmease:fix-103052, r=oli-obk
Make diagnostic for unsatisfied `Termination` bounds more precise Don't blindly emit a diagnostic claiming that “*`main` has an invalid return type*” if we encounter a type that should but doesn't implement `std::process::Termination` and isn't actually the return type of the program entry `main`. Fixes #103052. ``@rustbot`` label A-diagnostics T-compiler T-libs r? diagnostics
2 parents 56e4123 + 684df4d commit 472a874

File tree

8 files changed

+78
-5
lines changed

8 files changed

+78
-5
lines changed

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ symbols! {
451451
call_once,
452452
caller_location,
453453
capture_disjoint_fields,
454+
cause,
454455
cdylib,
455456
ceilf32,
456457
ceilf64,

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

+4
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
164164
flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
165165
}
166166

167+
if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
168+
flags.push((sym::cause, Some("MainFunctionType".to_string())));
169+
}
170+
167171
// Add all types without trimmed paths.
168172
ty::print::with_no_trimmed_paths!({
169173
let generics = self.tcx.generics_of(def_id);

library/std/src/process.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -2154,8 +2154,16 @@ pub fn id() -> u32 {
21542154
#[cfg_attr(not(test), lang = "termination")]
21552155
#[stable(feature = "termination_trait_lib", since = "1.61.0")]
21562156
#[rustc_on_unimplemented(
2157-
message = "`main` has invalid return type `{Self}`",
2158-
label = "`main` can only return types that implement `{Termination}`"
2157+
on(
2158+
all(not(bootstrap), cause = "MainFunctionType"),
2159+
message = "`main` has invalid return type `{Self}`",
2160+
label = "`main` can only return types that implement `{Termination}`"
2161+
),
2162+
on(
2163+
bootstrap,
2164+
message = "`main` has invalid return type `{Self}`",
2165+
label = "`main` can only return types that implement `{Termination}`"
2166+
)
21592167
)]
21602168
pub trait Termination {
21612169
/// Is called to get the representation of the value as status code.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Check that we don't blindly emit a diagnostic claiming that "`main` has an invalid return type"
2+
// if we encounter a type that doesn't implement `std::process::Termination` and is not actually
3+
// the return type of the program entry `main`.
4+
5+
fn receive(_: impl std::process::Termination) {}
6+
7+
struct Something;
8+
9+
fn main() {
10+
receive(Something); //~ ERROR the trait bound `Something: Termination` is not satisfied
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0277]: the trait bound `Something: Termination` is not satisfied
2+
--> $DIR/issue-103052-1.rs:10:13
3+
|
4+
LL | receive(Something);
5+
| ------- ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
note: required by a bound in `receive`
10+
--> $DIR/issue-103052-1.rs:5:20
11+
|
12+
LL | fn receive(_: impl std::process::Termination) {}
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `receive`
14+
15+
error: aborting due to previous error
16+
17+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![feature(return_position_impl_trait_in_trait)]
2+
#![allow(incomplete_features)]
3+
4+
mod child {
5+
trait Main {
6+
fn main() -> impl std::process::Termination;
7+
}
8+
9+
struct Something;
10+
11+
impl Main for () {
12+
fn main() -> Something { //~ ERROR the trait bound `Something: Termination` is not satisfied
13+
Something
14+
}
15+
}
16+
}
17+
18+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0277]: the trait bound `Something: Termination` is not satisfied
2+
--> $DIR/issue-103052-2.rs:12:22
3+
|
4+
LL | fn main() -> Something {
5+
| ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
6+
|
7+
note: required by a bound in `Main::main::{opaque#0}`
8+
--> $DIR/issue-103052-2.rs:6:27
9+
|
10+
LL | fn main() -> impl std::process::Termination;
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::main::{opaque#0}`
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0277`.

src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
error[E0277]: `main` has invalid return type `f32`
1+
error[E0277]: the trait bound `f32: Termination` is not satisfied
22
--> $DIR/termination-trait-test-wrong-type.rs:6:1
33
|
44
LL | #[test]
55
| ------- in this procedural macro expansion
66
LL | / fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
77
LL | | "0".parse()
88
LL | | }
9-
| |_^ `main` can only return types that implement `Termination`
9+
| |_^ the trait `Termination` is not implemented for `f32`
1010
|
11-
= help: the trait `Termination` is not implemented for `f32`
1211
= note: required for `Result<f32, ParseFloatError>` to implement `Termination`
1312
note: required by a bound in `assert_test_result`
1413
--> $SRC_DIR/test/src/lib.rs:LL:COL

0 commit comments

Comments
 (0)