From e7c51320dbe1c5120596265a993dd42f5f11aaf4 Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Sat, 9 Sep 2023 12:30:25 +0530 Subject: [PATCH] Fix ICE in improper_ctypes_definitions lint The lint panicked for an input like 'extern "C" fn(Option<&::FooType>)' because the type T therein cannot be normalized. The normalization failure caused SizeSkeleton::compute() to return an error and trigger a panic in the unwrap(). --- compiler/rustc_lint/src/types.rs | 4 ++-- tests/ui/lint/lint-ctypes-94223.rs | 7 +++++++ tests/ui/lint/lint-ctypes-94223.stderr | 27 +++++++++++++++++--------- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index fc4c29eb36d..c38c6337b7b 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -917,8 +917,8 @@ pub(crate) fn repr_nullable_ptr<'tcx>( // At this point, the field's type is known to be nonnull and the parent enum is Option-like. // If the computed size for the field and the enum are different, the nonnull optimization isn't // being applied (and we've got a problem somewhere). - let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, param_env).unwrap(); - if !compute_size_skeleton(ty).same_size(compute_size_skeleton(field_ty)) { + let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, param_env).ok(); + if !compute_size_skeleton(ty)?.same_size(compute_size_skeleton(field_ty)?) { bug!("improper_ctypes: Option nonnull optimization not applied?"); } diff --git a/tests/ui/lint/lint-ctypes-94223.rs b/tests/ui/lint/lint-ctypes-94223.rs index 70dd2a71f26..ac24f61b0ac 100644 --- a/tests/ui/lint/lint-ctypes-94223.rs +++ b/tests/ui/lint/lint-ctypes-94223.rs @@ -24,6 +24,13 @@ enum BadUnion { type Foo = extern "C" fn([u8]); //~^ ERROR `extern` fn uses type `[u8]`, which is not FFI-safe +pub trait FooTrait { + type FooType; +} + +pub type Foo2 = extern "C" fn(Option<&::FooType>); +//~^ ERROR `extern` fn uses type `Option<&::FooType>`, which is not FFI-safe + pub struct FfiUnsafe; #[allow(improper_ctypes_definitions)] diff --git a/tests/ui/lint/lint-ctypes-94223.stderr b/tests/ui/lint/lint-ctypes-94223.stderr index 49e64ed5140..bd127cf6004 100644 --- a/tests/ui/lint/lint-ctypes-94223.stderr +++ b/tests/ui/lint/lint-ctypes-94223.stderr @@ -66,8 +66,17 @@ LL | type Foo = extern "C" fn([u8]); = help: consider using a raw pointer instead = note: slices have no C equivalent +error: `extern` fn uses type `Option<&::FooType>`, which is not FFI-safe + --> $DIR/lint-ctypes-94223.rs:31:20 + | +LL | pub type Foo2 = extern "C" fn(Option<&::FooType>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:34:17 + --> $DIR/lint-ctypes-94223.rs:41:17 | LL | pub static BAD: extern "C" fn(FfiUnsafe) = f; | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -75,13 +84,13 @@ LL | pub static BAD: extern "C" fn(FfiUnsafe) = f; = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/lint-ctypes-94223.rs:27:1 + --> $DIR/lint-ctypes-94223.rs:34:1 | LL | pub struct FfiUnsafe; | ^^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:37:30 + --> $DIR/lint-ctypes-94223.rs:44:30 | LL | pub static BAD_TWICE: Result = Ok(f); | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -89,13 +98,13 @@ LL | pub static BAD_TWICE: Result $DIR/lint-ctypes-94223.rs:27:1 + --> $DIR/lint-ctypes-94223.rs:34:1 | LL | pub struct FfiUnsafe; | ^^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:37:56 + --> $DIR/lint-ctypes-94223.rs:44:56 | LL | pub static BAD_TWICE: Result = Ok(f); | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -103,13 +112,13 @@ LL | pub static BAD_TWICE: Result $DIR/lint-ctypes-94223.rs:27:1 + --> $DIR/lint-ctypes-94223.rs:34:1 | LL | pub struct FfiUnsafe; | ^^^^^^^^^^^^^^^^^^^^ error: `extern` fn uses type `FfiUnsafe`, which is not FFI-safe - --> $DIR/lint-ctypes-94223.rs:41:22 + --> $DIR/lint-ctypes-94223.rs:48:22 | LL | pub const BAD_CONST: extern "C" fn(FfiUnsafe) = f; | ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -117,10 +126,10 @@ LL | pub const BAD_CONST: extern "C" fn(FfiUnsafe) = f; = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/lint-ctypes-94223.rs:27:1 + --> $DIR/lint-ctypes-94223.rs:34:1 | LL | pub struct FfiUnsafe; | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 11 previous errors +error: aborting due to 12 previous errors