-
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);
}