diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 5b2100b5da9d1..b1ff76865abda 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2781,8 +2781,7 @@ impl ClashingExternDeclarations { // Given a transparent newtype, reach through and grab the inner // type unless the newtype makes the type non-null. - let non_transparent_ty = |ty: Ty<'tcx>| -> Ty<'tcx> { - let mut ty = ty; + let non_transparent_ty = |mut ty: Ty<'tcx>| -> Ty<'tcx> { loop { if let ty::Adt(def, substs) = *ty.kind() { let is_transparent = def.repr().transparent(); @@ -2792,14 +2791,14 @@ impl ClashingExternDeclarations { ty, is_transparent, is_non_null ); if is_transparent && !is_non_null { - debug_assert!(def.variants().len() == 1); + debug_assert_eq!(def.variants().len(), 1); let v = &def.variant(VariantIdx::new(0)); - ty = transparent_newtype_field(tcx, v) - .expect( - "single-variant transparent structure with zero-sized field", - ) - .ty(tcx, substs); - continue; + // continue with `ty`'s non-ZST field, + // otherwise `ty` is a ZST and we can return + if let Some(field) = transparent_newtype_field(tcx, v) { + ty = field.ty(tcx, substs); + continue; + } } } debug!("non_transparent_ty -> {:?}", ty); @@ -2813,10 +2812,8 @@ impl ClashingExternDeclarations { if !seen_types.insert((a, b)) { // We've encountered a cycle. There's no point going any further -- the types are // structurally the same. - return true; - } - let tcx = cx.tcx; - if a == b { + true + } else if a == b { // All nominally-same types are structurally same, too. true } else { diff --git a/tests/ui/lint/clashing-extern-fn.rs b/tests/ui/lint/clashing-extern-fn.rs index 809e0602671fe..09fda33dbec5c 100644 --- a/tests/ui/lint/clashing-extern-fn.rs +++ b/tests/ui/lint/clashing-extern-fn.rs @@ -122,8 +122,8 @@ mod banana { weight: u32, length: u16, } // note: distinct type - // This should not trigger the lint because two::Banana is structurally equivalent to - // one::Banana. + // This should not trigger the lint because two::Banana is structurally equivalent to + // one::Banana. extern "C" { fn weigh_banana(count: *const Banana) -> u64; } @@ -223,6 +223,27 @@ mod transparent { } } +#[allow(improper_ctypes)] +mod zst { + mod transparent { + #[repr(transparent)] + struct TransparentZst(()); + extern "C" { + fn zst() -> (); + fn transparent_zst() -> TransparentZst; + } + } + + mod not_transparent { + struct NotTransparentZst(()); + extern "C" { + // These shouldn't warn since all return types are zero sized + fn zst() -> NotTransparentZst; + fn transparent_zst() -> NotTransparentZst; + } + } +} + mod missing_return_type { mod a { extern "C" { @@ -397,10 +418,14 @@ mod hidden_niche { use std::num::NonZeroUsize; #[repr(transparent)] - struct Transparent { x: NonZeroUsize } + struct Transparent { + x: NonZeroUsize, + } #[repr(transparent)] - struct TransparentNoNiche { y: UnsafeCell } + struct TransparentNoNiche { + y: UnsafeCell, + } extern "C" { fn hidden_niche_transparent() -> Option; diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr index 217eed6c92cea..5d457ba0ec763 100644 --- a/tests/ui/lint/clashing-extern-fn.stderr +++ b/tests/ui/lint/clashing-extern-fn.stderr @@ -130,7 +130,7 @@ LL | fn transparent_incorrect() -> isize; found `unsafe extern "C" fn() -> isize` warning: `missing_return_type` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:238:13 + --> $DIR/clashing-extern-fn.rs:259:13 | LL | fn missing_return_type() -> usize; | ---------------------------------- `missing_return_type` previously declared here @@ -142,7 +142,7 @@ LL | fn missing_return_type(); found `unsafe extern "C" fn()` warning: `non_zero_usize` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:256:13 + --> $DIR/clashing-extern-fn.rs:277:13 | LL | fn non_zero_usize() -> core::num::NonZeroUsize; | ----------------------------------------------- `non_zero_usize` previously declared here @@ -154,7 +154,7 @@ LL | fn non_zero_usize() -> usize; found `unsafe extern "C" fn() -> usize` warning: `non_null_ptr` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:258:13 + --> $DIR/clashing-extern-fn.rs:279:13 | LL | fn non_null_ptr() -> core::ptr::NonNull; | ----------------------------------------------- `non_null_ptr` previously declared here @@ -166,7 +166,7 @@ LL | fn non_null_ptr() -> *const usize; found `unsafe extern "C" fn() -> *const usize` warning: `option_non_zero_usize_incorrect` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:356:13 + --> $DIR/clashing-extern-fn.rs:377:13 | LL | fn option_non_zero_usize_incorrect() -> usize; | ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here @@ -178,7 +178,7 @@ LL | fn option_non_zero_usize_incorrect() -> isize; found `unsafe extern "C" fn() -> isize` warning: `option_non_null_ptr_incorrect` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:358:13 + --> $DIR/clashing-extern-fn.rs:379:13 | LL | fn option_non_null_ptr_incorrect() -> *const usize; | --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here @@ -190,7 +190,7 @@ LL | fn option_non_null_ptr_incorrect() -> *const isize; found `unsafe extern "C" fn() -> *const isize` warning: `hidden_niche_transparent_no_niche` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:408:13 + --> $DIR/clashing-extern-fn.rs:433:13 | LL | fn hidden_niche_transparent_no_niche() -> usize; | ------------------------------------------------ `hidden_niche_transparent_no_niche` previously declared here @@ -202,7 +202,7 @@ LL | fn hidden_niche_transparent_no_niche() -> Option Option` warning: `hidden_niche_unsafe_cell` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:412:13 + --> $DIR/clashing-extern-fn.rs:437:13 | LL | fn hidden_niche_unsafe_cell() -> usize; | --------------------------------------- `hidden_niche_unsafe_cell` previously declared here @@ -214,7 +214,7 @@ LL | fn hidden_niche_unsafe_cell() -> Option Option>` warning: `extern` block uses type `Option`, which is not FFI-safe - --> $DIR/clashing-extern-fn.rs:408:55 + --> $DIR/clashing-extern-fn.rs:433:55 | LL | fn hidden_niche_transparent_no_niche() -> Option; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -224,7 +224,7 @@ LL | fn hidden_niche_transparent_no_niche() -> Option>`, which is not FFI-safe - --> $DIR/clashing-extern-fn.rs:412:46 + --> $DIR/clashing-extern-fn.rs:437:46 | LL | fn hidden_niche_unsafe_cell() -> Option>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe