mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 02:03:53 +00:00
Rollup merge of #126152 - RalfJung:size_of_val_raw, r=saethlin
size_of_val_raw: for length 0 this is safe to call For motivation, see https://github.com/rust-lang/unsafe-code-guidelines/issues/465, specifically around [here](https://github.com/rust-lang/unsafe-code-guidelines/issues/465#issuecomment-2136401114). Cc `@rust-lang/opsem`
This commit is contained in:
commit
130d15e23e
@ -183,6 +183,8 @@ impl Layout {
|
||||
/// - a [slice], then the length of the slice tail must be an initialized
|
||||
/// integer, and the size of the *entire value*
|
||||
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
|
||||
/// For the special case where the dynamic tail length is 0, this function
|
||||
/// is safe to call.
|
||||
/// - a [trait object], then the vtable part of the pointer must point
|
||||
/// to a valid vtable for the type `T` acquired by an unsizing coercion,
|
||||
/// and the size of the *entire value*
|
||||
|
@ -359,6 +359,12 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
|
||||
/// - a [slice], then the length of the slice tail must be an initialized
|
||||
/// integer, and the size of the *entire value*
|
||||
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
|
||||
/// For the special case where the dynamic tail length is 0, this function
|
||||
/// is safe to call.
|
||||
// NOTE: the reason this is safe is that if an overflow were to occur already with size 0,
|
||||
// then we would stop compilation as even the "statically known" part of the type would
|
||||
// already be too big (or the call may be in dead code and optimized away, but then it
|
||||
// doesn't matter).
|
||||
/// - a [trait object], then the vtable part of the pointer must point
|
||||
/// to a valid vtable acquired by an unsizing coercion, and the size
|
||||
/// of the *entire value* (dynamic tail length + statically sized prefix)
|
||||
@ -506,6 +512,8 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
|
||||
/// - a [slice], then the length of the slice tail must be an initialized
|
||||
/// integer, and the size of the *entire value*
|
||||
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
|
||||
/// For the special case where the dynamic tail length is 0, this function
|
||||
/// is safe to call.
|
||||
/// - a [trait object], then the vtable part of the pointer must point
|
||||
/// to a valid vtable acquired by an unsizing coercion, and the size
|
||||
/// of the *entire value* (dynamic tail length + statically sized prefix)
|
||||
|
18
tests/ui/layout/size-of-val-raw-too-big.rs
Normal file
18
tests/ui/layout/size-of-val-raw-too-big.rs
Normal file
@ -0,0 +1,18 @@
|
||||
//@ build-fail
|
||||
//@ compile-flags: --crate-type lib
|
||||
//@ only-32bit Layout computation rejects this layout for different reasons on 64-bit.
|
||||
//@ error-pattern: too big for the current architecture
|
||||
#![feature(core_intrinsics)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
// isize::MAX is fine, but with the padding for the unsized tail it is too big.
|
||||
#[repr(C)]
|
||||
pub struct Example([u8; isize::MAX as usize], [u16]);
|
||||
|
||||
// We guarantee that with length 0, `size_of_val_raw` (which calls the `size_of_val` intrinsic)
|
||||
// is safe to call. The compiler aborts compilation if a length of 0 would overflow.
|
||||
// So let's construct a case where length 0 just barely overflows, and ensure that
|
||||
// does abort compilation.
|
||||
pub fn check(x: *const Example) -> usize {
|
||||
unsafe { std::intrinsics::size_of_val(x) }
|
||||
}
|
4
tests/ui/layout/size-of-val-raw-too-big.stderr
Normal file
4
tests/ui/layout/size-of-val-raw-too-big.stderr
Normal file
@ -0,0 +1,4 @@
|
||||
error: values of the type `Example` are too big for the current architecture
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
Loading…
Reference in New Issue
Block a user