2 ms·
Short lifetime is not usually implicit from scope, in languages with GC. Function return values are the problem and solving this problem is the primary ergonomi
by barrkel 5y ago
Short lifetime is not usually implicit from scope, in languages with GC. Function return values are the problem and solving this problem is the primary ergonomic of GC which in turn affects the style of code written.
If you allocate a value to return, you don't in general know how it will be deallocated because that depends on the caller. The caller may use it for a short time (so stack allocation could work) or store it in the heap where it will have indefinite lifetime. This is why it's not implicit from the scope.
Data flow compounds the problem: if references to arguments to the function are stored in the allocated return value, then the return value extends their lifetime, but again, the writer of the function doesn't know by how much.
Simple refactoring which abstracts code into more reusable functions will obscure local reasoning about allocation.
Working around these problems in the absence of GC or lifetime analysis means adopting various ad-hoc fixes, like calling conventions which pass the location for the return value as a hidden parameter, or smart pointers which dynamically track ownership, or coding conventions like caller always allocates, or global conventions like zone allocation.
The big programming ergonomic side-effect of the presence of GC is the ability to more freely write and refactor functions that allocate and freely reuse them elsewhere. Conversely, code written without GC will be less factored into reusable functions.
Rust's lifetime management is somewhere in the middle. It requires particular conventions and if you're able to follow the conventions then ergonomics approach that of GC. But if you want cyclic data structures, or to simply pass data which might enable the construction of cyclic data structures, you need to think harder.