A name finds its own hook
Two variables have arrived wearing the same name. Neither seems prepared to change it.
The compiler needs a better arrangement than asking whichever one happens to be standing nearest the printer.
A spelling can have two addresses
A nested function can introduce a parameter whose name shadows an outer binding:
main() {
let count = 10
let next = fn(count: Int) { count + 1 }
assert next(4) == 5
assert count == 10
}
The occurrence inside the anonymous function refers to its parameter. The last occurrence refers to the outer binding. Equal spelling does not imply equal identity.
Resolve before generating code
A resolver walks the scopes in which declarations are visible. Once a name is resolved, later phases should retain the declaration it refers to rather than repeating the search with slightly different rules.
outer scope: count -> declaration A
function scope:
count -> declaration B
count + 1 reads B
back in the outer scope:
count reads A
Those letters are a diagram, not generated variable names. Their purpose is to separate identity from spelling.
This distinction also helps with diagnostics. An unused outer binding is still unused even if an unrelated inner parameter has the same name. Counting text matches would give it credit for somebody else’s work.
A closure remembers the right binding
Capturing an outer value is the other useful case:
main() {
let extra = 3
let add_extra = fn(value: Int) { value + extra }
assert add_extra(4) == 7
}
Here extra is not a parameter of the anonymous function. The closure needs the value from its enclosing scope.
The backend must preserve that connection when it chooses target variable names. Finding the correct declaration in the front end and then confusing it with a neighbour in generated code is a particularly elaborate way of returning the wrong answer.
Scope rules can feel like small housekeeping. They are also what lets us read a function locally without searching the entire project for somebody else who used the word count.
Both visitors can keep their names. We have found separate hooks for their coats.
— Peregrine Finch