Skip to content

cargo init's boilerplate doesn't work with ? #14007

Open
@jsha

Description

@jsha

cargo init currently produces boilerplate that looks like this:

fn main() {
    println!("Hello, world!");
}

However, if someone starts from this boilerplate and pastes in examples from documentation that use ?, they'll get an error. main doesn't return Result, so ? can't be used. The API guidelines recommend that examples use ? rather than unwrap.

As an example, if someone tries to paste in this small File example:

use std::fs::File;
use std::io::prelude::*;

fn main() {
    let mut file = File::create("foo.txt")?;
    file.write_all(b"Hello, world!")?;
}

They get some rather confusing errors (what's FromResidual?):

error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> src/main.rs:5:43
    |
4   | / fn main() {
5   | |     let mut file = File::create("foo.txt")?;
    | |                                           ^ cannot use the `?` operator in a function that returns `()`
6   | |     file.write_all(b"Hello, world!")?;
7   | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
note: required by `from_residual`
   --> /home/jsha/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/try_trait.rs:339:5
    |
339 |     fn from_residual(residual: R) -> Self;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> src/main.rs:6:37
    |
4   | / fn main() {
5   | |     let mut file = File::create("foo.txt")?;
6   | |     file.write_all(b"Hello, world!")?;
    | |                                     ^ cannot use the `?` operator in a function that returns `()`
7   | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
    = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
note: required by `from_residual`
   --> /home/jsha/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/try_trait.rs:339:5
    |
339 |     fn from_residual(residual: R) -> Self;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

This is a problem I remember running into when I was first learning the language. I suspect it may be an issue for other language learners too.

I propose changing the boilerplate to:

use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    println!("Hello, world!");
    Ok(())
}

This compiles cleanly and passes clippy.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions