Exit from main using a custom type

Hi all,

The Termination trait is implemented for Result<T,E> but uses the Debug trait when an error occurs:

impl<T: Termination, E: fmt::Debug> Termination for Result<T, E> {
    fn report(self) -> ExitCode {
        match self {
            Ok(val) => val.report(),
            Err(err) => {
                io::attempt_print_to_stderr(format_args_nl!("Error: {err:?}"));
                ExitCode::FAILURE
            }
        }
    }
}

Returning from main is only possible for Result or Option, and the Try trait is not yet stable.

Any idea to return from main using ? in the code but using the Display trait ?

Thanks for your help.

The easiest way is probably to just wrap your cod in another function:

use std::process::ExitCode;
use std::process::Termination;

fn main() -> ExitCode {
    match run() {
        Ok(val) => val.report(),
        Err(err) => {
            eprintln!("Error: {err}");
            ExitCode::FAILURE
        }
    }
}

fn run() -> Result<(), String> {
    Err("\\")?
}
5 Likes

Or maybe it is feasible to implement Debug for your error type by simply forwarding it to its Display implementation?

2 Likes

@jofas the problem is that the TerminationT impl for Result<T,E> will print out "Error:" in front of every error.

Iā€™d consider main being able to return a Result a fun piece of trivia at least for now, not something useful except in tiny fire-and-forget programs. Better to just delegate to another function and handle its return value in main however you like.

1 Like

I use main returning anyhow::Result<()> in nearly every program I write - it's there not as the "normal" error handling path, but as a back-stop for cases where I think the error handling is never going to come into play.

This then means that things that can return an error that I think "will never happen" use ? to return it from main, instead of unwrap() - but any error that I expect to handle is handled separately before I get this far.