From daaf367e542c7040a610d1e0c7f5ca8cb3f8d04f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 7 Jun 2026 23:33:00 +0200 Subject: [PATCH] explain that the size_of constant also serves to avoid optimizing away 'unused' size_of calls --- library/core/src/mem/mod.rs | 7 +++++++ tests/ui/layout/too-big-no-dce.rs | 20 ++++++++++++++++++++ tests/ui/layout/too-big-no-dce.stderr | 8 ++++++++ 3 files changed, 35 insertions(+) create mode 100644 tests/ui/layout/too-big-no-dce.rs create mode 100644 tests/ui/layout/too-big-no-dce.stderr diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 62c612e7ba2a6..5caa545628c1e 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -371,6 +371,13 @@ pub fn forget_unsized(t: T) { #[rustc_const_stable(feature = "const_mem_size_of", since = "1.24.0")] #[rustc_diagnostic_item = "mem_size_of"] pub const fn size_of() -> usize { + // By making this a constant, we also guarantee that the constant can be successfully evaluated + // in any program execution that actually executes `size_of`. Which is relevant because the + // constant can fail to evaluate if the type is too big. Someone might do something cursed where + // soundness relies on a certain type not being too big, and they check that by just invoking + // size_of on the type to ensure it exists, so if we fully DCE'd size_of calls that would be + // considered unsound... but by making this a constant, it participates in the usual "required + // consts" system, and we are safe. ::SIZE } diff --git a/tests/ui/layout/too-big-no-dce.rs b/tests/ui/layout/too-big-no-dce.rs new file mode 100644 index 0000000000000..7ea714f5cd3ee --- /dev/null +++ b/tests/ui/layout/too-big-no-dce.rs @@ -0,0 +1,20 @@ +//! Ensure that we do not dead-code-eliminate `size_of` calls. That might hide "type too big" +//! errors! +//@ build-fail (test needs codegen) +//@ compile-flags: -O +//@ normalize-stderr: "\d{5}\d*" -> "NUMBER" + +//~? ERROR too big for the target + +#![crate_type = "lib"] + +const PTR_BITS_MINUS_1: usize = std::mem::size_of::<*const ()>() * 8 - 1; + +#[unsafe(no_mangle)] // ensure this gets monomorphized +pub fn f() { + assert_valid_type::<[u32; 1 << PTR_BITS_MINUS_1]>(); +} + +pub fn assert_valid_type() { + std::mem::size_of::(); +} diff --git a/tests/ui/layout/too-big-no-dce.stderr b/tests/ui/layout/too-big-no-dce.stderr new file mode 100644 index 0000000000000..a4b01dda0a444 --- /dev/null +++ b/tests/ui/layout/too-big-no-dce.stderr @@ -0,0 +1,8 @@ +error[E0080]: values of the type `[u32; NUMBER]` are too big for the target architecture + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | + = note: evaluation of `<[u32; NUMBER] as std::mem::SizedTypeProperties>::SIZE` failed here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`.