How do I implement FromStr with a concrete lifetime?

匆匆过客 提交于 2020-01-10 05:10:49

问题


I want to implement FromStr for a struct with a lifetime parameter:

use std::str::FromStr;

struct Foo<'a> {
    bar: &'a str,
}

impl<'a> FromStr for Foo<'a> {
    type Err = ();
    fn from_str(s: &str) -> Result<Foo<'a>, ()> {

        Ok(Foo { bar: s })
    }
}

pub fn main() {
    let foo: Foo = "foobar".parse().unwrap();
}

However, the compiler complains:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/main.rs:11:12
   |
11 |         Ok(Foo { bar: s })
   |            ^^^
   |
help: consider using an explicit lifetime parameter as shown: fn from_str(s: &'a str) -> Result<Foo<'a>, ()>
  --> src/main.rs:9:5
   |
9  |     fn from_str(s: &str) -> Result<Foo<'a>, ()> {
   |     ^

Changing the impl to

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

gives this error

error[E0308]: method not compatible with trait
  --> src/main.rs:9:5
   |
9  |     fn from_str(s: &'a str) -> Result<Foo<'a>, ()> {
   |     ^ lifetime mismatch
   |
   = note: expected type `fn(&str) -> std::result::Result<Foo<'a>, ()>`
   = note:    found type `fn(&'a str) -> std::result::Result<Foo<'a>, ()>`
note: the anonymous lifetime #1 defined on the block at 9:51...
  --> src/main.rs:9:52
   |
9  |     fn from_str(s: &'a str) -> Result<Foo<'a>, ()> {
   |                                                    ^
note: ...does not necessarily outlive the lifetime 'a as defined on the block at 9:51
  --> src/main.rs:9:52
   |
9  |     fn from_str(s: &'a str) -> Result<Foo<'a>, ()> {
   |                                                    ^
help: consider using an explicit lifetime parameter as shown: fn from_str(s: &'a str) -> Result<Foo<'a>, ()>
  --> src/main.rs:9:5
   |
9  |     fn from_str(s: &'a str) -> Result<Foo<'a>, ()> {
   |     ^

Playpen


回答1:


I don't believe that you can implement FromStr in this case.

fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err>;

There's nothing in the trait definition that ties the lifetime of the input to the lifetime of the output.

Not a direct answer, but I'd just suggest making a constructor that accepts the reference:

struct Foo<'a> {
    bar: &'a str
}

impl<'a> Foo<'a> {
    fn new(s: &str) -> Foo {
        Foo { bar: s }
    }
}

pub fn main() {
    let foo = Foo::new("foobar"); 
}

This has the side benefit of there not being any failure modes - no need to unwrap.

You could also just implement From:

struct Foo<'a> {
    bar: &'a str,
}

impl<'a> From<&'a str> for Foo<'a> {
    fn from(s: &'a str) -> Foo<'a> {
        Foo { bar: s }
    }
}

pub fn main() {
    let foo: Foo = "foobar".into();
}


来源:https://stackoverflow.com/questions/28931515/how-do-i-implement-fromstr-with-a-concrete-lifetime

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!