Skip to content

Commit 14be58a

Browse files
committed
compiler: allow transmute of ZST arrays with generics
Extend the `SizeSkeleton` evaluator to shortcut zero-sized arrays, thus considering `[T; 0]` to have a compile-time fixed-size of 0. The existing evaluator already deals with generic arrays under the feature-guard `transmute_const_generics`. However, it merely allows comparing fixed-size types with fixed-size types, and generic types with generic types. For generic types, it merely compares whether their arguments match (ordering them first). Even if their exact sizes are not known at compile time, it can ensure that they will eventually be the same. This patch extends this by shortcutting the size-evaluation of zero sized arrays and thus allowing size comparisons of `()` with `[T; 0]`, where one contains generics and the other does not. This code is guarded by `transmute_const_generics` (#109929), even though it is unclear whether it should be. However, this assumes that a separate stabilization PR is required to move this out of the feature guard. Initially reported in #98104.
1 parent ced592a commit 14be58a

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

compiler/rustc_middle/src/ty/layout.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -345,11 +345,16 @@ impl<'tcx> SizeSkeleton<'tcx> {
345345
ty::Array(inner, len)
346346
if len.ty() == tcx.types.usize && tcx.features().transmute_generic_consts =>
347347
{
348+
let len_eval = len.try_eval_target_usize(tcx, param_env);
349+
if len_eval == Some(0) {
350+
return Ok(SizeSkeleton::Known(Size::from_bytes(0)));
351+
}
352+
348353
match SizeSkeleton::compute(inner, tcx, param_env)? {
349354
// This may succeed because the multiplication of two types may overflow
350355
// but a single size of a nested array will not.
351356
SizeSkeleton::Known(s) => {
352-
if let Some(c) = len.try_eval_target_usize(tcx, param_env) {
357+
if let Some(c) = len_eval {
353358
let size = s
354359
.bytes()
355360
.checked_mul(c)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// run-pass
2+
// Transmuting to/from ZSTs that contain generics.
3+
4+
#![feature(transmute_generic_consts)]
5+
6+
unsafe fn cast_zst<T>(from: ()) -> [T; 0] {
7+
::std::mem::transmute::<(), [T; 0]>(from)
8+
}
9+
10+
pub fn main() {
11+
unsafe {
12+
let _: [u32; 0] = cast_zst(());
13+
};
14+
}

0 commit comments

Comments
 (0)