-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
non_send_fields_in_send_ty seems to be misguided #8045
Comments
And here's a reduced version of actual code which triggered the false positive for me. use core::cell::UnsafeCell;
use core::ptr::NonNull;
pub struct S(UnsafeCell<NonNull<()>>);
// Safety: S ensures that there is no aliasing even though
// a pointer (NonNull) is used rather than a reference.
unsafe impl Send for S {} |
I am also confused as to what the purpose of this lint is supposed to be - the entire point of |
This is indeed very unhelpful... |
This was added in #7709, FWIW. But the explanation there is also not very helpful, and also the example is arguably half-wrong (it shows two unsound uses, but the one concering the |
This is not about whether the lint is useful, but while reading 1.57 release notes, I noticed that the documentation for it is also wrong — it says
which is not how sending works (sending is not observable / does not run code, let alone
which is a more correct (s/and drops/and then dropping/) description of the problem. On the original question of whether there's any value at all, maybe this lint should be looking for fields which are |
You can have a Rust struct wrapping an FFI struct that in turn contains a pointer. The Rust struct makes sure there is no aliasing so that it can be |
Even if it is completely safe in that case, I think that it is correct to mark this as suspicious.
Personally, I like the notion to only mark allow structs to be cc: @Qwaz What are your thoughts on this? 🙃 |
This is exactly what the automatic implementation of
Which is when you use |
Thanks for bringing this false positive to the attention. TL;DR (1) This lint has a rule that handles Let me start with the background (and excuse) for this lint. This lint is designed after actual soundness bugs we found during our ecosystem scale memory safety bugs finding work, Rudra. The original proposal #7703 included 4 representative bugs, but the lint was designed after reviewing more than a hundred of Send/Sync soundness bugs throughout the Rust ecosystem (the bugs with SV tag in the PoC repository). This lint is most useful when writing a generic data structure. There are surprising amount of unsound Regarding false postives, it already has a rule to suppress false positives related to It would be extra helpful if anyone can share (1) types that are specifically designed |
Given that clarification, I'd say the lint documentation has two problems:
|
That description is indeed incorrect and I'll include that in the fix |
Not exactly the same situation, but in gtk-rs we have helper structs around Currently this lint triggers for each of these user-facing structs that are actually |
I hit this in Rug. This is somehow similar to having a small vector which can be borrowed as a full vector, that is there is a way to get |
Thanks for sharing more false positive cases! It seems it's evident that we need a better heuristic to handle non-Send internal types. I can see two directions to approach this problem at high level. We can (1) limit the lint to Send impls related to generic types (Send/Sync variance bugs) or (2) try to invent a ruleset to allow internal structs similar to what we do for pointer-like types. I suggest to demote this lint back to |
Consider NonNull as a pointer type PR 1/2 for issue #8045. Add `NonNull` as a pointer class to suppress false positives like `UnsafeCell<NonNull<()>>`. However, this change is not sufficient to handle the cases shared in gtk-rs and Rug in the issue. changelog: none r? `@xFrednet`
Clarify the purpose of the non_send lint PR 2/2 for issue #8045. Tried to tone down the warning message and clarify the intention of the lint. Specifically, I added a description that this lint tries to detect "types that are not safe to be sent to another thread". changelog: none r? `@xFrednet`
Unfortunately this lint ended up in the default set of lints for 1.58 now. |
Yes, I think we didn't back port the group change, not that you say that 🙈 It should be in nursery on beta and nightly, but it should have been the same for stable. Sorry that I've missed that. We're currently planning on how this can be improved for the future, to prevent instances like these. Thank you for pointing that out! |
We're needing to disable this lint for Android because it triggers with Specifically, For specific types, the user may want to specify that the generated type is in fact Send, based on knowledge of the underlying type - this lint prohibits that. I think that for this lint to be productive, at a minimum it would need to only fire on annotated structures, since marking a structure containing In general though, I'm not sure there is a right way to do this lint. Even if there were an |
This is triggering a ton of false positive spam for hecs, for similar reasons to the above. Is there a plan to make a point release with the backport? |
I'm also getting some false positives. Here's a workaround.
|
No, there is not. Even if this is annoying, I'm not convinced that the problem is big enough to justify a point release. For now, I sadly have to suggest allowing the lint. You can use the console like @Xaeroxe suggested or a crate level attribute like this: #![allow(clippy::non_send_fields_in_send_ty)] |
I'm concerned that a common response to this problem is going to be disabling clippy in CI. I'd strongly encourage a point release, but I acknowledge this isn't my decision to make. |
Maybe we need to include a few of the crates mentioned in this thread to the lintcheck crate set to prevent a similar situation in the future. Also, it would be great to have a process to run Clippy at a much larger scale than the current fixed set before stabilizing a new lint (#6623?). Thanks to the release team for handling the situation. |
They can be included without any risk. However, it's also fine if not, since normal users won't see the message unless they deliberately enable nursery or this lint. Thanks for pointing this out!
We definitely should, we're also planning to improve the stabilization process of lint to prevent this in the future. Currently, I'm sadly busy with some RL stuff, but I plan to extend the lintcheck crates with a more diverse selection. Adding a few crates from this thread is a great idea 👍 |
With the standard of existing The difficulty of implementing I've reported a few Send/Sync soundness bugs where (Just to be clear, I'm not using this argument to justify all the false positives.) Footnotes
|
Hmm, I'd prefer to backport the minimal set of changes needed to revert the breakage in the point release. As xFrednet said users won't likely see those messages anyway. |
Then 5d63a28 will be sufficient. 👍 |
@Qwaz The problem with this lint is that it is very unlikely that a user added an unsafe impl Send and included a non Send field unintentionally. The lint does not effectively discern whether that action was unsound, and cannot give the user any guidance as to whether or not they were wrong. Since a user presumably believes their code is sound, they are very likely to ignore this lint rather than change their code, making it very ineffective. On the other hand, a lint that only targets the wrapping case is much more likely to highlight an oversight (users meant to add the Send bound to the generic parameter, but forgot). Users will only have to allow it in the uncommon event that their type does not need the bound. This would be much more effective. |
Rust 1.58.1 moved this lint to the nursery, disabling it by default. |
…ty)]` Rust 1.58.0 (before Rust was merged into the kernel) made Clippy's `non_send_fields_in_send_ty` lint part of the `suspicious` lint group for a brief window of time [1] until the minor version 1.58.1 got released a week after, where the lint was moved back to `nursery`. By that time, we had already upgraded to that Rust version, and thus we had `allow`ed the lint here for `CondVar`. Nowadays, Clippy's `non_send_fields_in_send_ty` would still trigger here if it were enabled. Moreover, if enabled, `Lock<T, B>` and `Task` would also require an `allow`. Therefore, it does not seem like someone is actually enabling it (in, e.g., a custom flags build). Finally, the lint does not appear to have had major improvements since then [2]. Thus remove the `allow` since it is unneeded. Link: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1581-2022-01-20 [1] Link: rust-lang/rust-clippy#8045 [2] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
…ty)]` Rust 1.58.0 (before Rust was merged into the kernel) made Clippy's `non_send_fields_in_send_ty` lint part of the `suspicious` lint group for a brief window of time [1] until the minor version 1.58.1 got released a week after, where the lint was moved back to `nursery`. By that time, we had already upgraded to that Rust version, and thus we had `allow`ed the lint here for `CondVar`. Nowadays, Clippy's `non_send_fields_in_send_ty` would still trigger here if it were enabled. Moreover, if enabled, `Lock<T, B>` and `Task` would also require an `allow`. Therefore, it does not seem like someone is actually enabling it (in, e.g., a custom flags build). Finally, the lint does not appear to have had major improvements since then [2]. Thus remove the `allow` since it is unneeded. Link: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1581-2022-01-20 [1] Link: rust-lang/rust-clippy#8045 [2] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
…ty)]` Rust 1.58.0 (before Rust was merged into the kernel) made Clippy's `non_send_fields_in_send_ty` lint part of the `suspicious` lint group for a brief window of time [1] until the minor version 1.58.1 got released a week after, where the lint was moved back to `nursery`. By that time, we had already upgraded to that Rust version, and thus we had `allow`ed the lint here for `CondVar`. Nowadays, Clippy's `non_send_fields_in_send_ty` would still trigger here if it were enabled. Moreover, if enabled, `Lock<T, B>` and `Task` would also require an `allow`. Therefore, it does not seem like someone is actually enabling it (in, e.g., a custom flags build). Finally, the lint does not appear to have had major improvements since then [2]. Thus remove the `allow` since it is unneeded. Link: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1581-2022-01-20 [1] Link: rust-lang/rust-clippy#8045 [2] Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Trevor Gross <tmgross@umich.edu> Tested-by: Gary Guo <gary@garyguo.net> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://lore.kernel.org/r/20240904204347.168520-11-ojeda@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
…ty)]` Rust 1.58.0 (before Rust was merged into the kernel) made Clippy's `non_send_fields_in_send_ty` lint part of the `suspicious` lint group for a brief window of time [1] until the minor version 1.58.1 got released a week after, where the lint was moved back to `nursery`. By that time, we had already upgraded to that Rust version, and thus we had `allow`ed the lint here for `CondVar`. Nowadays, Clippy's `non_send_fields_in_send_ty` would still trigger here if it were enabled. Moreover, if enabled, `Lock<T, B>` and `Task` would also require an `allow`. Therefore, it does not seem like someone is actually enabling it (in, e.g., a custom flags build). Finally, the lint does not appear to have had major improvements since then [2]. Thus remove the `allow` since it is unneeded. Link: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1581-2022-01-20 [1] Link: rust-lang/rust-clippy#8045 [2] Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Trevor Gross <tmgross@umich.edu> Tested-by: Gary Guo <gary@garyguo.net> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://lore.kernel.org/r/20240904204347.168520-11-ojeda@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
…ty)]` Rust 1.58.0 (before Rust was merged into the kernel) made Clippy's `non_send_fields_in_send_ty` lint part of the `suspicious` lint group for a brief window of time [1] until the minor version 1.58.1 got released a week after, where the lint was moved back to `nursery`. By that time, we had already upgraded to that Rust version, and thus we had `allow`ed the lint here for `CondVar`. Nowadays, Clippy's `non_send_fields_in_send_ty` would still trigger here if it were enabled. Moreover, if enabled, `Lock<T, B>` and `Task` would also require an `allow`. Therefore, it does not seem like someone is actually enabling it (in, e.g., a custom flags build). Finally, the lint does not appear to have had major improvements since then [2]. Thus remove the `allow` since it is unneeded. Link: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1581-2022-01-20 [1] Link: rust-lang/rust-clippy#8045 [2] Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Trevor Gross <tmgross@umich.edu> Tested-by: Gary Guo <gary@garyguo.net> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://lore.kernel.org/r/20240904204347.168520-11-ojeda@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
…ty)]` Rust 1.58.0 (before Rust was merged into the kernel) made Clippy's `non_send_fields_in_send_ty` lint part of the `suspicious` lint group for a brief window of time [1] until the minor version 1.58.1 got released a week after, where the lint was moved back to `nursery`. By that time, we had already upgraded to that Rust version, and thus we had `allow`ed the lint here for `CondVar`. Nowadays, Clippy's `non_send_fields_in_send_ty` would still trigger here if it were enabled. Moreover, if enabled, `Lock<T, B>` and `Task` would also require an `allow`. Therefore, it does not seem like someone is actually enabling it (in, e.g., a custom flags build). Finally, the lint does not appear to have had major improvements since then [2]. Thus remove the `allow` since it is unneeded. Link: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1581-2022-01-20 [1] Link: rust-lang/rust-clippy#8045 [2] Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Trevor Gross <tmgross@umich.edu> Tested-by: Gary Guo <gary@garyguo.net> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://lore.kernel.org/r/20240904204347.168520-11-ojeda@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
…ty)]` Rust 1.58.0 (before Rust was merged into the kernel) made Clippy's `non_send_fields_in_send_ty` lint part of the `suspicious` lint group for a brief window of time [1] until the minor version 1.58.1 got released a week after, where the lint was moved back to `nursery`. By that time, we had already upgraded to that Rust version, and thus we had `allow`ed the lint here for `CondVar`. Nowadays, Clippy's `non_send_fields_in_send_ty` would still trigger here if it were enabled. Moreover, if enabled, `Lock<T, B>` and `Task` would also require an `allow`. Therefore, it does not seem like someone is actually enabling it (in, e.g., a custom flags build). Finally, the lint does not appear to have had major improvements since then [2]. Thus remove the `allow` since it is unneeded. Link: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1581-2022-01-20 [1] Link: rust-lang/rust-clippy#8045 [2] Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Trevor Gross <tmgross@umich.edu> Tested-by: Gary Guo <gary@garyguo.net> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://lore.kernel.org/r/20240904204347.168520-11-ojeda@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
…ty)]` Rust 1.58.0 (before Rust was merged into the kernel) made Clippy's `non_send_fields_in_send_ty` lint part of the `suspicious` lint group for a brief window of time [1] until the minor version 1.58.1 got released a week after, where the lint was moved back to `nursery`. By that time, we had already upgraded to that Rust version, and thus we had `allow`ed the lint here for `CondVar`. Nowadays, Clippy's `non_send_fields_in_send_ty` would still trigger here if it were enabled. Moreover, if enabled, `Lock<T, B>` and `Task` would also require an `allow`. Therefore, it does not seem like someone is actually enabling it (in, e.g., a custom flags build). Finally, the lint does not appear to have had major improvements since then [2]. Thus remove the `allow` since it is unneeded. Link: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1581-2022-01-20 [1] Link: rust-lang/rust-clippy#8045 [2] Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Trevor Gross <tmgross@umich.edu> Tested-by: Gary Guo <gary@garyguo.net> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://lore.kernel.org/r/20240904204347.168520-11-ojeda@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
…ty)]` Rust 1.58.0 (before Rust was merged into the kernel) made Clippy's `non_send_fields_in_send_ty` lint part of the `suspicious` lint group for a brief window of time [1] until the minor version 1.58.1 got released a week after, where the lint was moved back to `nursery`. By that time, we had already upgraded to that Rust version, and thus we had `allow`ed the lint here for `CondVar`. Nowadays, Clippy's `non_send_fields_in_send_ty` would still trigger here if it were enabled. Moreover, if enabled, `Lock<T, B>` and `Task` would also require an `allow`. Therefore, it does not seem like someone is actually enabling it (in, e.g., a custom flags build). Finally, the lint does not appear to have had major improvements since then [2]. Thus remove the `allow` since it is unneeded. Link: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1581-2022-01-20 [1] Link: rust-lang/rust-clippy#8045 [2] Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Trevor Gross <tmgross@umich.edu> Tested-by: Gary Guo <gary@garyguo.net> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://lore.kernel.org/r/20240904204347.168520-11-ojeda@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
…ty)]` Rust 1.58.0 (before Rust was merged into the kernel) made Clippy's `non_send_fields_in_send_ty` lint part of the `suspicious` lint group for a brief window of time [1] until the minor version 1.58.1 got released a week after, where the lint was moved back to `nursery`. By that time, we had already upgraded to that Rust version, and thus we had `allow`ed the lint here for `CondVar`. Nowadays, Clippy's `non_send_fields_in_send_ty` would still trigger here if it were enabled. Moreover, if enabled, `Lock<T, B>` and `Task` would also require an `allow`. Therefore, it does not seem like someone is actually enabling it (in, e.g., a custom flags build). Finally, the lint does not appear to have had major improvements since then [2]. Thus remove the `allow` since it is unneeded. Link: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1581-2022-01-20 [1] Link: rust-lang/rust-clippy#8045 [2] Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Trevor Gross <tmgross@umich.edu> Tested-by: Gary Guo <gary@garyguo.net> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://lore.kernel.org/r/20240904204347.168520-11-ojeda@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
…ty)]` Rust 1.58.0 (before Rust was merged into the kernel) made Clippy's `non_send_fields_in_send_ty` lint part of the `suspicious` lint group for a brief window of time [1] until the minor version 1.58.1 got released a week after, where the lint was moved back to `nursery`. By that time, we had already upgraded to that Rust version, and thus we had `allow`ed the lint here for `CondVar`. Nowadays, Clippy's `non_send_fields_in_send_ty` would still trigger here if it were enabled. Moreover, if enabled, `Lock<T, B>` and `Task` would also require an `allow`. Therefore, it does not seem like someone is actually enabling it (in, e.g., a custom flags build). Finally, the lint does not appear to have had major improvements since then [2]. Thus remove the `allow` since it is unneeded. Link: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1581-2022-01-20 [1] Link: rust-lang/rust-clippy#8045 [2] Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Trevor Gross <tmgross@umich.edu> Tested-by: Gary Guo <gary@garyguo.net> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://lore.kernel.org/r/20240904204347.168520-11-ojeda@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
The non_send_fields_in_send_ty lint wrongly states that implementations of
Send
are unsound because some fields are!Send
.If the fields were
Send
, there would be no need to writeunsafe impl Send for S {}
, asS
would be automaticallySend
. The only time you need to explicitly implementSend
for a struct is when some fields aren'tSend
. That is why the code needs to be markedunsafe
.The text was updated successfully, but these errors were encountered: