Hello,
This is something I've been wrestling with for a while. Basically, I have a function that takes a collection of strings and may return an error containing a reference to one of those strings:
#[derive(PartialEq, Debug)]
pub enum SomeError<'a> {
BadThing(&'a str)
}
impl<'a> std::fmt::Display for SomeError<'a> { /* implementation */ }
impl<'a> std::error::Error for SomeError<'a> { /* implementation */ }
pub fn do_something<'a>(things: &[&'a str]) -> Result<(), SomeError<'a>> {
Err(SomeError::BadThing(things[0]))
}
However, because it's a public function and all I need to do with the collection is iterate through it, I'd rather not enforce the type of the collection:
pub fn do_something<'a, I, S>(things: I) -> Result<(), SomeError<'a, S>>
where I: std::iter::Iterator<Item=S> + Clone, // Clone because I want to make several passes
S: AsRef<str> + 'a { /* implementation */ }
Despite S
having a lifetime, the as_ref()
function won't return a reference with one because it's not passed to AsRef
's type parameter, so SomeError
needs to use this generic type as well. But because of the Display
and Error
implementations for SomeError
this requires some more trait restraints for S
, eventually leading to this monstrosity:
#[derive(PartialEq, Debug)]
pub enum SomeError<'a, S>
where S: AsRef<str> + std::marker::Reflect + std::fmt::Debug + 'a {
BadThing(S)
}
impl<'a, S> std::fmt::Display for SomeError<'a, S>
where S: AsRef<str> + std::marker::Reflect + std::fmt::Debug + 'a { /* implementation */ }
impl<'a, S> std::error::Error for SomeError<'a, S>
where S: AsRef<str> + std::marker::Reflect + std::fmt::Debug + 'a { /* implementation */ }
pub fn do_something<'a, I, S>(things: I) -> Result<(), SomeError<'a, S>>
where I: std::iter::Iterator<Item=S> + Clone,
S: AsRef<str> + std::marker::Reflect + std::fmt::Debug + 'a {
Err(SomeError::BadThing(things.next().unwrap()))
}
I have two issues with this code: one is, that it still doesn't compile. It gives the error parameter 'a is never used [E0392]
for SomeError
despite being a requirement for S
. The second thing is, it really doesn't feel like this is the way I should be doing this. Is there any, perhaps more "rustic"(?), way of doing this at all?
Thanks.