4

Rust FromStr trait is defined like this

pub trait FromStr {
    type Err;
    fn from_str(s: &str) -> Result<Self, Self::Err>;
}

It does not name its lifetime and one cannot implement that trait for something containing reference to source string, for example:

struct MyIterator<'a> {
    cur_pointer: &'a str
}

impl<'a> FromStr for MyIterator<'a> {
    type Err = i32;
    fn from_str(s: &'a str) -> Result<Self, Self::Err> {
        Ok(MyIterator { cur_pointer: s })
    }
}

gives error

method `from_str` has an incompatible type for trait: expected bound lifetime parameter , found concrete lifetime [E0053]

By far I found no way to implement FromStr for MyIterator. I assume that is because original trait did not expose string's lifetime in its parameters. My first question is: am I right that there is no way to implement FromStr for MyIterator? If I'm wrong, what is a way to do it (assuming MyIterator wants to keep reference to original string)?

By now I found only this question: How do I implement FromStr with a concrete lifetime?, but best answer starts with "I don't believe that you can implement", so I want to be sure this is really impossible in Rust 1.0.0.

Now, if trait definition was like that:

trait MyFromStr<'a> {
    type Err;
    fn from_str(s: &'a str) -> Result<Self, Self::Err>;
}

one could implement it for types containing references to original string and not containing references to original string:

struct MyIterator<'a> {
    cur_pointer: &'a str
}

impl<'a> MyFromStr<'a> for MyIterator<'a> {
    type Err = i32;
    fn from_str(s: &'a str) -> Result<Self, Self::Err> {
        Ok(MyIterator { cur_pointer: s })
    }
}

struct MyCopy {
    val: String
}

impl<'a> MyFromStr<'a> for MyCopy {
    type Err = i32;
    fn from_str(s: &'a str) -> Result<Self, Self::Err> {
        Ok(MyCopy { val: s.to_string() })
    }
}

My second question is: is there any particular reason that trait FromStr does not expose lifetime? Maybe I misunderstand something about lifetimes and exposing lifetime has drawbacks?

Community
  • 1
  • 1
Slava Baginov
  • 949
  • 1
  • 8
  • 10

1 Answers1

9

Including the lifetime makes the trait more complicated and, more specifically, makes generic code using that trait more verbose (carrying around an unneeded lifetime). fn foo<T: FromStr> would no longer work.

It's also unnecessary for the intended uses of strings. Usually you parse from a string and use the result without worrying about the string. It's certainly easier to code that way. Many types don't need the lifetime anyway (see the long list of types implementing it).

You can't implement FromStr for this type. What you can do is

impl<'a> From<&'a str> for MyIterator<'a> { ... }

This gives you a lot of generic conversion machinery, just not the method str::parse(). Perhaps the name of that method is another argument for the omission of the lifetime.

  • Thanks a lot for that answer! I really missed that if lifetime is exposed, trait cannot be easily used as a type parameter. – Slava Baginov May 20 '15 at 18:49