Borrow held even though nothing is borrowed
⚓ Rust 📅 2026-02-10 👤 surdeus 👁️ 1I have some trouble getting the borrow checker to understand my intentions. The following is a simplified version of my code: a next method tries to generate an Object (which borrows data) from a byte array at an index, advances the index into the byte array, and returns the Object. Once no more Objects can be generated (Object::get returns None), the potential rest of the array is discarded and the index is reset. But even though Object::get returned None, the borrow checker still declares the data as borrowed, and disallows the discarding:
struct Buffer {
content: Vec<u8>,
index: usize,
}
impl Buffer {
// Fails to compile
fn next(&mut self) -> Option<Object> {
if let Some(obj) = Object::get(&self.content[self.index..]) {
self.index += 1; // Example consumes only 1 byte, real code can consume multiple
return Some(obj);
}
// `Object::get` returned `None`, so I expect nothing to be borrowed at this point.
self.content.clear(); // error[E0502]: cannot borrow `self.content` as mutable, since it is already borrowed
self.index = 0;
None
}
}
#[derive(Debug)]
struct Object<'a>(&'a u8);
impl<'a> Object<'a> {
fn get(buffer: &'a [u8]) -> Option<Self> {
buffer.get(0).map(|b| Self(b))
}
}
Instead of if-let I tried other control flow constructs like match and let-else, with the same (consistent) outcome. The following two variants do compile, but have their own issues:
// Compiles: Does not return an `Object`, no borrow checker issues.
fn next_no_return(&mut self) {
if let Some(obj) = Object::get(&self.content[self.index..]) {
println!("{obj:?}");
self.index += 1;
return;
}
self.content.clear(); // no error
self.index = 0;
}
// Compiles: Parses the current object 2 times, now it's OK for the borrow checker.
fn next_parse_twice(&mut self) -> Option<Object> {
if let Some(_obj) = Object::get(&self.content[self.offset..]) {
let reparsed_result = Object::get(&self.content[self.offset..]);
self.index += 1;
return reparsed_result;
}
self.content.clear(); // no error
self.index = 0;
None
}
How can I modify the original example to get it past the borrow checker?
4 posts - 3 participants
🏷️ Rust_feed