HRTBs to the rescue. The problem here is that you create the string slice Ainside of f. Therefore you, f, the callee decides what the lifetime 'a is (some unnamable lifetime that exists inside of your function). But if you have a generic lifetime parameter 'a on f, the caller (i.e. in this case your main function) must decide what 'a is supposed to be. Because we don't allow main to specify 'a, we violate the contract of a generic (lifetime) parameter. The solution is to not expose 'a that way and instead have it as a higher ranked trait bound on A, which means that A implements TryFrom<&'a str> for any lifetime 'a, including the unnamable one that exists inside of f.
use std::fmt::Debug;
pub enum PubType {
Print,
Online,
}
impl TryFrom<&str> for PubType {
type Error = ();
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value {
"print" => Ok(PubType::Print),
"online" => Ok(PubType::Online),
_ => Err(()),
}
}
}
fn f<A>() -> Option<A>
where
for<'a> A: TryFrom<&'a str>,
for<'a> <A as TryFrom<&'a str>>::Error: Debug,
{
// get value
let value: Option<String> = Some("foo".to_owned());
// parse value
value.map(|s| A::try_from(&s).expect("get_try_from_opt"))
}
fn main() {
let _x: Option<PubType> = f();
}