I'm just playing around with making versions of the trim*
/strip*
family of functions that operate on a String
by modifying it instead of returning a &str
, and I'm running into an annoying problem.
When it comes to trim_matches
, its signature is as follows:
pub fn trim_matches<'a, P>(&'a self, pat: P) -> &'a str
where
P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>,
This works fine when you return a slice, but since I'm operating on a &mut String
, I'm running into troubles with lifetimes, presumably due to variance. My method is
fn trim_matches_in_place<'a, P>(&'a mut self, pat: P)
where
P: Pattern<'a>,
<P as Pattern<'a>>::Searcher: DoubleEndedSearcher<'a>,
{
let trimmed = self.trim_matches(pat);
let (start_offset, end_offset) = get_str_offsets(self, trimmed);
self.trim_start_bytes(start_offset);
self.trim_end_bytes(end_offset);
}
and this is what the compiler tells me:
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src\string_extensions.rs:240:9
|
233 | fn trim_matches_in_place<'a, P>(&'a mut self, pat: P)
| -- lifetime `'a` defined here
...
238 | let trimmed = self.trim_matches(pat);
| ----------------------
| |
| immutable borrow occurs here
| argument requires that `*self` is borrowed for `'a`
239 | let (start_offset, end_offset) = get_str_offsets(self, trimmed);
240 | self.trim_start_bytes(start_offset);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
I think this is invariance coming to bite me in the ass, but it feels like the compiler is misunderstanding here, because once the call to trim_matches
returns, that borrow is no longer needed. Is this solvable? I'd rather avoid unsafe if I can, but to me, this feels like there's something off about the way the trim_matches
API works.