Ok, and finally my overall takeaway. It took a long while for “Lock data, not code” to become understood, and I worry that we could be making a similar mistake here. I think the most of (un)safety can be thought about looking the inhabitants of types—or since Rust is a sub-structural language, we must take the contexts into account too (e.g. aliasing).
First, consider that transmutes and unsafe casts boil down to “extra introduction rules”. These introductions are “extra” in safe code operating on the introduced types is not expected to “work right” when fed the unsafely introduced values. This is probably a pretty common way of thinking about these sorts of unsafe code, I’d assume.
More interestingly is what this means “encapsulation and sealing” are all about----using scoping / privacy to restrict the inhabitants to some subset what it would “normally” be. Modules, privacy, “unsafe boundaries” etc are just the means to this end, and not the end itself. Not only do proposals like “unsafe fields” correctly put the emphasis back on the type with fewer inhabitants, but they also conveniently make functions like copy_drop unsafe even in the module where those fields are in scope. Supporting all 4 combinations of [pub] [unsafe] <field-or-item> nicely separates pub for stability, and unsafe for safety—use both for unsafe things likely to be removed or changed.