rust-lang / rust-clippy

A bunch of lints to catch common mistakes and improve your Rust code. Book: https://doc.rust-lang.org/clippy/
https://rust-lang.github.io/rust-clippy/
Other
11.38k stars 1.54k forks source link

should_implement_trait should not be triggered by from_str with explicit type annotation #1731

Open SamWhited opened 7 years ago

SamWhited commented 7 years ago
warning: defining a method called `from_str` on this type; consider implementing the `std::str::FromStr` trait or choosing a less ambiguous name
   --> src/lib.rs:222:5
    |
222 | /     pub fn from_str(s: &'a str) -> Result<JID<'a>> {
223 | |         if s == "" {
224 | |             return Err(Error::EmptyJID);
225 | |         }
...   |
305 | |         JID::new(lpart, dpart.trim_right_matches('.'), rpart)
306 | |     }
    | |_____^
    |
    = note: #[warn(should_implement_trait)] on by default
    = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#should_implement_trait

For types that require an explicit type annotation, it is sometimes impossible to implement FromStr because its argument does not have a type annotation. For instance, consider the following:

use std::borrow;
use std::str;

struct JID<'a> {
    local: borrow::Cow<'a, str>,
}

struct DummyErr {}

impl<'a> str::FromStr for JID<'a> {
    type Err = DummyErr;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        // We can not guarantee that s lives longer than 'a
        Ok(JID { local: s.into() })
    }
}

Since we can never guarantee that the &str lives longer than 'a, FromStr cannot be implemented for this type.

Naming the method something else goes against the API guidelines (although admittedly it is confusing naming it the same thing as a method on a common trait).

Related: #1600

clarfonthey commented 7 years ago

One thing to note is that once TryFrom is stabilised this will be possible.

impl<'a> TryFrom<&'a str> for JID<'a> {
    type Err = DummyErr;
    fn try_from(s: &'a str) -> Result<Self, Self::Err> { ... }
}