Original conversation can be found in this IRLO thread, including a request from @RalfJung to file a bug report.
PR 68491 was accepted to hide niches of types that are in an UnsafeCell. However, experiments show that niches are still exposed within Cell, Mutex, and others.
Consider this code, adapted from a playground by @SkiFire13. It currently runs on the playground without panicking and optimizes down to a ret in the Godbolt explorer.
assert_eq!( 8, mem::size_of::< UnsafeCell<&()> >()); // 8
assert_eq!(16, mem::size_of::<Option<UnsafeCell<&()>>>()); // 16 (✗ niche opt)
assert_eq!( 8, mem::size_of::< Cell<&()> >()); // 8
assert_eq!( 8, mem::size_of::<Option< Cell<&()>>>()); // 8 (✓ niche opt)
assert_eq!(16, mem::size_of::< RefCell<&()> >()); // 16
assert_eq!(24, mem::size_of::<Option< RefCell<&()>>>()); // 24 (✗ niche opt)
assert_eq!(24, mem::size_of::< RwLock<&()> >()); // 24
assert_eq!(24, mem::size_of::<Option< RwLock<&()>>>()); // 24 (✓ niche opt)
assert_eq!(24, mem::size_of::< Mutex<&()> >()); // 24
assert_eq!(24, mem::size_of::<Option< Mutex<&()>>>()); // 24 (✓ niche opt)
I would have expected Option<Cell<&()>> to not exhibit the niche-exploiting size optimization. The RwLock and Mutex cases may or may not be problematic, depending on their platform-specific implementations. But Cell in particular is a #[repr(transparent)] wrapper around UnsafeCell.
Here is another playground by @SkiFire13 from which they observed:
Even more interesting, looks like the current behaviour of a type that contains an UnsafeCell is to allow niche optimizations only if it doesn't contains something else before the UnsafeCell, and that something is not a ZST.
This indicates that the behavior is not Cell-specific. And although there has been some discussion about revealing the niches for Cell in particular, the discussion in the PR and in this hackmd seem to indicate that the niches being exploited is not intentional, even for Cell. The behavior can be observed back until Rust 1.43 when the PR landed.
Meta
Current playground (all versions) and Godbolt on all versions I tried from 1.43 forward.
Original conversation can be found in this IRLO thread, including a request from @RalfJung to file a bug report.
PR 68491 was accepted to hide niches of types that are in an
UnsafeCell. However, experiments show that niches are still exposed withinCell,Mutex, and others.Consider this code, adapted from a playground by @SkiFire13. It currently runs on the playground without panicking and optimizes down to a
retin the Godbolt explorer.I would have expected
Option<Cell<&()>>to not exhibit the niche-exploiting size optimization. TheRwLockandMutexcases may or may not be problematic, depending on their platform-specific implementations. ButCellin particular is a#[repr(transparent)]wrapper aroundUnsafeCell.Here is another playground by @SkiFire13 from which they observed:
This indicates that the behavior is not
Cell-specific. And although there has been some discussion about revealing the niches forCellin particular, the discussion in the PR and in this hackmd seem to indicate that the niches being exploited is not intentional, even forCell. The behavior can be observed back until Rust 1.43 when the PR landed.Meta
Current playground (all versions) and Godbolt on all versions I tried from 1.43 forward.