fn parse_foo_from_string<'a>(input: String, results: &mut Vec<Foo<'a>>) {
let tmp = input.as_str();
parse_foo(tmp, results);
drop(tmp);
drop(input);
// from this point any use of results causes crash
}
You have to change parse_foo<'a>(input: &'a str to take ownership of the input, e.g. parse_foo<'a>(input: Cow<'a, str>, so that it can store owned Cow, and call it with parse_foo(input.into()
Firstly, I agreed. The parse_foo_from_string function will definitely cause use after free error. Rust is able to prevent such problems by introducing lifetime. The parse_foo requires the input to live as long as the Foo struct while input is getting dropped right before parse_foo_from_string finishes. So the compiler goes crazy. This is what I mean, "lifetime issue".
Then, taking a Cow<'a, str> instead of &str actually doesn't change nothing. You still have to check whether the input is owned or not:
fn parse<'a>(input: Cow<'a, str>, results: &mut Vec<Cow<'a, str>>) {
match input {
Cow::Borrowed(s) => {
for bar in s.split(' ').filter(|s| !s.is_empty()) {
results.push(Cow::Borrowed(bar))
}
}
Cow::Owned(s) => {
for bar in s.split(' ').filter(|s| !s.is_empty()) {
results.push(Cow::Owned(bar.into()))
}
}
}
}
The only thing different is that we now have a long function instead of two short functions.