-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Safe functions cannot impose constraints on callers #1354
Comments
Hi! Thanks for going into detail on this, especially with the numerous examples! We understand that Lines 74 to 75 in 7d72409
We don't think that individual safety comments on every index are easier to understand than a more centralized analysis of how indices and ranges are split up among tasks and threads, and thus that they would in fact be more Ultimately, we need a solution to this that is performant enough and as safe as possible.
This is a great point that we didn't consider. We should be able to fix this. |
Marked or not, from what you're saying, much of the codebase (namely, the parts that A contributor or user can easily ignore or otherwise miss a doc comment on a function. They can't ignore a compile error that tells them to explicitly opt-in to a potentially unsafe function (and encourages them to read that function's safety documentation to learn about its preconditions). Aside from that, another option here is replacing all usages of |
probably more than slight, I think. |
We did consider this, and personally I did want to fully try it out and see how it's performance was. The two major downsides to this that we saw were 1) performance as you said. While relaxed atomic load and stores are identical to a normal load and store for a single isolated instruction, they're not optimized the same. Two consecutive, 16-bit aligned And 2) assembly. All of these |
I strongly urge you to adjust the methods so that they are correctly defined as
Then don't do that. Safety comments are suggested documentation, but they're still just documentation. If the unsafe usage is just |
The only level at which you can guarantee that all calls are sound, and thus mark safe, is the very top level calls. So essentially the whole codebase becomes unsafe, and that doesn't seem more contributor friendly either. It would also hide other usages of |
Using an Each And I really don't understand what you mean by some unsafe would cover up other unsafe. You can use smaller blocks if separate spans have separate logic. |
...and be sound, anyways.
To demonstrate this, I recommend you add the following unit test to
src/disjoint_mut.rs
and count with me:This code is rejected by both Miri's stricter and more permissive experimental borrowing models:
cargo miri test --lib count --release
MIRIFLAGS="-Zmiri-tree-borrows" cargo miri test --lib count --release
The "safety preconditions" referenced on line 324 are exactly what a safe function CANNOT impose!
rav1d/src/disjoint_mut.rs
Lines 318 to 330 in 7d72409
A function is most definitely not safe if calling it twice with the same input (assuming it is possible to safely be called twice... this is the entire reason types that you can't clone exist, after all...) is possible and causes undefined behavior. While DisjointMut's API is currently not a public detail of the library, this function is nonetheless in fact an unsound function by the rules of Rust, because it should be marked
unsafe
, but isn't.And there are plenty of ways to achieve unsound behavior from entirely internal code that goes undetected by testing but is actually exercised by real public usage of the API. I can link you to dozens of examples from other codebases that thought the "checked in debug, unchecked at runtime" was sufficient to establish safety on its own, if you like.
I mean, I think it's a rather nice type even if
index_mut
(and probably a few other fn) has to beunsafe
! But in its current form, with them falsely marked as safe fn, prevents correctly linting against unsafe code. It bypasses such linting. Your codebase probably will not exceed compilation memory usage limits just by processing a few moreunsafe
tokens, will it?There's plenty of weird holes to fall down, too, even with the debug assertions in play, because debug assertions firing isn't necessarily good enough if you put the panic in the wrong place. The panic should go before the safety condition is violated. e.g. this also fails
cargo miri test --lib
, and without--release
or anything:The text was updated successfully, but these errors were encountered: