From cd228ce5609bae8bd43e5fe9d478708ebc600c78 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Thu, 2 Jul 2026 12:59:53 +0900 Subject: [PATCH 1/2] add regression test for NonZero improper_ctypes ICE --- tests/ui/lint/improper-ctypes/nonzero-char.rs | 13 +++++++++++++ .../ui/lint/improper-ctypes/nonzero-char.stderr | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/ui/lint/improper-ctypes/nonzero-char.rs create mode 100644 tests/ui/lint/improper-ctypes/nonzero-char.stderr diff --git a/tests/ui/lint/improper-ctypes/nonzero-char.rs b/tests/ui/lint/improper-ctypes/nonzero-char.rs new file mode 100644 index 0000000000000..1c60322060af7 --- /dev/null +++ b/tests/ui/lint/improper-ctypes/nonzero-char.rs @@ -0,0 +1,13 @@ +// Regression test for https://github.com/rust-lang/rust/issues/158511. + +#![allow(dead_code)] +#![deny(improper_ctypes)] + +use std::num; + +extern "C" { + fn result_nonzero_u32_t(x: Result, ()>); + //~^ ERROR `extern` block uses type `char`, which is not FFI-safe +} + +fn main() {} diff --git a/tests/ui/lint/improper-ctypes/nonzero-char.stderr b/tests/ui/lint/improper-ctypes/nonzero-char.stderr new file mode 100644 index 0000000000000..4c1940fe4318f --- /dev/null +++ b/tests/ui/lint/improper-ctypes/nonzero-char.stderr @@ -0,0 +1,16 @@ +error: `extern` block uses type `char`, which is not FFI-safe + --> $DIR/nonzero-char.rs:9:32 + | +LL | fn result_nonzero_u32_t(x: Result, ()>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider using `u32` or `libc::wchar_t` instead + = note: the `char` type has no C equivalent +note: the lint level is defined here + --> $DIR/nonzero-char.rs:4:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From 427a94a96cb0a694dce06cf51b85e830fd03c983 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Thu, 2 Jul 2026 13:08:31 +0900 Subject: [PATCH 2/2] avoid ICE for NonZero in improper_ctypes --- compiler/rustc_lint/src/types.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index a12e347284f7c..58599db734c49 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -793,7 +793,7 @@ fn get_nullable_type<'tcx>( return get_nullable_type(tcx, typing_env, inner_field_ty); } ty::Pat(base, ..) => return get_nullable_type(tcx, typing_env, base), - ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => ty, + ty::Int(_) | ty::Uint(_) | ty::Char | ty::RawPtr(..) => ty, // As these types are always non-null, the nullable equivalent of // `Option` of these types are their raw pointer counterparts. ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl), @@ -895,10 +895,14 @@ pub(crate) fn repr_nullable_ptr<'tcx>( WrappingRange { start: 0, end } if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 => { - return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); + return Some(get_nullable_type(tcx, typing_env, field_ty).expect( + "known non-null scalar type should have a nullable representation", + )); } WrappingRange { start: 1, .. } => { - return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); + return Some(get_nullable_type(tcx, typing_env, field_ty).expect( + "known non-null scalar type should have a nullable representation", + )); } WrappingRange { start, end } => { unreachable!("Unhandled start and end range: ({}, {})", start, end)