Skip to content

improper_ctypes triggering on Box<T : Sized + FFISafe> is a dangerous false positive that hides uses of actual improper_ctypes #151448

Description

@Morgane55440

Code

#![allow(unused)]
#[link(name = "my_c_library")]
unsafe extern "C" {
    fn my_c_function_1(x: Box<i32>);
    fn my_c_function_2(x: i32) -> Box<String>;
    fn my_c_function_3(x: &mut Box<[u8]>);
}

Current output

warning: `extern` block uses type `Box<i32>`, which is not FFI-safe
 --> src/lib.rs:6:27
  |
6 |     fn my_c_function_1(x: Box<i32>);
  |                           ^^^^^^^^ not FFI-safe
  |
  = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
  = note: this struct has unspecified layout
  = note: `#[warn(improper_ctypes)]` on by default

warning: `extern` block uses type `Box<String>`, which is not FFI-safe
 --> src/lib.rs:7:35
  |
7 |     fn my_c_function_2(x: i32) -> Box<String>;
  |                                   ^^^^^^^^^^^ not FFI-safe
  |
  = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
  = note: this struct has unspecified layout

warning: `extern` block uses type `Box<[u8]>`, which is not FFI-safe
 --> src/lib.rs:8:27
  |
8 |     fn my_c_function_3(x: &mut Box<[u8]>);
  |                           ^^^^^^^^^^^^^^ not FFI-safe
  |
  = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
  = note: this struct has unspecified layout

Desired output

warning: `extern` block uses type `String`, which is not FFI-safe
 --> src/lib.rs:8:35
  |
8 |     fn my_c_function_2(x: i32) -> Box<String>;
  |                                   ^^^^^^^^^^^ not FFI-safe
  |
  = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
  = note: this struct has unspecified layout
  = note: `#[warn(improper_ctypes)]` on by default

warning: `extern` block uses type `[u8]`, which is not FFI-safe
 --> src/lib.rs:9:27
  |
9 |     fn my_c_function_3(x: &mut Box<[u8]>);
  |                           ^^^^^^^^^^^^^^ not FFI-safe
  |
  = help: consider using a raw pointer instead
  = note: slices have no C equivalent

Rationale and extra context

Box is FFI safe, as promised by its documentation https://doc.rust-lang.org/std/boxed/index.html#memory-layout.
its use may be dangerous, as it must always be aligned, nonnull, has strict aliasing rules, and must be allocated and deallocated in rust, but it can still be very useful in well crafted APIs.

having improper_ctypes trigger on it forces users who use it to add allow/expect(improper_ctypes), preventing them from seeing other improper_ctypes behind the indirection.

thus i believe Box should be special-cased to have improper_ctypes not trigger on it directly.

i believe it should behave the exact same way as other pointers do(*mut/*const/NonNull/&/&mut).
note that this should only apply for Box<T,GLobal>, as no guarantees are made about other allocators, especially if they are not 1-aligned ZSTs

link to a forum post where a user ran into this exact issue https://users.rust-lang.org/t/ffi-safety-of-box-t/39156

on the note of the danger posed by the many safety and validity invariants of Box, i would like to note that &mut shares many of them, and does not trigger improper_ctypes. as it should given it is layout compatible.

Rust Version

rustc 1.92.0 (ded5c06cf 2025-12-08)
binary: rustc
commit-hash: ded5c06cf21d2b93bffd5d884aa6e96934ee4234
commit-date: 2025-12-08
host: x86_64-pc-windows-msvc
release: 1.92.0
LLVM version: 21.1.3

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-FFIArea: Foreign function interface (FFI)A-boxArea: Our favorite opsem complicationA-diagnosticsArea: Messages for errors, warnings, and lintsA-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.L-improper_ctypesLint: improper_ctypesT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions