DedSec Project

E0502 — DedSec Project

Rust E0502 — immutable and mutable borrows overlap The conflicting lifetimes Rust allows multiple read-only references, or a unique mutable reference, but not both active on the same data…

Rust E0502 — immutable and mutable borrows overlap

The conflicting lifetimes

Rust allows multiple read-only references, or a unique mutable reference, but not both active on the same data. A Vec push may reallocate its backing buffer, invalidating references into it.

fn main() {
    let mut names = vec![String::from("Ada")];
    let first = &names[0];
    // names.push(String::from("Grace"));  // E0502 if first used below
    println!("{}", first);
    names.push(String::from("Grace")); // immutable borrow is finished
    assert_eq!(names.len(), 2);
}

Repair through phases

End the borrowing read before modifying the structure. For a membership check, return a boolean before mutating:

fn add_if_missing(names: &mut Vec<String>, candidate: &str) {
    let exists = names.iter().any(|name| name == candidate);
    if !exists { names.push(candidate.to_owned()); }
}

Test deliberately

Check an already-present value and a new value. Create a failing variation that uses first after push, then fix it without unsafe. For mutation of independent pieces of a slice, investigate split_at_mut, which gives nonoverlapping mutable references. RefCell has runtime borrow checks and is not a generic fix for poorly scoped references.

Reference: https://doc.rust-lang.org/error_codes/E0502.html

Why storing indices can be safer than storing borrows

A Vec may grow its allocation after push, so holding &names[0] across that mutation is invalid. Store index 0 instead, append another element, and only then borrow &names[0]. Verify the first element is still "Ada" and the final length is two. If you need a snapshot independent of future mutations, let first = names[0].clone() has different allocation semantics. A borrow that is never used after push ends before the mutation under non-lexical lifetimes. Do not conclude that an earlier let first = &names[0] is forbidden by itself.