rust-lang / rust-lang/rust-clippy

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

Open
#4,644 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-lint E-medium L-perf L-style
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

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, https://github.com/rust-lang/rust/issues/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)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the proposed FromStr and TryFrom trait-implementation examples and the distinction between Infallible and the unstable ! type. Define the lint's supported scope, including whether it should cover only trait implementations or general Result-returning functions, and consider the suggested behavior complete when the intended cases are specified without changing potentially intentional APIs.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
devtools
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.