Explanation of Restricted Borrowing
⚓ Rust 📅 2026-02-03 👤 surdeus 👁️ 8The following code:
#[derive(Debug, thiserror::Error)]
enum Error<'p, 'v> {
#[error("Remaining parameters are invalid: {remaining:?}")]
InvalidRemaining { remaining: &'p str },
#[error("Parameter name is too long: {parameter:?}")]
NameTooLong { parameter: &'p str },
}
fn read_cmdline_while<const N: usize>(
cmdline: &mut Peekable<Chars>,
buffer: &mut heapless::String<N>,
mut predicate: impl FnMut(char) -> bool,
) -> Result<usize, CapacityError> {
buffer.clear();
while let Some(c) = cmdline.next_if(|c| predicate(*c)) {
buffer.push(c)?;
}
Ok(buffer.len())
}
fn read_parameter_name<'p, 'v>(
cmdline: &mut Peekable<Chars>,
name_buffer: &'p mut heapless::String::<128>,
) -> Result<(), Error<'p, 'v>> {
read_cmdline_while(cmdline, name_buffer, |c| c.is_alphanumeric() || c == '_')
.map_err(|_| Error::NameTooLong {
parameter: name_buffer.as_str(),
})
.and_then(|char_count_read| {
// Check if there were no valid parameter name chars.
if char_count_read > 0 || cmdline.peek().is_none() {
Ok(())
} else {
read_cmdline_while(cmdline, name_buffer, |_| true).ok();
Err(Error::InvalidRemaining {
remaining: name_buffer.as_str(),
})
}
})
}
results in the following error:
error[E0500]: closure requires unique access to `*name_buffer` but it is already borrowed
--> src/params.rs:147:19
|
139 | fn read_parameter_name<'p, 'v>(
| -- lifetime `'p` defined here
...
143 | / read_cmdline_while(cmdline, name_buffer, |c| c.is_alphanumeric() || c == '_')
144 | | .map_err(|_| Error::NameTooLong {
| | --- borrow occurs here
145 | | parameter: name_buffer.as_str(),
| | ----------- first borrow occurs due to use of `*name_buffer` in closure
146 | | })
147 | | .and_then(|char_count_read| {
| | ^^^^^^^^^^^^^^^^^ closure construction occurs here
... |
152 | | read_cmdline_while(cmdline, name_buffer, |_| true).ok();
| | ----------- second borrow occurs due to use of `*name_buffer` in closure
... |
158 | | })
| |__________- returning this value requires that `*name_buffer` is borrowed for `'p`
I do not understand how this borrowing failure is occurring. In no circumstance will name_buffer be borrowed in the .and_then closure, as it is only borrowed in the case of the call to Result::<(), heapless::CapacityError>::map_err—in which case, the .and_then closure is never called.
If anyone could elucidate the failure in my understanding—and potentially explain a solution to the above issue—I would be very grateful.
6 posts - 4 participants
🏷️ Rust_feed