-
Notifications
You must be signed in to change notification settings - Fork 1
Extracted function argument borrows
Deciding how to pass values into the extracted function is non-trivial and requires analysis.
The end result of this algorithm is to decide for some value a: A
, whether
- a
Copy
ofa
is passed into the extracted function; - ownership of
a
is moved into the extracted function; - an immutable reference of
a
,&a
is passed into the extracted function; - a mutable reference of
a
,&mut a
is passed into the extracted function.
To decide this, the algorithm needs to consider the follwing metadata:
-
does
A
implementCopy
trait?
Since Rust does not consider a type implementing theCopy
trait amove
i.e. a change of ownership, it can be passed into the extracted function directly. -
is
a
live after the extracted block?
If the variable is not alive, then it ismoved
into the function--otherwise, it cannot bemoved
as the value will bedropped
after the function call finished. -
is
a
defined with themut
keyword?
Ifa
is not and it is written to within the extracted block then this is an error and cannot be extracted. -
a
is written to within the extracted block.-
a: A
whereA
is&mut B
for some typeB
soa
is passed asa: &mut B
. -
a: A
whereA
is not a reference type so a new mutable reference is created&mut a: &mut A
and passed from the caller asbar(&mut a)
.
-
-
a
is not written to within the extracted block.-
a: A
whereA
is&B
or&mut B
for some typeB
soa
is passed as itself. -
a: A
whereA
is not a reference type so a new immutable reference is created&a: &A
and passed from the caller asbar(&a)
.
-
Algorithm FuncParams
Input: liveness CFG LIVE
, reaching definition CFG REACH
, type definitions variables in extracted block TV
, extracted block statements BLK
Output: variables mapping between variable name and its type into the extracted function, and its passing in text
MakeMutableInput
Input: type definitions variables in extracted block TV
, variable name V
Output: variable type and variable passing statment
MakeImmutableInput
Input: type definitions variables in extracted block TV
, variable name V
Output: variable type and variable passing statment
We need to ensure that the reaching definition considers whether it's changing the reference to something like: z:&mut &i32
, where *z = some_i32_ref
so in this case, z
definition itself is not reaching but what z
is referencing perviously still is.
let x = 1;
let y = 1;
let mut z:&mut &i32 = &mut &x;
*z = &y;
Here, x
definition on line 1 is still reaching after line 4, while z
definition on line 3 is not reaching after line 4.
The implication here is in whether we should borrow the reference itself i.e. z
or we should just pass z
in.