-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
improper_ctypes fires for &mut T, &T, *const T and *mut T (when T: Sized) #66220
Comments
Is |
Yes, here's the playground example pub struct Foo {
_x: i32,
}
#[no_mangle]
pub extern "C" fn foo(_: *const Foo) {}
|
I am pretty sure this is intentional (or was, when this part of the lint was implemented), but that doesn't mean it can't change. This is a scenario where reasonable interpretations of the lint disagree with each other:
It is not obvious to me which side the |
I believe this could possibly be a separate lint (and with a different message too |
Splitting up into two different lints seems interesting (as long as both stay in rustc and enabled by default). It comes with an interesting backwards compatibility question, though. We probably wouldn't want projects that used |
Is there any way to mark a type (instead of the method) as "I know this is improper but don't warn me about it"? #[repr(transparent)]
#[allow(improper_ctypes)]
pub struct Opaque<T>(T);
pub extern "C" fn foo(_: *const Opaque<String>) {} The following does work, which surprised me because #[repr(transparent)]
pub struct OpaquePtr<T>(*mut std::ffi::c_void, std::marker::PhantomData<T>);
pub extern "C" fn bar(_: OpaquePtr<String>) {} I'm just looking for ways to describe the "FFI just passes the pointer around" intent in the type system. I realize the use of this might be noisy at scale given there's no automatic conversion between the types and would need manual wrapping and unwrapping. |
Well idea would be to mark it with |
I believe this doesn't work because the lint message is associated with the function rather than the type(s) which the lint finds objectionable. I don't know how difficult it would be to support this, I guess it would be something of a special case at best.
|
#65134 adds thousands of new warnings to Servo. The pervasive pattern is that we have many Changing the parameter type to Now I’m tempted to add Please consider reverting #65134, or making raw pointers unconditionally FFI-safe. CC @rust-lang/lang |
Does it really? It’s nightly-only still, isn’t it? That level of churn (in the small timeframe present) seems acceptable in nightly. |
I'm confused, #65867 is unrelated (as discussed there, probably wasn't even a legit issue, just a temporary issue with #65134, that I thought was pre-existing and independent from that PR). You might be thinking of #19834 that actually predates and motivated #65134? But I didn't file that, FWIW. In any case, I think we should revert #65134 right now so we can discuss how to handle the unexpected fallout without pressure. Options raised so far include:
It's a messy subject and I'd rather not see people add |
Since the PR description for #65134 contains “Fixes #65867” I assumed it was an implementation of what that issue proposed.
I’d rather not add it either, but at this point it’s the only practical way (without changing all parameters to |
I added this to the PR when @rkruppe filed #65867 since it was, as @rkruppe said, a temporary issue within #65134 that it resolved. Just to clarify, #65134 didn't change the behaviour of the lint so that would trigger for Perhaps a good compromise would be to stop looking at the |
cc #66373
@davidtwco Not sure how invasive that would be in the lint code but as an interim solution, that seems reasonable. Would you be up for implementing the tweak? |
Nominating for discussion at T-compiler meeting, largely to figure out whether we should ASAP revert PR #65134 as a whole, or if we should/can wait for a more nuanced solution/compromise. |
I think we should revert ASAP, and I say this as someone who was very eager to get the PR merged. It's likely quicker to revert than to land any tweaks, especially since we have to consider the possibility that whatever tweaks get done quickly/first will turn out to be insufficient. Plus, after the revert, a PR with the tweaked lint can get a try build either for a crater run or for affected projects like Servo to try out the tweaked rules. That will allow us to judge how effective the tweaks are without time pressure. (Also feel free to @ me in the T-compiler meeting when discussing this, I'm free in that time slot.) |
@davidtwco Yes, that compromise would take care of Servo’s new warnings and unblock the compiler upgrade. However it effectively means there are two different definitions of "FFI-safe". I don’t know how desirable that is. |
(Reverting #65134 would also unblock Servo.) |
I want to take the devil's advocate here. I think that if someone is passing pointers to C with the point of being opaque the right thing to do is use void pointer. But I would agree as a compromise that we can not lint this when it's a |
Then you lose all type safety on Rust's side. I'm passing stuff like Option<&mut RustType> as parameters and return values in my FFI. In fact my C API comprised of 250 functions or so is almost entirely safe (only C strings are unsafe, and even those can be made safe). Also I'm automatically generating safe high level bindings from the C API, and that wouldn't really be possible anymore if everything was just *const c_void. I don't think throwing out all safety / type safety is a good long term solution. |
@CryZe I edited my post.
Writing this code shows you know what you're doing, you know you're using it as an opaque pointer because you're using void pointer. if you don't use void pointer i'd argue it's more likely you just forgot putting a repr or you have no idea what you're doing. |
Boiling the ocean is not realistic. Many projects already exists with hundreds of FFI bindings. Migrating every extern function to have a wrapper function and every parameter to have a wrapper type would be an enormous amount of work. And that proposal does lose type safety. If you use bindgen, all the other side sees is still |
I understand, I'm just trying to also say that usually people pass stuff to C code by const pointers and not by value, so not checking the repr on those arguments means the lint lose most of it's usefulness for the regular user (who needs the lint the most) |
Hence the need for two separate lints: it depends on the use case. |
As a matter of fact, the following code triggers the lint: #[no_mangle] pub
unsafe
extern "C"
fn foo (_: *const Foo) {}
pub
struct Foo {
_private: [u8; 0],
} Given that no members of |
The T-lang design team discussed this matter in their weekly meeting about a week ago. (Sorry I didn't take the time to write a summary until now.)
Some cases caught by Other cases caught by the lint are just trying to help the developer avoid footguns. Specifically, as pointed out earlier by @rkruppe, the
A related point brought up during the lang team meeting: before, when the lint only covered
Overall, there was a general consensus that we do not want to just reland PR # #65134 (not that anyone on this thread was currently suggesting doing that). A more nuanced approach seems justified here. @rkruppe has laid out some options previously. I think the options the T-lang design team was most interested in exploring were either:
The T-lang design team did not come to a conclusion as to which of the above two approaches we thought would be best. (And I have generalized the statements here to make it clear that its possible that we will want a mix of the two.) Would @davidtwco and/or @rkruppe be interested in trying to explore the design space of the above two points, and come back with a concrete proposal after doing such exploration? |
FWIW, personally I have come to believe that we should definitely split up the lint (with or without the other option) since it's useful independently of this specific issue, but I don't think I can commit the time to explore this further or write up a more detailed proposal any time soon. (If I get pinged to discuss that in Discord or Zulip, I probably won't be able to resist being nerd-sniped. Please use this knowledge responsibly :P) |
I’m happy to perform any implementation required here, but I don’t have any particular opinions on the semantics - I just spotted #19834 as work needing done. I’m happy to proceed with making the lint behave differently (for this case) depending on |
triage: since PR #66378 has landed, I am reclassifying this as P-medium. |
removing nomination label. T-compiler does not need to discuss this, at least not until the follow-up work is done. |
…es-declarations, r=lcnr,varkor `improper_ctypes_definitions` lint Addresses rust-lang#19834, rust-lang#66220, and rust-lang#66373. This PR takes another attempt at rust-lang#65134 (reverted in rust-lang#66378). Instead of modifying the existing `improper_ctypes` lint to consider `extern "C" fn` definitions in addition to `extern "C" {}` declarations, this PR adds a new lint - `improper_ctypes_definitions` - which only applies to `extern "C" fn` definitions. In addition, the `improper_ctype_definitions` lint differs from `improper_ctypes` by considering `*T` and `&T` (where `T: Sized`) FFI-safe (addressing rust-lang#66220). There wasn't a clear consensus in rust-lang#66220 (where the issues with rust-lang#65134 were primarily discussed) on the approach to take, but there has [been some discussion in Zulip](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/.2366220.20improper_ctypes.20definitions.20vs.20declarations/near/198903086). I fully expect that we'll want to iterate on this before landing. cc @varkor + @shepmaster (from rust-lang#19834) @hanna-kruppe (active in discussing rust-lang#66220), @SimonSapin (rust-lang#65134 caused problems for Servo, want to make sure that this PR doesn't)
…es-declarations, r=lcnr,varkor `improper_ctypes_definitions` lint Addresses rust-lang#19834, rust-lang#66220, and rust-lang#66373. This PR takes another attempt at rust-lang#65134 (reverted in rust-lang#66378). Instead of modifying the existing `improper_ctypes` lint to consider `extern "C" fn` definitions in addition to `extern "C" {}` declarations, this PR adds a new lint - `improper_ctypes_definitions` - which only applies to `extern "C" fn` definitions. In addition, the `improper_ctype_definitions` lint differs from `improper_ctypes` by considering `*T` and `&T` (where `T: Sized`) FFI-safe (addressing rust-lang#66220). There wasn't a clear consensus in rust-lang#66220 (where the issues with rust-lang#65134 were primarily discussed) on the approach to take, but there has [been some discussion in Zulip](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/.2366220.20improper_ctypes.20definitions.20vs.20declarations/near/198903086). I fully expect that we'll want to iterate on this before landing. cc @varkor + @shepmaster (from rust-lang#19834) @hanna-kruppe (active in discussing rust-lang#66220), @SimonSapin (rust-lang#65134 caused problems for Servo, want to make sure that this PR doesn't)
…es-declarations, r=lcnr,varkor `improper_ctypes_definitions` lint Addresses rust-lang#19834, rust-lang#66220, and rust-lang#66373. This PR takes another attempt at rust-lang#65134 (reverted in rust-lang#66378). Instead of modifying the existing `improper_ctypes` lint to consider `extern "C" fn` definitions in addition to `extern "C" {}` declarations, this PR adds a new lint - `improper_ctypes_definitions` - which only applies to `extern "C" fn` definitions. In addition, the `improper_ctype_definitions` lint differs from `improper_ctypes` by considering `*T` and `&T` (where `T: Sized`) FFI-safe (addressing rust-lang#66220). There wasn't a clear consensus in rust-lang#66220 (where the issues with rust-lang#65134 were primarily discussed) on the approach to take, but there has [been some discussion in Zulip](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/.2366220.20improper_ctypes.20definitions.20vs.20declarations/near/198903086). I fully expect that we'll want to iterate on this before landing. cc @varkor + @shepmaster (from rust-lang#19834) @hanna-kruppe (active in discussing rust-lang#66220), @SimonSapin (rust-lang#65134 caused problems for Servo, want to make sure that this PR doesn't)
Closing, #72700 fixes this. |
I'm not sure if this is intentional, but I haven't found any discussion regarding this. The improper_ctypes lint fires on pointer types when T is not FFI safe. However pointers have defined layout that is always FFI safe, independent of what the pointer is pointing to. It certainly seems valid to point out the pointer won't be able to be dereferenced by C. This should probably be a clippy lint though. Rust itself shouldn't fire false positives like this.
The text was updated successfully, but these errors were encountered: