Uh oh!
There was an error while loading. Please reload this page.
Remove confusing comment about ideally using ! for c_void - #56594
Conversation
rust-highfive
commented
Dec 7, 2018
r? @TimNN (rust_highfive has picked a reviewer for you, use r? to override) |
sdroege
commented
Dec 7, 2018
This might be something @RalfJung could know and clarify :) |
RalfJung
commented
Dec 8, 2018
Maybe. That's not decided yet (and I think it shouldn't be). But |
RalfJung
commented
Dec 8, 2018
So concerning this PR, I basically agree with this change, but there are some comments here that are still dangerously misleading. Namely, the comments say that the two variants shouldn't have to exist. But that would be fatal! An enum with no variants behaves exactly like So the non-doc-comments here should also be fixed to explain that we need at least one variant to avoid UB.
Cc @gankro The nomicon pattern is designed to avoid the non-FFI-safe-types warning. Does this enum also avoid that? |
sdroege
commented
Dec 10, 2018
Thanks a lot for the clarifications!
Thanks, I've updated the comment and
Ok, intuitively it would seem like such references should never exist similar to how references to
There don't seem to be any warnings, no. See https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7c3c81c0b724dafbb2ed11d6ee943697 use std::ffi::c_void;pubstructFoo(c_void);pubextern"C"fnmeh1(m:*mutFoo) -> *mutFoo{ m }#[repr(C)]pubstructBar{v:*mutFoo,}pubextern"C"fnmeh2(m:*mutBar) -> *mutBar{ m } |
No, references must never be NULL. That's part of their validity invariant.
Uninhabitedness is not a special property when it comes to UB. I think "is having a
That's great! @SimonSapin do you remember why you suggested this empty-array pattern in rust-lang/nomicon#44 instead of a newtype around |
RalfJung
commented
Dec 10, 2018
Actually, it seems there never are warnings for exporting functions. But this also does not warn (we do need the use std::ffi::c_void;#[repr(C)]pubstructFoo(c_void);extern"C"{fnmeh1(m:*mutFoo) -> *mutFoo;} |
SimonSapin
commented
Dec 10, 2018
To avoid uninhabited types, it seemed like a zero-size type would be the next closest thing. To avoid some misuses this type should not be trivial to construct, so it should have a private field.
|
SimonSapin
commented
Dec 10, 2018
That would fit in a one-liner. |
Gankra
commented
Dec 10, 2018
(gonna assume Simon has this issue covered) |
sdroege
commented
Dec 10, 2018
Why is the
Is passing of ZST over FFI well-defined? A pointer to one, sure Is there any advantage for having a ZST here over |
RalfJung
commented
Dec 10, 2018
Ah right, the point was to make it a ZST! Thanks for reminding me.
Yes: If you ever accidentally dereference the pointer, it's a NOP if it points to a ZST. |
SimonSapin
commented
Dec 10, 2018
Yes, that was the point but I’m not sure how important it is. When a type does not implement any trait (in particular not |
sdroege
commented
Dec 10, 2018
Ok, that makes sense but also doesn't really make a difference in practice compared to reading a byte or does it? Unless it was an dangling pointer but in that case... So I guess,
|
RalfJung
commented
Dec 12, 2018
Given that this is a pointer to an opaque type, the opaque type might have size 0, and in that case the read would be a problem.
I think this PR is an improvement over the status quo certainly, and as such I'm in favor of landing it. However, it'd be nice to be consistent with the FFI section in the nomicon -- we should recommend the same thing for the same job. So, I'd prefer if instead of recommending to use this for opaque extern types, it would point to the nomicon.
Yes. Struct field ordering otherwise may differ between C and Rust (and even between different Rust versions).
I'd prefer to keep recommending the empty array. Eventually (TM), we'll have extern types and then the answer about what to use is quite clear. |
sdroege
commented
Dec 12, 2018
Thanks for the clarifications :)
But as this is an opaque type we don't even know its fields. That was my point, you only have a pointer of reference but don't know what's behind it anyway.
OK, I'll update it accordingly later and also add a link to the Thanks again for all the explanations :) |
sdroege
commented
Dec 12, 2018
Updated |
392db0f to
7a4d32fCompareRalfJung
commented
Dec 12, 2018
I guess then it strictly speaking doesn't matter. But there also is no reason not to use |
Uh oh!
There was an error while loading. Please reload this page.
sdroege
commented
Dec 13, 2018
Sure, this was just to complete my understanding. I agree that marking things as |
Using `!` for `c_void` would have the problem that pointers and potentially references to an uninhabited type would be created, and at least for references this is UB. Also document in addition that newtype wrappers around `c_void` are not recommended for representing opaque types (as a workaround for `extern type` not being stable) but instead refer to the Nomicon.
…rent implementation We need at least two variants of the enum as otherwise the compiler complains about the #[repr(u8)] attribute and we also need at least one variant as otherwise the enum would be uninhabitated and dereferencing pointers to it would be UB. As such, mark the variants not unstable because they should not actually exist but because they are temporary implementation details until `extern type` is stable and can be used instead.
7a4d32f to
8de8880CompareRalfJung
commented
Dec 13, 2018
This patch looks good to me now. @SimonSapin what do you think? |
SimonSapin
commented
Dec 13, 2018
The diff says Note that |
sdroege
commented
Dec 14, 2018
The idea was that it could be replaced with
Moving
And this documentation/comments update here would bring all these things in sync again. However your point about |
SimonSapin
commented
Dec 14, 2018
I assume we didn’t realize the |
Gankra
commented
Dec 14, 2018
also extern types have been stalled precisely because how size is supposed to work was punted on, and no one can agree on how to proceed |
sdroege
commented
Dec 15, 2018
I see, I didn't realize that this is still an open issue. So what to do here then? Feel free to simply close the PR if you think there's no value in this before everything else is cleared up elsewhere. IMHO |
I've read some of the discussion and skimmed the rest. Overall I think the new docs are an improvement over the old ones, so: @bors r+ (If someone disagrees, please comment / |
bors
commented
Jan 15, 2019
📌 Commit 8de8880 has been approved by |
Centril
commented
Jan 15, 2019
@bors rollup |
Remove confusing comment about ideally using `!` for `c_void` Using `!` for `c_void` would have the problem that pointers and potentially references to an uninhabited type would be created, and at least for references this is UB. In addition document that newtype wrappers around `c_void` can be used safely in place of `extern type` until the latter is stabilized. ---- I'm not 100% sure about the usage for opaque types as the [nomicon](https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs) still recommends using `#[repr(C)] pub struct Foo { _private: [u8; 0] }` but it seems like these two should be equivalent in the end? Also the `#[repr(C)]` (in both cases) should be unneeded because such types never being passed by value, never being dereferenced but only passed around as pointer or reference, so the representation of (*values* of) the type itself should not matter at all? Also in context of `c_void` and `!` the second unresolved question in the [`extern type`](rust-lang#43467) stabilization ticket seems relevant > In [std's](https://github.com/rust-lang/rust/blob/164619a8cfe6d376d25bd3a6a9a5f2856c8de64d/src/libstd/os/raw.rs#L59-L64) source, it is mentioned that LLVM expects i8* for C's void*. > We'd need to continue to hack this for the two c_voids in std and libc. > But perhaps this should be done across-the-board for all extern types? > Somebody should check what Clang does. Please correct me if my understanding is wrong and everything's actually fine as is.
Remove confusing comment about ideally using `!` for `c_void` Using `!` for `c_void` would have the problem that pointers and potentially references to an uninhabited type would be created, and at least for references this is UB. In addition document that newtype wrappers around `c_void` can be used safely in place of `extern type` until the latter is stabilized. ---- I'm not 100% sure about the usage for opaque types as the [nomicon](https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs) still recommends using `#[repr(C)] pub struct Foo { _private: [u8; 0] }` but it seems like these two should be equivalent in the end? Also the `#[repr(C)]` (in both cases) should be unneeded because such types never being passed by value, never being dereferenced but only passed around as pointer or reference, so the representation of (*values* of) the type itself should not matter at all? Also in context of `c_void` and `!` the second unresolved question in the [`extern type`](rust-lang#43467) stabilization ticket seems relevant > In [std's](https://github.com/rust-lang/rust/blob/164619a8cfe6d376d25bd3a6a9a5f2856c8de64d/src/libstd/os/raw.rs#L59-L64) source, it is mentioned that LLVM expects i8* for C's void*. > We'd need to continue to hack this for the two c_voids in std and libc. > But perhaps this should be done across-the-board for all extern types? > Somebody should check what Clang does. Please correct me if my understanding is wrong and everything's actually fine as is.
Remove confusing comment about ideally using `!` for `c_void` Using `!` for `c_void` would have the problem that pointers and potentially references to an uninhabited type would be created, and at least for references this is UB. In addition document that newtype wrappers around `c_void` can be used safely in place of `extern type` until the latter is stabilized. ---- I'm not 100% sure about the usage for opaque types as the [nomicon](https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs) still recommends using `#[repr(C)] pub struct Foo { _private: [u8; 0] }` but it seems like these two should be equivalent in the end? Also the `#[repr(C)]` (in both cases) should be unneeded because such types never being passed by value, never being dereferenced but only passed around as pointer or reference, so the representation of (*values* of) the type itself should not matter at all? Also in context of `c_void` and `!` the second unresolved question in the [`extern type`](rust-lang#43467) stabilization ticket seems relevant > In [std's](https://github.com/rust-lang/rust/blob/164619a8cfe6d376d25bd3a6a9a5f2856c8de64d/src/libstd/os/raw.rs#L59-L64) source, it is mentioned that LLVM expects i8* for C's void*. > We'd need to continue to hack this for the two c_voids in std and libc. > But perhaps this should be done across-the-board for all extern types? > Somebody should check what Clang does. Please correct me if my understanding is wrong and everything's actually fine as is.
Remove confusing comment about ideally using `!` for `c_void` Using `!` for `c_void` would have the problem that pointers and potentially references to an uninhabited type would be created, and at least for references this is UB. In addition document that newtype wrappers around `c_void` can be used safely in place of `extern type` until the latter is stabilized. ---- I'm not 100% sure about the usage for opaque types as the [nomicon](https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs) still recommends using `#[repr(C)] pub struct Foo { _private: [u8; 0] }` but it seems like these two should be equivalent in the end? Also the `#[repr(C)]` (in both cases) should be unneeded because such types never being passed by value, never being dereferenced but only passed around as pointer or reference, so the representation of (*values* of) the type itself should not matter at all? Also in context of `c_void` and `!` the second unresolved question in the [`extern type`](rust-lang#43467) stabilization ticket seems relevant > In [std's](https://github.com/rust-lang/rust/blob/164619a8cfe6d376d25bd3a6a9a5f2856c8de64d/src/libstd/os/raw.rs#L59-L64) source, it is mentioned that LLVM expects i8* for C's void*. > We'd need to continue to hack this for the two c_voids in std and libc. > But perhaps this should be done across-the-board for all extern types? > Somebody should check what Clang does. Please correct me if my understanding is wrong and everything's actually fine as is.
Remove confusing comment about ideally using `!` for `c_void` Using `!` for `c_void` would have the problem that pointers and potentially references to an uninhabited type would be created, and at least for references this is UB. In addition document that newtype wrappers around `c_void` can be used safely in place of `extern type` until the latter is stabilized. ---- I'm not 100% sure about the usage for opaque types as the [nomicon](https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs) still recommends using `#[repr(C)] pub struct Foo { _private: [u8; 0] }` but it seems like these two should be equivalent in the end? Also the `#[repr(C)]` (in both cases) should be unneeded because such types never being passed by value, never being dereferenced but only passed around as pointer or reference, so the representation of (*values* of) the type itself should not matter at all? Also in context of `c_void` and `!` the second unresolved question in the [`extern type`](rust-lang#43467) stabilization ticket seems relevant > In [std's](https://github.com/rust-lang/rust/blob/164619a8cfe6d376d25bd3a6a9a5f2856c8de64d/src/libstd/os/raw.rs#L59-L64) source, it is mentioned that LLVM expects i8* for C's void*. > We'd need to continue to hack this for the two c_voids in std and libc. > But perhaps this should be done across-the-board for all extern types? > Somebody should check what Clang does. Please correct me if my understanding is wrong and everything's actually fine as is.
Remove confusing comment about ideally using `!` for `c_void` Using `!` for `c_void` would have the problem that pointers and potentially references to an uninhabited type would be created, and at least for references this is UB. In addition document that newtype wrappers around `c_void` can be used safely in place of `extern type` until the latter is stabilized. ---- I'm not 100% sure about the usage for opaque types as the [nomicon](https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs) still recommends using `#[repr(C)] pub struct Foo { _private: [u8; 0] }` but it seems like these two should be equivalent in the end? Also the `#[repr(C)]` (in both cases) should be unneeded because such types never being passed by value, never being dereferenced but only passed around as pointer or reference, so the representation of (*values* of) the type itself should not matter at all? Also in context of `c_void` and `!` the second unresolved question in the [`extern type`](rust-lang#43467) stabilization ticket seems relevant > In [std's](https://github.com/rust-lang/rust/blob/164619a8cfe6d376d25bd3a6a9a5f2856c8de64d/src/libstd/os/raw.rs#L59-L64) source, it is mentioned that LLVM expects i8* for C's void*. > We'd need to continue to hack this for the two c_voids in std and libc. > But perhaps this should be done across-the-board for all extern types? > Somebody should check what Clang does. Please correct me if my understanding is wrong and everything's actually fine as is.
Remove confusing comment about ideally using `!` for `c_void` Using `!` for `c_void` would have the problem that pointers and potentially references to an uninhabited type would be created, and at least for references this is UB. In addition document that newtype wrappers around `c_void` can be used safely in place of `extern type` until the latter is stabilized. ---- I'm not 100% sure about the usage for opaque types as the [nomicon](https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs) still recommends using `#[repr(C)] pub struct Foo { _private: [u8; 0] }` but it seems like these two should be equivalent in the end? Also the `#[repr(C)]` (in both cases) should be unneeded because such types never being passed by value, never being dereferenced but only passed around as pointer or reference, so the representation of (*values* of) the type itself should not matter at all? Also in context of `c_void` and `!` the second unresolved question in the [`extern type`](rust-lang#43467) stabilization ticket seems relevant > In [std's](https://github.com/rust-lang/rust/blob/164619a8cfe6d376d25bd3a6a9a5f2856c8de64d/src/libstd/os/raw.rs#L59-L64) source, it is mentioned that LLVM expects i8* for C's void*. > We'd need to continue to hack this for the two c_voids in std and libc. > But perhaps this should be done across-the-board for all extern types? > Somebody should check what Clang does. Please correct me if my understanding is wrong and everything's actually fine as is.
Rollup of 10 pull requests Successful merges: - #56594 (Remove confusing comment about ideally using `!` for `c_void`) - #57340 (Use correct tracking issue for c_variadic) - #57357 (Cleanup PartialEq docs.) - #57551 (resolve: Add a test for issue #57539) - #57636 (Fix sources sidebar not showing up) - #57646 (Fixes text becoming invisible when element targetted) - #57654 (Add some links in std::fs.) - #57683 (Document Unpin in std::prelude documentation) - #57685 (Enhance `Pin` impl applicability for `PartialEq` and `PartialOrd`.) - #57710 (Fix non-clickable urls) Failed merges: r? @ghost
Using
!forc_voidwould have the problem that pointers andpotentially references to an uninhabited type would be created, and at
least for references this is UB.
In addition document that newtype wrappers around
c_voidcan be usedsafely in place of
extern typeuntil the latter is stabilized.I'm not 100% sure about the usage for opaque types as the nomicon still recommends using
#[repr(C)] pub struct Foo { _private: [u8; 0] }but it seems like these two should be equivalent in the end? Also the#[repr(C)](in both cases) should be unneeded because such types never being passed by value, never being dereferenced but only passed around as pointer or reference, so the representation of (values of) the type itself should not matter at all?Also in context of
c_voidand!the second unresolved question in theextern typestabilization ticket seems relevantPlease correct me if my understanding is wrong and everything's actually fine as is.