Change:
pub fn good17(p: TransparentCustomZst); #[allow(improper_ctypes)] pub fn good18(_: &String); <ins> pub fn good20(arr: *const [u8; 8]); pub static good21: [u8; 8]; </ins> } #[allow(improper_ctypes)]

Discussion:
Arrays are passed to C as a raw pointers, which means that does not move it, so this example is confusing at best. () Errors: If one does not try to use the moved value, this will silently compile, but will be deallocated as soon as the function returns, yet the C code could still try to read (or even write - the code above doesn't make it clear what C can actually do with the pointer...) to it. It would be better if we would require code to be more explicit about this, e.g., by writing: instead. This makes it clear that doesn't own the array, how many elements are expected behind the pointer, and whether the foreign function only reads or also might write to it. We could avoid breaking changes due to updating C FFI code by allowing people to still call but treating it a as a unique or shared borrow depending on the mutability of the FFI declaration, and then applying a coercion to the raw pointer, while simultaneously emitting a warning to users that they should be more explicit and write instead.
FWIW, my preferred solution to this problem would be to just warn when arrays are not used behind a pointer on foreign function declarations, and maybe ban that in a future edition. I would prefer if we would just do that, and call it a day. However, I imagine that a lot of code will want to update to avoid this warning, or be compatible with a future edition. This will require API breaking changes all over the place. We could either say, "such is life", or we could try to allow updating the signatures of the FFI declarations without breaking their callers. Iff that were something worth doing, then the idea I suggested of automatically borrowing the array according to the mutability of the C FFI foreign function declaration fixes the error message of my example, where it is incorrectly diagnosed that the array was moved. In a sense, this is what we are already doing when we transform moves of arrays into pointers when calling foreign functions, so it isn't really a type system change, but rather a bug fix to the implementation of the type system that we already have.
Is this not just a duplicate of ?
It's an accident that the ABI matches up, since in Rust is equivalent to in C++, i.e. in C (although we might not guarantee any of that).

And then there's stuff like this, which I don't think we should have landed - the situation in question is impossible in C (since you always would have a wrapper ):
I think raw arrays should be marked as . arrays should be passed by ref/pointer. EDIT: Related: Will try to make a PR.

(imported from improperly closed bug ) You cannot pass an array to or return an array from a C function. The signature is equivalent to for every in C. Therefore it is meaningless to write this in Rust, (or rather, it does not mean what a C programmer and/or FFI generation tool likely thinks it means): Option for dealing with this: We can extend our existing lint to detect cases like this and warn about them. We could make the form reject this signature, since the expected correspondence between Rust and C does not hold here. If the Rust FFI binding generation scripts/programs out there are generating this sort of code, they need to be fixed.
triage: P-low
Triage: array syntax has changed, here's the correct syntax: no warning or anything.
Triage: no change
This would have to be implemented as a lint now due to the potential of breaking existing builds. It should be easy enough to implement.