impl StringExt for String {
fn replacement(&self) -> Self {
let replaced = NEWLINE_RE.replace_all(self, "\n");
let replaced = QUOTES_RE.replace_all(&replaced, "");
let replaced = LINKS_RE.replace_all(&replaced, |caps: &Captures| {
let caps_str: Vec<_> = caps
.iter()
.flat_map(|c| c.map(|c| c.as_str()))
.collect();
caps_str.last().unwrap()
//format!("{}", caps_str.last().unwrap())
});
replaced.into()
}
}
When I try to compile I'm getting following error about lifetimes:
error: lifetime may not live long enough
--> src/main.rs:72:13
|
67 | let replaced = LINKS_RE.replace_all(&replaced, |caps: &Captures| {
| ---- - return type of closure is &'2 &str
| |
| has type `®ex::Captures<'1>`
...
72 | caps_str.last().unwrap()
| ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
error[E0515]: cannot return value referencing local variable `caps_str`
--> src/main.rs:72:13
|
72 | caps_str.last().unwrap()
| --------^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `caps_str` is borrowed here
I can easily workaround it by using format, but of course I would like to know how to this proper. Using caps_str.last().cloned().unwrap() does not work either
Clone of a reference is still a reference. You need to return a String, so value wouldn't be lost when Vec<…> would be dropped. So… call to_owned there. Or maybe even into(), even that's a bit more cryptic.
impl<F, T> Replacer for F
where
F: for<'outer, 'inner> FnMut(&'outer Captures<'inner>) -> T,
T: AsRef<str>,
(It's possible to write a |caps: &Captures<'inner>| -> &'inner str, but in the above implementation, it's impossible for T to contain 'inner (or 'outer). It must be the same type for all the input lifetimes. That's why you need to return a String for replace_all.)
caps_str.last().unwrap() returns &'_ &'haystack str, and you want to return &'haystack str from the closure, so you need an additional dereference: *caps_str.last().unwrap()
as @quinedot pointed out, the impl Replacer for FnMut is formulated in such a way that the returned type T may not reference the "haystack" (because T does not depend on its lifetime).
If you want to avoid unnecessary allocations, you can create your own impl of Replacer that supports returning borrowed captures: