Skip to content

Commit

Permalink
Add a special case for CStr/CString in the improper_ctypes lint
Browse files Browse the repository at this point in the history
Instead of saying to "consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct",
we now tell users to "Use `*const ffi::c_char` instead, and pass the value from `CStr::as_ptr()`" when the
type involved is a `CStr` or a `CString`.
  • Loading branch information
Flying-Toast committed Jan 21, 2024
1 parent 1828461 commit e607e99
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 0 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,10 @@ lint_improper_ctypes_box = box cannot be represented as a single pointer
lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead
lint_improper_ctypes_char_reason = the `char` type has no C equivalent
lint_improper_ctypes_cstr_help = consider using `*const std::ffi::c_char` instead, and pass the value from `CStr::as_ptr()`
lint_improper_ctypes_cstr_reason = `CStr`/`CString` do not have a guaranteed layout
lint_improper_ctypes_dyn = trait objects have no C equivalent
lint_improper_ctypes_enum_repr_help =
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1229,6 +1229,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
match def.adt_kind() {
AdtKind::Struct | AdtKind::Union => {
if let Some(sym::cstring_type | sym::cstr_type) =
tcx.get_diagnostic_name(def.did())
{
return FfiUnsafe {
ty,
reason: fluent::lint_improper_ctypes_cstr_reason,
help: Some(fluent::lint_improper_ctypes_cstr_help),
};
}

if !def.repr().c() && !def.repr().transparent() {
return FfiUnsafe {
ty,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,7 @@ symbols! {
crate_visibility_modifier,
crt_dash_static: "crt-static",
csky_target_feature,
cstr_type,
cstring_type,
ctlz,
ctlz_nonzero,
Expand Down
1 change: 1 addition & 0 deletions library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ use crate::str;
/// [str]: prim@str "str"
#[derive(Hash)]
#[stable(feature = "core_c_str", since = "1.64.0")]
#[rustc_diagnostic_item = "cstr_type"]
#[rustc_has_incoherent_inherent_impls]
#[lang = "CStr"]
// `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies
Expand Down
16 changes: 16 additions & 0 deletions tests/ui/lint/lint-ctypes-cstr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![crate_type = "lib"]
#![deny(improper_ctypes)]

use std::ffi::{CStr, CString};

extern "C" {
fn take_cstr(s: CStr);
//~^ ERROR `extern` block uses type `CStr`, which is not FFI-safe
//~| HELP consider using `*const std::ffi::c_char` instead, and pass the value from `CStr::as_ptr()`
fn take_cstring(s: CString);
//~^ ERROR `extern` block uses type `CString`, which is not FFI-safe
//~| HELP consider using `*const std::ffi::c_char` instead, and pass the value from `CStr::as_ptr()`
fn take_cstring_ref(s: &CString);
//~^ ERROR `extern` block uses type `CString`, which is not FFI-safe
//~| HELP consider using `*const std::ffi::c_char` instead, and pass the value from `CStr::as_ptr()`
}
34 changes: 34 additions & 0 deletions tests/ui/lint/lint-ctypes-cstr.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
error: `extern` block uses type `CStr`, which is not FFI-safe
--> $DIR/lint-ctypes-cstr.rs:7:21
|
LL | fn take_cstr(s: CStr);
| ^^^^ not FFI-safe
|
= help: consider using `*const std::ffi::c_char` instead, and pass the value from `CStr::as_ptr()`
= note: `CStr`/`CString` do not have a guaranteed layout
note: the lint level is defined here
--> $DIR/lint-ctypes-cstr.rs:2:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^

error: `extern` block uses type `CString`, which is not FFI-safe
--> $DIR/lint-ctypes-cstr.rs:10:24
|
LL | fn take_cstring(s: CString);
| ^^^^^^^ not FFI-safe
|
= help: consider using `*const std::ffi::c_char` instead, and pass the value from `CStr::as_ptr()`
= note: `CStr`/`CString` do not have a guaranteed layout

error: `extern` block uses type `CString`, which is not FFI-safe
--> $DIR/lint-ctypes-cstr.rs:13:28
|
LL | fn take_cstring_ref(s: &CString);
| ^^^^^^^^ not FFI-safe
|
= help: consider using `*const std::ffi::c_char` instead, and pass the value from `CStr::as_ptr()`
= note: `CStr`/`CString` do not have a guaranteed layout

error: aborting due to 3 previous errors

0 comments on commit e607e99

Please sign in to comment.