lint: transitive FFI-safety for transparent types

This commit ensures that if a `repr(transparent)` newtype's only
non-zero-sized field is FFI-safe then the newtype is also FFI-safe.

Previously, ZSTs were ignored for the purposes of linting FFI-safety
in transparent structs - thus, only the single non-ZST would be checked
for FFI-safety. However, if the non-zero-sized field is a generic
parameter, and is substituted for a ZST, then the type would be
considered FFI-unsafe (as when every field is thought to be zero-sized,
the type is considered to be "composed only of `PhantomData`" which is
FFI-unsafe).

In this commit, for transparent structs, the non-zero-sized field is
identified (before any substitutions are applied, necessarily) and then
that field's type (now with substitutions) is checked for FFI-safety
(where previously it would have been skipped for being zero-sized in
this case).

To handle the case where the non-zero-sized field is a generic
parameter, which is substituted for `()` (a ZST), and is being used
as a return type - the `FfiUnsafe` result (previously `FfiPhantom`) is
caught and silenced.

Signed-off-by: David Wood <david@davidtw.co>
This commit is contained in:
David Wood 2020-06-01 17:00:58 +01:00
parent 3e7aabb1b3
commit d4d3d7de68
No known key found for this signature in database
GPG key ID: 2592E76C87381FD9
5 changed files with 69 additions and 51 deletions

View file

@ -1,3 +1,5 @@
// check-pass
#![deny(improper_ctypes)]
// This test checks that return types are normalized before being checked for FFI-safety, and that
@ -10,7 +12,6 @@ extern "C" {
pub fn bare() -> ();
pub fn normalize() -> <() as ToOwned>::Owned;
pub fn transparent() -> W<()>;
//~^ ERROR uses type `W<()>`
}
fn main() {}

View file

@ -1,20 +0,0 @@
error: `extern` block uses type `W<()>`, which is not FFI-safe
--> $DIR/lint-ctypes-66202.rs:12:29
|
LL | pub fn transparent() -> W<()>;
| ^^^^^ not FFI-safe
|
note: the lint level is defined here
--> $DIR/lint-ctypes-66202.rs:1:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= note: composed only of `PhantomData`
note: the type is defined here
--> $DIR/lint-ctypes-66202.rs:7:1
|
LL | pub struct W<T>(T);
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error