Description
Continuing the thread from the forum. Rust gives a warning that this is potentially UB:
let r = Regex::new("aaa")?;
r.replace_all("aaa", |c: &Captures<'_> | {
c.get(0).unwrap().as_str()
});
In the Replacer
trait, there's no place to define that the returned T: AsRef<str>
lives at least as long as '_
in Captures<'_>
.
This becomes more evident if you try to use explicit &str
as the return type. There's just no way to compile it with 'a: 't
or similar requirement:
impl<'a, F> Replacer for F where F: for<'t> FnMut(&Captures<'t>) -> &'a str {
fn replace_append<'t>(&mut self, caps: &Captures<'t>, dst: &mut String) {
dst.push_str((*self)(caps).as_ref());
}
}
As far as I understand, the difficulty here is that the lifetime in question is inside of function arguments in the trait, but needs to be named outside of it in the closure type. There's just no syntax for such thing.
Ability to return some of the captures for replacement seems quite useful, but having a scary warning for this, and potentially UB or fatal error in the future, is not good.
-
Is there some clever syntax/generics/lifetimes solution that would make it work?
-
Can closures be made to work some other way, via wrapper type, or another function call?
-
Should Rust add some syntax, or make the borrow checker more clever, to make the existing solution acceptable?