-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New lint: Limit unsafe blocks to a single unsafe operation #10064
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
Comments
I'll try to implement this @rustbot claim |
Would the lint accept the same operation multiple times, e.g. two pointer derefs? I do worry that such a lint might lead to very unidiomatic code, but as a restriction lint it might be a good addition for some use cases. |
Actually not sure, maybe the the issue author will answer this better.
That's what I'm worried about as well, but this is a restriction lint, so developers using it will be very aware of this, and use it accordingly, maybe it doesn't make sense crate-wide, but restricting some specific module to it might be a good idea: // very unsafe module
#[warn(clippy::one_unsafe_op_per_block)]
mod not_very_safe {
// ...
} |
FWIW, this lint sounds very similar to #8022. |
The issue author seems a bit inactive on this, and since I've assigned myself, I'm going to push this issue a bit. Assuming the lint should count any unsafe operation (8 pointer derefs -> 8 unsafe ops), I have the lint implemented and pretty much ready for PR (maybe some cleanup is needed, but the logic is already there). As for the usefulness of this lint, I personally believe that it will be useful in cases where you're writing a safe wrapper for an About the relation to #8022, I think this lint request shouldn't suffer from the pushback received there (although most of the points raised there are still valid for this lint as well), at least because this lint was initially proposed as a tl;dr: when used right, this lint should be useful, and considering that it's a I will wait for comments on this for a bit, and open a PR if there are no additional concerns. |
What it does
Checks for
unsafe
blocks that contain more than one unsafe operation. Unsafe operations include:*const T
or*mut T
)union
sLint Name
one_unsafe_op_per_unsafe_block
Category
restriction
Advantage
Combined with
undocumented_unsafe_blocks
, this lint ensures that each unsafe operation must be independently justified. Combined withunused_unsafe
, this lint also ensures that we know when we eliminate unsafe operations through refactoring.See the "Example" section for comprehensive examples.
Drawbacks
It may be awkward or noisy to break up a series of related unsafe operations into individual blocks.
Example
With
undocumented_unsafe_blocks
Although the
unsafe
block is properly justified forchar::from_u32_unchecked
, there are actually two unsafe operations in it. The pointer dereference needs to be justified as well, but it's easy to accidentally include it without updating the justification. By limiting unsafe blocks to a single unsafe operation, this would be rewritten as:Breaking up our unsafe block led us to justify dereferencing
ptr
, which in turn led us to update the function's safety requirements to accurately reflect the invariants used by the implementation.With
unused_unsafe
Refactoring from the same starting function as the example in
undocumented_unsafe_blocks
:By changing our function to accept
&u32
, we were able to remove the only unsafe operation from our first unsafe block. In turn, we were able to eliminate the unsafe block, prompting us to update our safety requirements for our function. In this way, refactoring a function to remove unsafe helps ensure that the safety documentation also gets updated to reflect the new requirements.The text was updated successfully, but these errors were encountered: