Indirection in frozen
That new reference is now the one that must be used for this location, but the old reference it was created from cannot be forgotten: At some point, the reborrow will expire and the old reference will be “active” again. This forms a stack: When we have an &mut i32, we can reborrow it to obtain a new reference. (I will discuss later just how we keep track of this for now, let’s just assume it can be done.) The central idea of this model (and its precursors by and is that, for every location, we keep track of the references that are allowed to access this location. It’s not a long post, and I cannot repeat everything again here. If you need some more context on undefined behavior and how it relates to compiler optimizations, I suggest you read my blog post on this topic first.
2 Stacking Borrowsįor these reasons, my second proposal makes lifetimes in general and the result of lifetime inference in particular completely irrelevant for whether a program has undefined behavior (UB). With non-lexical lifetimes, the “end” of a lifetime is not even so clearly defined any more.
Not only did this make the specification complex and hard to understand the implementation in Miri also had to actively work against the compiler’s general intention to forget about lifetimes as early as possible. With “Types as Contracts”, the exact place where a lifetime ended turned out to be really important. However, in Rust, we cannot talk about references and whether the are valid at their given type without talking about lifetimes. “All data must always be valid” is also easier to explain than a long list of operations and the kind of restrictions they place upon the data.
Indirection in frozen code#
Validity-based models have several advantages: Eager checking means we can typically identify which code is actually responsible for producing the “bad” value. In both cases, violating a property that the model requires to hold is undefined behavior.Įssentially, with a validity-based model like “Types as Contracts”, the basic idea is that all data is always valid according to the type it is given.Įnforcing the restrictions of such a model (e.g., when checking whether a program has undefined behavior) amounts to eagerly checking all reachable data for validity.Īn access-based model, on the other hand, only requires data to be valid when used.Įnforcing it amounts to lazily checking the bare minimum at each operation. In contrast, a “validity”-based model requires these properties to always hold for all references that could be used. Access-basedĪn “access”-based model is one where certain properties – in this case, mutable references being unique and shared references pointing to read-only memory – are only enforced when the reference is actually used to access memory. Only go on reading here if you want some additional historic context.
That other post is self-contained, so if you are just interested in the current state of Stacked Borrows, I suggest you go there. Since publishing this post, I have written another blog post about a slightly adjusted version of Stacked Borrows (the first version that actually got implemented). “Types as Contracts” was a fully “validity”-based model, while “Stacked Borrows” is (to some extent) “access”-based. The model I am proposing here is by far not the first attempt at giving a definition: The model is heavily based on ideas by and and of course taking into account the lessons I learned last year when I took my first stab at defining such a model, dubbed “Types as Contracts”.īut before I delve into my latest proposal, I want to briefly discuss a key difference between my previous model and this one: This is a long-standing open question of many unsafe code authors, and also by compiler authors who want to add more optimizations. This is intended to answer the question which pointer may be used when to perform which kinds of memory accesses. In this post, I am proposing “Stacked Borrows”: A set of rules defining which kinds of aliasing are allowed in Rust. Stacked Borrows: An Aliasing Model For Rust.