-
Notifications
You must be signed in to change notification settings - Fork 1
Mutability propagation through alias info
Andreea Costea edited this page Jun 15, 2023
·
4 revisions
Consider the function test_A.
fn test_A(){
let mut x = String::new();
let a: &mut String = &mut x;
let b: &mut String = a;
println!("b: {}", b);
let c = b;
println!("c: {}", c);
}Let's assume we would like to refactor its last three lines as follows:
fn foo_A(b: &String){
println!("b: {}", b);
let c = b;
println!("c: {}", c);
}
fn test_A(){
let mut x = String::new();
let a: &mut String = &mut x;
let b: &mut String = a;
foo_A(b);
}Note that, although b is a mutable reference in test_A, foo_A only requires an immutable borrow since b and its alias c are only used in a read-only manner.
Consider next test_B, a variation of the above function, where c is used to mutate the value it refers to.
fn test_B(){
let mut x = String::new();
let a: &mut String = &mut x;
let b: &mut String = a;
println!("b: {}", b);
let c = b;
c.push('a');
} After extracting the last three lines in foo_B as below, our analysis collects a constraint system mut <: c to denoted that c requires mutability capabilities.
Although there is no mutability constraint collected for b, since c and b are aliased, the mutability constraint is being propagated to b as well resulting in the following refactored code:
fn foo_B(b:&mut String){
println!("b: {}", b);
let c = b;
c.push('a');
}
fn test_B(){
let mut x = String::new();
let a: &mut String = &mut x;
let b: &mut String = a;
foo_B(b);
}