Which uses of a variable in a Rusty-Elixir body are its last, so lowering knows where Rust may take a value and where it must borrow or copy one.
Elixir never changes a value, so a list, map, or set passed to a function is still there
for every later use. Rust code taking the value ends it, so lowering takes one only at its
last use. annotate/1 walks a body backwards, as liveness is computed, and records on each
variable occurrence the variables still in use after it:
- expressions, arguments, and pipes run in order;
- the branches of
case,if,cond, andwithare alternatives; - a closure or comprehension body may run many times, so no use inside one is the last;
- rebinding a name ends the value it had.
A value built from another, as by_id = index(records), may borrow from it, so the other
stays in use while the built value does; in_use?/3 asks.
Summary
Functions
Annotates every variable occurrence in body with the variables in use after it, and
returns what each binding was built from.
Whether the variable occurrence variable is not the last use of its value: a later use
follows, it is inside a body that may run again, or a value still in use was built from it
and, by its type in vars, may borrow from it. An occurrence lowering made itself, without
an annotation, is a fresh value's only use.
Types
Functions
@spec annotate(Macro.t()) :: {Macro.t(), built_from()}
Annotates every variable occurrence in body with the variables in use after it, and
returns what each binding was built from.
@spec in_use?(Macro.t(), built_from(), %{optional(atom()) => RustQ.Meta.Type.t()}) :: boolean()
Whether the variable occurrence variable is not the last use of its value: a later use
follows, it is inside a body that may run again, or a value still in use was built from it
and, by its type in vars, may borrow from it. An occurrence lowering made itself, without
an annotation, is a fresh value's only use.