Skip to content

Commit

Permalink
Rollup merge of #103142 - fmease:fix-103052, r=oli-obk
Browse files Browse the repository at this point in the history
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
  • Loading branch information
JohnTitor authored Oct 18, 2022
2 parents 56e4123 + 684df4d commit 472a874
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 5 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ symbols! {
call_once,
caller_location,
capture_disjoint_fields,
cause,
cdylib,
ceilf32,
ceilf64,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
}

if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
flags.push((sym::cause, Some("MainFunctionType".to_string())));
}

// Add all types without trimmed paths.
ty::print::with_no_trimmed_paths!({
let generics = self.tcx.generics_of(def_id);
Expand Down
12 changes: 10 additions & 2 deletions library/std/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2154,8 +2154,16 @@ pub fn id() -> u32 {
#[cfg_attr(not(test), lang = "termination")]
#[stable(feature = "termination_trait_lib", since = "1.61.0")]
#[rustc_on_unimplemented(
message = "`main` has invalid return type `{Self}`",
label = "`main` can only return types that implement `{Termination}`"
on(
all(not(bootstrap), cause = "MainFunctionType"),
message = "`main` has invalid return type `{Self}`",
label = "`main` can only return types that implement `{Termination}`"
),
on(
bootstrap,
message = "`main` has invalid return type `{Self}`",
label = "`main` can only return types that implement `{Termination}`"
)
)]
pub trait Termination {
/// Is called to get the representation of the value as status code.
Expand Down
11 changes: 11 additions & 0 deletions src/test/ui/rfc-1937-termination-trait/issue-103052-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Check that we don't blindly emit a diagnostic claiming that "`main` has an invalid return type"
// if we encounter a type that doesn't implement `std::process::Termination` and is not actually
// the return type of the program entry `main`.

fn receive(_: impl std::process::Termination) {}

struct Something;

fn main() {
receive(Something); //~ ERROR the trait bound `Something: Termination` is not satisfied
}
17 changes: 17 additions & 0 deletions src/test/ui/rfc-1937-termination-trait/issue-103052-1.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0277]: the trait bound `Something: Termination` is not satisfied
--> $DIR/issue-103052-1.rs:10:13
|
LL | receive(Something);
| ------- ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
| |
| required by a bound introduced by this call
|
note: required by a bound in `receive`
--> $DIR/issue-103052-1.rs:5:20
|
LL | fn receive(_: impl std::process::Termination) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `receive`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
18 changes: 18 additions & 0 deletions src/test/ui/rfc-1937-termination-trait/issue-103052-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#![feature(return_position_impl_trait_in_trait)]
#![allow(incomplete_features)]

mod child {
trait Main {
fn main() -> impl std::process::Termination;
}

struct Something;

impl Main for () {
fn main() -> Something { //~ ERROR the trait bound `Something: Termination` is not satisfied
Something
}
}
}

fn main() {}
15 changes: 15 additions & 0 deletions src/test/ui/rfc-1937-termination-trait/issue-103052-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0277]: the trait bound `Something: Termination` is not satisfied
--> $DIR/issue-103052-2.rs:12:22
|
LL | fn main() -> Something {
| ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
|
note: required by a bound in `Main::main::{opaque#0}`
--> $DIR/issue-103052-2.rs:6:27
|
LL | fn main() -> impl std::process::Termination;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::main::{opaque#0}`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
error[E0277]: `main` has invalid return type `f32`
error[E0277]: the trait bound `f32: Termination` is not satisfied
--> $DIR/termination-trait-test-wrong-type.rs:6:1
|
LL | #[test]
| ------- in this procedural macro expansion
LL | / fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
LL | | "0".parse()
LL | | }
| |_^ `main` can only return types that implement `Termination`
| |_^ the trait `Termination` is not implemented for `f32`
|
= help: the trait `Termination` is not implemented for `f32`
= note: required for `Result<f32, ParseFloatError>` to implement `Termination`
note: required by a bound in `assert_test_result`
--> $SRC_DIR/test/src/lib.rs:LL:COL
Expand Down

0 comments on commit 472a874

Please sign in to comment.