4.9 KiB
4.9 KiB
Common Ownership Errors & Fixes
E0382: Use of Moved Value
Error Pattern
let s = String::from("hello");
let s2 = s; // s moved here
println!("{}", s); // ERROR: value borrowed after move
Fix Options
Option 1: Clone (if ownership not needed)
let s = String::from("hello");
let s2 = s.clone(); // s is cloned
println!("{}", s); // OK: s still valid
Option 2: Borrow (if modification not needed)
let s = String::from("hello");
let s2 = &s; // borrow, not move
println!("{}", s); // OK
println!("{}", s2); // OK
Option 3: Use Rc/Arc (for shared ownership)
use std::rc::Rc;
let s = Rc::new(String::from("hello"));
let s2 = Rc::clone(&s); // shared ownership
println!("{}", s); // OK
println!("{}", s2); // OK
E0597: Borrowed Value Does Not Live Long Enough
Error Pattern
fn get_str() -> &str {
let s = String::from("hello");
&s // ERROR: s dropped here, but reference returned
}
Fix Options
Option 1: Return owned value
fn get_str() -> String {
String::from("hello") // return owned value
}
Option 2: Use 'static lifetime
fn get_str() -> &'static str {
"hello" // string literal has 'static lifetime
}
Option 3: Accept reference parameter
fn get_str<'a>(s: &'a str) -> &'a str {
s // return reference with same lifetime as input
}
E0499: Cannot Borrow as Mutable More Than Once
Error Pattern
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s; // ERROR: second mutable borrow
println!("{}, {}", r1, r2);
Fix Options
Option 1: Sequential borrows
let mut s = String::from("hello");
{
let r1 = &mut s;
r1.push_str(" world");
} // r1 goes out of scope
let r2 = &mut s; // OK: r1 no longer exists
Option 2: Use RefCell for interior mutability
use std::cell::RefCell;
let s = RefCell::new(String::from("hello"));
let mut r1 = s.borrow_mut();
// drop r1 before borrowing again
drop(r1);
let mut r2 = s.borrow_mut();
E0502: Cannot Borrow as Mutable While Immutable Borrow Exists
Error Pattern
let mut v = vec![1, 2, 3];
let first = &v[0]; // immutable borrow
v.push(4); // ERROR: mutable borrow while immutable exists
println!("{}", first);
Fix Options
Option 1: Finish using immutable borrow first
let mut v = vec![1, 2, 3];
let first = v[0]; // copy value, not borrow
v.push(4); // OK
println!("{}", first); // OK: using copied value
Option 2: Clone before mutating
let mut v = vec![1, 2, 3];
let first = v[0].clone(); // if T: Clone
v.push(4);
println!("{}", first);
E0507: Cannot Move Out of Borrowed Content
Error Pattern
fn take_string(s: &String) {
let moved = *s; // ERROR: cannot move out of borrowed content
}
Fix Options
Option 1: Clone
fn take_string(s: &String) {
let cloned = s.clone();
}
Option 2: Take ownership in function signature
fn take_string(s: String) { // take ownership
let moved = s;
}
Option 3: Use mem::take for Option/Default types
fn take_from_option(opt: &mut Option<String>) -> Option<String> {
std::mem::take(opt) // replaces with None, returns owned value
}
E0515: Return Local Reference
Error Pattern
fn create_string() -> &String {
let s = String::from("hello");
&s // ERROR: cannot return reference to local variable
}
Fix Options
Option 1: Return owned value
fn create_string() -> String {
String::from("hello")
}
Option 2: Use static/const
fn get_static_str() -> &'static str {
"hello"
}
E0716: Temporary Value Dropped While Borrowed
Error Pattern
let r: &str = &String::from("hello"); // ERROR: temporary dropped
println!("{}", r);
Fix Options
Option 1: Bind to variable first
let s = String::from("hello");
let r: &str = &s;
println!("{}", r);
Option 2: Use let binding with reference
let r: &str = {
let s = String::from("hello");
// s.as_str() // ERROR: still temporary
Box::leak(s.into_boxed_str()) // extreme: leak for 'static
};
Pattern: Loop Ownership Issues
Error Pattern
let strings = vec![String::from("a"), String::from("b")];
for s in strings {
println!("{}", s);
}
// ERROR: strings moved into loop
println!("{:?}", strings);
Fix Options
Option 1: Iterate by reference
let strings = vec![String::from("a"), String::from("b")];
for s in &strings {
println!("{}", s);
}
println!("{:?}", strings); // OK
Option 2: Use iter()
for s in strings.iter() {
println!("{}", s);
}
Option 3: Clone if needed
for s in strings.clone() {
// consumes cloned vec
}
println!("{:?}", strings); // original still available