Lifetime confusion around replace_all closures. #775
-
I am trying to pass a closure to My initial solution was to return a use std::borrow::Cow;
use regex::{Captures, Regex};
fn replace<'a>(input: &'a str) -> Cow<'a, str> {
let pattern = Regex::new("foo(bar)?").unwrap();
pattern.replace_all(input, |cap: &Captures| expand(cap))
}
fn expand<'a>(cap: &Captures<'a>) -> Cow<'a, str> {
Cow::Borrowed(cap.get(0).unwrap().as_str())
} The compiler is happy with the expand function so I'm assuming that the lifetimes are valid there but the closure in the replace function is not accepted
As far as I can see, the specifiers in the expand method say that the lifetime of the returned Cow is the same as the lifetime of the Captures passed in but the compiler sees them as different, Where is my intuition going wrong here? And is there a way to do this so that the compiler is happy without returning a new String from the expand method every time? From discussion on reddit, this can be worked around by passing the original &str to the expand method and returning a slice of that instead. I'd assumed that the lifetimes of the input &str and the matched &str would be the same. fn replace<'a>(input: &'a str) -> Cow<'a, str> {
let pattern = Regex::new("foo(bar)?").unwrap();
pattern.replace_all(input, |cap: &Captures| expand(input, cap))
}
fn expand<'a>(input: &'a str, cap: &Captures) -> Cow<'a, str> {
Cow::Borrowed(&input[cap.get(0).unwrap().range()])
} |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 8 replies
-
NOTE: See @sgrif's comments below and their PR in #776 for the actual answer. I also created #777 to track this particular issue, since it can't be fixed until a hypothetical I believe the issue rests in how
I think the key part is this: F: FnMut(&Captures<'_>) -> T,
T: AsRef<str>, That is, there is nothing connecting the lifetime of I'm not particularly confident in this answer. I'll broadcast this and see if someone smarter than me can figure this out and whether there's a work-around. |
Beta Was this translation helpful? Give feedback.
-
See this post on URLO for a possible workaround using a newtype wrapper and unstable/experimental closure lifetime binders. |
Beta Was this translation helpful? Give feedback.
NOTE: See @sgrif's comments below and their PR in #776 for the actual answer. I also created #777 to track this particular issue, since it can't be fixed until a hypothetical
regex 2.0.0
release.I believe the issue rests in how
Replacer
is implemented for closure types:I think the key part is this:
That is, there is nothing connecting the lifetime of
'_
in&Captures<'_>
withT
. So in a generic context, I guess that the com…