Why I need to specify 'static file time in .parse()?

Hi everybody

I have two questions about this code:

  1. Why do I need 'static filetime in <T as FromStr>::Err: 'static.
    My understand is that <T as FromStr>::Err can have the same lifetime that &self has but, if I try to put a 'a in self, it doesn't compile
  2. Do I need to repeat that where clause in the implementation?

The 'static lifetime error

   Compiling gitignore v0.1.0 (/Users/gecko/code/gitignore)
error[E0310]: the associated type `<T as std::str::FromStr>::Err` may not live long enough
   --> src/lib.rs:249:39
    |
249 |                 let n = x.parse::<T>()?;
    |                                       ^
    |
    = help: consider adding an explicit lifetime bound `<T as std::str::FromStr>::Err: 'static`...
note: ...so that the type `<T as std::str::FromStr>::Err` will meet its required lifetime bounds
   --> src/lib.rs:249:39
    |
249 |                 let n = x.parse::<T>()?;
    |                                       ^

error: aborting due to previous error

The code

fn main() {
        use std::error::Error;
        use std::fmt::Debug;
        use std::ops::Range;
        use std::str::FromStr;

        trait ToRange {
            fn to_range<T>(&self) -> Result<Range<T>, Box<dyn Error>>
            where
                T: FromStr + PartialOrd + Copy,
                <T as FromStr>::Err: Debug + Error,
                <T as FromStr>::Err: 'static;
        }

        impl ToRange for &str {
            fn to_range<T>(&self) -> Result<Range<T>, Box<dyn Error>>
            where
                T: FromStr + PartialOrd + Copy,
                <T as FromStr>::Err: Debug + Error,
                <T as FromStr>::Err: 'static,
            {
                let mut vec = Vec::new();
                let xs = self.splitn(2, "..");
                for x in xs {
                    let n = x.parse::<T>()?;
                    vec.push(n);
                }

                Ok(vec[0]..vec[1])
            }
        }

        println!("{:?}", "0..1".to_range::<i32>().unwrap());
}

(Playground)

Box by default forbids temporary references (has default 'static bound), since it usually doesn't make sense to crate an owned heap-allocated object that is still effectively temporary.

You can relax that bound by saying the error can borrow something temporary from self:


        trait ToRange {
            fn to_range<'tmp, T>(&'tmp self) -> Result<Range<T>, Box<dyn Error + 'tmp>>
            where
                T: FromStr + PartialOrd + Copy,
                <T as FromStr>::Err: Debug + Error + 'tmp;
        }
1 Like

Ohh so problem was with Box not parse, thanks!

Yeah, type inference also reasons "backwards" from return types.

1 Like

Is this 'static defined by the Any blank implementation of Box?

https://doc.rust-lang.org/std/boxed/struct.Box.html#blanket-implementations

You don't need to bind self, this is overly restrictive because FromStr::Err can't depend on the lifetime of the input string.

  trait ToRange {
            fn to_range<'tmp, T>(&self) -> Result<Range<T>, Box<dyn Error + 'tmp>>
            where
                T: FromStr + PartialOrd + Copy,
                <T as FromStr>::Err: Debug + Error + 'tmp;
        }
1 Like