clarify validity for prtially initialized local variables
[web.git] / ralf / _posts / 2018-08-22-two-kinds-of-invariants.md
index a90dc47c9ba7cb25f812d7683280a1d2bc7e4415..c54a0101833990a2b889f8a4109e6d86dbafe58c 100644 (file)
@@ -1,5 +1,5 @@
 ---
-title: "Two Kinds of Invariants"
+title: "Two Kinds of Invariants: Safety and Validity"
 categories: internship rust
 forum: https://internals.rust-lang.org/t/two-kinds-of-invariants/8264
 ---
@@ -102,12 +102,17 @@ But that's okay, because this is carefully controlled unsafe code -- and by the
 
 > *Unsafe code only has to uphold safety invariants at the boundaries to safe code.*
 
+Notice that the "boundary" is not necessarily where the `unsafe` block ends.
+The boundary occurs where the unsafe code provides a public API that safe code is intended to use -- that might be at the module boundary, or it might even be at the crate level.
+That is where safe code should be able to rely on safety, so that it can interact with the unsafe code without triggering undefined behavior, and hence that is where the safety invariants come into play.
+
 This is in strong contrast to validity, which must *always* hold.
 Layout optimizations and LLVM's attributes are in effect throughout unsafe code, so it is never okay to ever have invalid data.
+(With the sole restriction of data which *the compiler statically knows is not initialized*: If you write `let b: bool;`, that data in `b` is kept inaccessible *even to unsafe code*, and it does not have to satisfy any invariant. This works because the compiler knows about `b` not being initialized.)
 
 > *Unsafe code must always uphold validity invariants.*
 
-So we clearly cannot just pick the same invariant for both.
+So we clearly cannot just pick the same invariant for both, or else it would be impossible to write `Vec`.
 We *might* want to just ignore user-defined invariants when it comes to validity, but I think that would be ill-advised.
 
 First of all, validity is part of the definition of undefined behavior.