4 ms·
You even have this phenomenon inside single functions. Let's say you write a function that's supposed to be a safe/sound abstraction. You might be setting up a
by codeflo 4y ago
You even have this phenomenon inside single functions. Let's say you write a function that's supposed to be a safe/sound abstraction. You might be setting up a pointer, maybe determined by a dozen lines of codes, that is then finally dereferenced. You'd typically only put the unsafe block around this final pointer access, but its safety depends on the whole calculation being correct.
- zozbot234 4y agoUnsafe blocks are very different from unsafe-marked functions. A function that can indirectly cause UB when called in safe code must be marked as unsafe, so that the invariants it relies on can be properly documented in a Safety: comment, and manually checked by callers.
- LegionMammal978 4y agoOnly if it's public, and you don't know who the callers are. If you do know exactly who the callers are (since it's a private function), and you have internal documentation that lets contributors know of the proper invariants, then it's entirely possible to prevent UB from ever occurring even if the function is marked as safe. By itself, this is usually not a good idea. But in some cases, it's necessary, e.g., an unsafe implementation of an external safe trait on an internal type that only your internal code will ever see.
- zozbot234 4y agoWhy? If you have a non-public function and all its potential callers are known, what's the harm in marking it as unsafe and documenting its invariants in the idiomatic way (a Safety comment)? Your case of implementing a safe trait via unsafe code seems like it should be quite rare, and even then the trait implementation should document the assumptions it's relying on as part of an unsafe block. If you neglect to mark other possibly-UB functions as unsafe, this becomes harder to ensure.
- LegionMammal978 4y agoI agree that it's rarely a good idea to do this; it's a red flag at minimum when you see it. I'm just trying to reject the notion that it's categorically unsound to do this. I've personally seen the safe-trait example while reviewing a crate, and there were indeed plenty of comments documenting the assumptions. As long as there's absolutely no way for anyone to cause these assumptions to be broken from the outside, there's no way to cause UB, and it's not really useful to call the interface unsound.
- mlindner 4y agoIt doesn't matter if it's public or not. Every function is "public" to the person modifying the code. The purpose of unsafety/safety is primarily for the developer, not for users of a library.
- mlindner 4y agoI completely agree. The contract of calling any safe function is that it is impossible to cause undefined behavior by calling that function (assuming there are no unsoundness bugs). That is the inherent built-in contract in any piece of Rust code.