Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggest using !/Infallibe in trait implementations with a result type. #4644

Open
Luro02 opened this issue Oct 8, 2019 · 0 comments
Open
Labels
A-lint Area: New lints E-medium Call for participation: Medium difficulty level problem and requires some initial experience. L-perf Lint: Belongs in the perf lint group L-style Lint: Belongs in the style lint group

Comments

@Luro02
Copy link

Luro02 commented Oct 8, 2019

When a user implements a trait, where the function signature returns a result (like in FromStr or TryFrom) and the function body doesn't return an error, the lint should suggest to use Infallible or ! (! isn't stabilized yet, rust-lang/rust#35121).

What it does

Checks for trait implementations, where the function signature returns a Result<T, E> and the body doesn't return the error-variant.

Why is this bad

Using ! or an enum like Infallible , that can not be constructed, allows the compiler to better optimize the code (similar to unreachable!).

Example

use std::str::FromStr;

struct ExampleStruct(String);

impl FromStr for ExampleStruct {
    type Err = Box<dyn std::error::Error>;

    fn from_str(input: &str) -> Result<Self, Self::Err> {
        Ok(Self(input.to_string()))
    }
}

better

use std::str::FromStr;

struct ExampleStruct(String);

impl FromStr for ExampleStruct {
    type Err = std::convert::Infallible;

    fn from_str(input: &str) -> Result<Self, Self::Err> {
        Ok(Self(input.to_string()))
    }
}

even better (! isn't stabilized yet)

use std::str::FromStr;

struct ExampleStruct(String);

impl FromStr for ExampleStruct {
    type Err = !;

    fn from_str(input: &str) -> Result<Self, Self::Err> {
        Ok(Self(input.to_string()))
    }
}

This lint could be generalized to lint against all kind of functions like

struct ExampleStruct(String);

impl ExampleStruct {
    pub fn as_str(&self) -> Result<&str, Box<dyn std::error::Error> {
        Ok(self.0.as_str())
    }
}

but some of them might be intentional, to not break future versions.

In the above example it might be better to drop the Result type, which cannot be done for trait implementations. (hence the lint)

@flip1995 flip1995 added L-perf Lint: Belongs in the perf lint group L-style Lint: Belongs in the style lint group E-medium Call for participation: Medium difficulty level problem and requires some initial experience. A-lint Area: New lints labels Oct 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints E-medium Call for participation: Medium difficulty level problem and requires some initial experience. L-perf Lint: Belongs in the perf lint group L-style Lint: Belongs in the style lint group
Projects
None yet
Development

No branches or pull requests

2 participants