3 ms·
I don't think your attempt would be quite accurate: safe code, even though it is checked, can cause UB. This can only occur if some earlier unsafe code was unso
by LegionMammal978 4y ago
I don't think your attempt would be quite accurate: safe code, even though it is checked, can cause UB. This can only occur if some earlier unsafe code was unsound, by the current definition.
For instance, suppose you have an ordinary Box<i32>. Then, you dereference it to create a local &i32 reference, and use unsafe code to turn it into a &'static i32 reference. Then, you drop the Box<i32>, which deallocates the backing memory. Finally, you attempt to read the value from the &'static i32.
The UB occurs only at the last step, when you read from deallocated memory. But reading from a &'static i32 reference is completely allowed in safe, checked code. That's why we use the term "unsound" to cast fault on the earlier unsafe code which allowed us to do this.
- codeflo 4y agoThat's a very good example. I think that's what I meant by: > "Sound" code is safe code (that may or may not be checked by the compiler), that will remain safe no matter how it's called by checked code. Maybe "called" was too specific, it could be embedded in other ways. But it's clear in your example that there's a way of integrating the unsafe cast into otherwise fully checked code that leads to UB. Hence, it is not sound.
- skitter 4y agoJust holding an invalid reference is UB, even if you don't do anything with it (the example still works as the reference gets invalidated by safe code).
- LegionMammal978 4y agoA reference is never really "held": from a language-semantics standpoint, it only exists when it is actually used. In this example, copying, reborrowing, or accessing the reference would be UB, but simply letting it fall out of scope would not be UB (modulo the UCG issue oconnor mentioned; but I personally doubt that this status quo will change). You can try this yourself with Tools > Miri on the Playground (https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=6f829f372fa97bea62ccf7a1ae1c6871 https://play.rust-lang.org/?version=stable&mode=debug&editio...). The distinction is far more relevant for unsafe code than for safe code.
- oconnor663 4y agoI think there are some aspects of this rule that are still undecided. See for example: - https://github.com/rust-lang/unsafe-code-guidelines/issues/84 https://github.com/rust-lang/unsafe-code-guidelines/issues/8... - https://github.com/rust-lang/miri/issues/2732 https://github.com/rust-lang/miri/issues/2732
- oconnor663 4y agoYeah this is a great example of why formally defining "soundness" is so tricky. Not only do we have to worry about unsafe code committing UB, we also have to worry about it setting up a situation where safe code might commit UB later. Soundness is a property of functions and modules, but that property is a statement about the entire program that contains them, or actually about any program that could contain them. In retrospect, I kind of wish I had asked somebody like Ralf Jung to review this post before I published it. On the other hand, the fastest way to get an answer on the internet is to post the wrong answer :-D