struct SelfR<'a>{
a:String,
b:Option<&'a String>
}
fn foo0(){
let mut c = SelfR{a:"abc".to_string(),b:None};
c.b = Some(&c.a); // OK
println!("{}",c.b);
}
fn foo1(){
let mut c = SelfR{a:"abc".to_string(),b:None};
let d = Some(&c.a);
c.b = d; // OK
println!("{}",c.b);
}
fn foo2(){
let mut c = SelfR{a:"abc".to_string(),b:None};
let mrf = & mut c;
mrf.b = &mrf.a; // OK
println!("{}",mrf.b);
}
fn foo3(){
let mut c = SelfR{a:"abc".to_string(),b:None};
let mrf = & mut c;
(& mut *mrf).b = Some(&mrf.a); // Error
println!("{}",mrf.b);
}
fn foo4(){
let mut c = SelfR{a:"abc".to_string(),b:None};
(& mut c).b = Some(&c.a); // Error
println!("{}",c.b);
}
Why are foo0, foo1, and foo2 permitted to produce self-reference, I expect they would have the same diagnosis as that of foo3 and foo4. Is there a special rule that applies to the former three?
There's nothing really wrong with 3 and 4, they're just obfuscated from the compiler being able to tell that they're okay. The parts in parentheses are borrowing the whole c, so you aren't allowed to then borrow a part of c in the same expression.
This doesn't really have anything to do with self-references. This would apply when calling a method like c.b.m(&c.a) vs (&mut c).b.m(&c.a).
The other ones work because Rust deals with borrows per-member when such information is available. It knows &mut c.b and &c.a don't overlap.