Repository: rust-lang/rust
Pull request #140215: transmutability: Support char, NonZeroXxx
Author: login: joshlf
Labels: name: A-testsuite
description: Area: The testsuite used to check the correctness of rustc
name: T-compiler
description: Relevant to the compiler team, which will review and decide on the PR/issue.
name: T-bootstrap
description: Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap)
name: S-waiting-on-bors
description: Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
name: A-compiletest
description: Area: The compiletest test runner
Created: 2025-04-23T18:41:13Z | Merged: 2025-04-26T19:04:02Z

Note that `NonZero` support is not wired up, as the author encountered
bugs while attempting this. A future commit will wire up `NonZero`
support.

r? @jswrenn


Diff:
diff --git a/compiler/rustc_transmute/src/layout/mod.rs b/compiler/rustc_transmute/src/layout/mod.rs
index d555ea702a9fe..4d5f630ae229e 100644
--- a/compiler/rustc_transmute/src/layout/mod.rs
+++ b/compiler/rustc_transmute/src/layout/mod.rs
@@ -65,7 +65,12 @@ impl fmt::Debug for Byte {
     }
 }
 
-#[cfg(test)]
+impl From<RangeInclusive<u8>> for Byte {
+    fn from(src: RangeInclusive<u8>) -> Self {
+        Self::new(src)
+    }
+}
+
 impl From<u8> for Byte {
     fn from(src: u8) -> Self {
         Self::from_val(src)
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 6a09be18ef944..7cf712ce9e977 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -1,4 +1,4 @@
-use std::ops::ControlFlow;
+use std::ops::{ControlFlow, RangeInclusive};
 
 use super::{Byte, Def, Ref};
 
@@ -32,6 +32,22 @@ where
     Byte(Byte),
 }
 
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub(crate) enum Endian {
+    Little,
+    Big,
+}
+
+#[cfg(feature = "rustc")]
+impl From<rustc_abi::Endian> for Endian {
+    fn from(order: rustc_abi::Endian) -> Endian {
+        match order {
+            rustc_abi::Endian::Little => Endian::Little,
+            rustc_abi::Endian::Big => Endian::Big,
+        }
+    }
+}
+
 impl<D, R> Tree<D, R>
 where
     D: Def,
@@ -59,22 +75,60 @@ where
 
     /// A `Tree` representing the layout of `bool`.
     pub(crate) fn bool() -> Self {
-        Self::Byte(Byte::new(0x00..=0x01))
+        Self::byte(0x00..=0x01)
     }
 
     /// A `Tree` whose layout matches that of a `u8`.
     pub(crate) fn u8() -> Self {
-        Self::Byte(Byte::new(0x00..=0xFF))
+        Self::byte(0x00..=0xFF)
+    }
+
+    /// A `Tree` whose layout matches that of a `char`.
+    pub(crate) fn char(order: Endian) -> Self {
+        // `char`s can be in the following ranges:
+        // - [0, 0xD7FF]
+        // - [0xE000, 10FFFF]
+        //
+        // All other `char` values are illegal. We can thus represent a `char`
+        // as a union of three possible layouts:
+        // - 00 00 [00, D7] XX
+        // - 00 00 [E0, FF] XX
+        // - 00 [01, 10] XX XX
+
+        const _0: RangeInclusive<u8> = 0..=0;
+        const BYTE: RangeInclusive<u8> = 0x00..=0xFF;
+        let x = Self::from_big_endian(order, [_0, _0, 0x00..=0xD7, BYTE]);
+        let y = Self::from_big_endian(order, [_0, _0, 0xE0..=0xFF, BYTE]);
+        let z = Self::from_big_endian(order, [_0, 0x01..=0x10, BYTE, BYTE]);
+        Self::alt([x, y, z])
     }
 
-    /// A `Tree` whose layout accepts exactly the given bit pattern.
-    pub(crate) fn from_bits(bits: u8) -> Self {
-        Self::Byte(Byte::from_val(bits))
+    /// A `Tree` whose layout matches `std::num::NonZeroXxx`.
+    #[allow(dead_code)]
+    pub(crate) fn nonzero(width_in_bytes: u64) -> Self {
+        const BYTE: RangeInclusive<u8> = 0x00..=0xFF;
+        const NONZERO: RangeInclusive<u8> = 0x01..=0xFF;
+
+        (0..width_in_bytes)
+            .map(|nz_idx| {
+                (0..width_in_bytes)
+                    .map(|pos| Self::byte(if pos == nz_idx { NONZERO } else { BYTE }))
+                    .fold(Self::unit(), Self::then)
+            })
+            .fold(Self::uninhabited(), Self::or)
+    }
+
+    pub(crate) fn bytes<const N: usize, B: Into<Byte>>(bytes: [B; N]) -> Self {
+        Self::seq(bytes.map(B::into).map(Self::Byte))
+    }
+
+    pub(crate) fn byte(byte: impl Into<Byte>) -> Self {
+        Self::Byte(byte.into())
     }
 
     /// A `Tree` whose layout is a number of the given width.
-    pub(crate) fn number(width_in_bytes: usize) -> Self {
-        Self::Seq(vec![Self::u8(); width_in_bytes])
+    pub(crate) fn number(width_in_bytes: u64) -> Self {
+        Self::Seq(vec![Self::u8(); width_in_bytes.try_into().unwrap()])
     }
 
     /// A `Tree` whose layout is entirely padding of the given width.
@@ -125,13 +179,35 @@ where
             Self::Byte(..) | Self::Ref(..) | Self::Def(..) => true,
         }
     }
-}
 
-impl<D, R> Tree<D, R>
-where
-    D: Def,
-    R: Ref,
-{
+    /// Produces a `Tree` which represents a sequence of bytes stored in
+    /// `order`.
+    ///
+    /// `bytes` is taken to be in big-endian byte order, and its order will be
+    /// swapped if `order == Endian::Little`.
+    pub(crate) fn from_big_endian<const N: usize, B: Into<Byte>>(
+        order: Endian,
+        mut bytes: [B; N],
+    ) -> Self {
+        if order == Endian::Little {
+            (&mut bytes[..]).reverse();
+        }
+
+        Self::bytes(bytes)
+    }
+
+    /// Produces a `Tree` where each of the trees in `trees` are sequenced one
+    /// after another.
+    pub(crate) fn seq<const N: usize>(trees: [Tree<D, R>; N]) -> Self {
+        trees.into_iter().fold(Tree::unit(), Self::then)
+    }
+
+    /// Produces a `Tree` where each of the trees in `trees` are accepted as
+    /// alternative layouts.
+    pub(crate) fn alt<const N: usize>(trees: [Tree<D, R>; N]) -> Self {
+        trees.into_iter().fold(Tree::uninhabited(), Self::or)
+    }
+
     /// Produces a new `Tree` where `other` is sequenced after `self`.
     pub(crate) fn then(self, other: Self) -> Self {
         match (self, other) {
@@ -222,17 +298,17 @@ pub(crate) mod rustc {
 
                 ty::Float(nty) => {
                     let width = nty.bit_width() / 8;
-                    Ok(Self::number(width as _))
+                    Ok(Self::number(width.try_into().unwrap()))
                 }
 
                 ty::Int(nty) => {
                     let width = nty.normalize(pointer_size.bits() as _).bit_width().unwrap() / 8;
-                    Ok(Self::number(width as _))
+                    Ok(Self::number(width.try_into().unwrap()))
                 }
 
                 ty::Uint(nty) => {
                     let width = nty.normalize(pointer_size.bits() as _).bit_width().unwrap() / 8;
-                    Ok(Self::number(width as _))
+                    Ok(Self::number(width.try_into().unwrap()))
                 }
 
                 ty::Tuple(members) => Self::from_tuple((ty, layout), members, cx),
@@ -249,11 +325,33 @@ pub(crate) mod rustc {
                         .fold(Tree::unit(), |tree, elt| tree.then(elt)))
                 }
 
-                ty::Adt(adt_def, _args_ref) if !ty.is_box() => match adt_def.adt_kind() {
-                    AdtKind::Struct => Self::from_struct((ty, layout), *adt_def, cx),
-                    AdtKind::Enum => Self::from_enum((ty, layout), *adt_def, cx),
-                    AdtKind::Union => Self::from_union((ty, layout), *adt_def, cx),
-                },
+                ty::Adt(adt_def, _args_ref) if !ty.is_box() => {
+                    let (lo, hi) = cx.tcx().layout_scalar_valid_range(adt_def.did());
+
+                    use core::ops::Bound::*;
+                    let is_transparent = adt_def.repr().transparent();
+                    match (adt_def.adt_kind(), lo, hi) {
+                        (AdtKind::Struct, Unbounded, Unbounded) => {
+                            Self::from_struct((ty, layout), *adt_def, cx)
+                        }
+                        (AdtKind::Struct, Included(1), Included(_hi)) if is_transparent => {
+                            // FIXME(@joshlf): Support `NonZero` types:
+                            // - Check to make sure that the first field is
+                            //   numerical
+                            // - Check to make sure that the upper bound is the
+                            //   maximum value for the field's type
+                            // - Construct `Self::nonzero`
+                            Err(Err::NotYetSupported)
+                        }
+                        (AdtKind::Enum, Unbounded, Unbounded) => {
+                            Self::from_enum((ty, layout), *adt_def, cx)
+                        }
+                        (AdtKind::Union, Unbounded, Unbounded) => {
+                            Self::from_union((ty, layout), *adt_def, cx)
+                        }
+                        _ => Err(Err::NotYetSupported),
+                    }
+                }
 
                 ty::Ref(lifetime, ty, mutability) => {
                     let layout = layout_of(cx, *ty)?;
@@ -268,6 +366,8 @@ pub(crate) mod rustc {
                     }))
                 }
 
+                ty::Char => Ok(Self::char(cx.tcx().data_layout.endian.into())),
+
                 _ => Err(Err::NotYetSupported),
             }
         }
@@ -450,7 +550,7 @@ pub(crate) mod rustc {
                     &bytes[bytes.len() - size.bytes_usize()..]
                 }
             };
-            Self::Seq(bytes.iter().map(|&b| Self::from_bits(b)).collect())
+            Self::Seq(bytes.iter().map(|&b| Self::byte(b)).collect())
         }
 
         /// Constructs a `Tree` from a union.
diff --git a/compiler/rustc_transmute/src/layout/tree/tests.rs b/compiler/rustc_transmute/src/layout/tree/tests.rs
index 44f50a25c939a..8c3dbbe37ab21 100644
--- a/compiler/rustc_transmute/src/layout/tree/tests.rs
+++ b/compiler/rustc_transmute/src/layout/tree/tests.rs
@@ -20,23 +20,18 @@ mod prune {
 
         #[test]
         fn seq_1() {
-            let layout: Tree<Def, !> =
-                Tree::def(Def::NoSafetyInvariants).then(Tree::from_bits(0x00));
-            assert_eq!(
-                layout.prune(&|d| matches!(d, Def::HasSafetyInvariants)),
-                Tree::from_bits(0x00)
-            );
+            let layout: Tree<Def, !> = Tree::def(Def::NoSafetyInvariants).then(Tree::byte(0x00));
+            assert_eq!(layout.prune(&|d| matches!(d, Def::HasSafetyInvariants)), Tree::byte(0x00));
         }
 
         #[test]
         fn seq_2() {
-            let layout: Tree<Def, !> = Tree::from_bits(0x00)
-                .then(Tree::def(Def::NoSafetyInvariants))
-                .then(Tree::from_bits(0x01));
+            let layout: Tree<Def, !> =
+                Tree::byte(0x00).then(Tree::def(Def::NoSafetyInvariants)).then(Tree::byte(0x01));
 
             assert_eq!(
                 layout.prune(&|d| matches!(d, Def::HasSafetyInvariants)),
-                Tree::from_bits(0x00).then(Tree::from_bits(0x01))
+                Tree::byte(0x00).then(Tree::byte(0x01))
             );
         }
     }
@@ -66,7 +61,7 @@ mod prune {
         #[test]
         fn invisible_def_in_seq_len_3() {
             let layout: Tree<Def, !> = Tree::def(Def::NoSafetyInvariants)
-                .then(Tree::from_bits(0x00))
+                .then(Tree::byte(0x00))
                 .then(Tree::def(Def::HasSafetyInvariants));
             assert_eq!(
                 layout.prune(&|d| matches!(d, Def::HasSafetyInvariants)),
@@ -94,12 +89,9 @@ mod prune {
         #[test]
         fn visible_def_in_seq_len_3() {
             let layout: Tree<Def, !> = Tree::def(Def::NoSafetyInvariants)
-                .then(Tree::from_bits(0x00))
+                .then(Tree::byte(0x00))
                 .then(Tree::def(Def::NoSafetyInvariants));
-            assert_eq!(
-                layout.prune(&|d| matches!(d, Def::HasSafetyInvariants)),
-                Tree::from_bits(0x00)
-            );
+            assert_eq!(layout.prune(&|d| matches!(d, Def::HasSafetyInvariants)), Tree::byte(0x00));
         }
     }
 }
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
index 24e2a1acadd68..992fcb7cc4c81 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
@@ -177,9 +177,9 @@ mod bool {
 
     #[test]
     fn should_permit_validity_expansion_and_reject_contraction() {
-        let b0 = layout::Tree::<Def, !>::from_bits(0);
-        let b1 = layout::Tree::<Def, !>::from_bits(1);
-        let b2 = layout::Tree::<Def, !>::from_bits(2);
+        let b0 = layout::Tree::<Def, !>::byte(0);
+        let b1 = layout::Tree::<Def, !>::byte(1);
+        let b2 = layout::Tree::<Def, !>::byte(2);
 
         let alts = [b0, b1, b2];
 
@@ -279,8 +279,8 @@ mod alt {
     fn should_permit_identity_transmutation() {
         type Tree = layout::Tree<Def, !>;
 
-        let x = Tree::Seq(vec![Tree::from_bits(0), Tree::from_bits(0)]);
-        let y = Tree::Seq(vec![Tree::bool(), Tree::from_bits(1)]);
+        let x = Tree::Seq(vec![Tree::byte(0), Tree::byte(0)]);
+        let y = Tree::Seq(vec![Tree::bool(), Tree::byte(1)]);
         let layout = Tree::Alt(vec![x, y]);
 
         let answer = crate::maybe_transmutable::MaybeTransmutableQuery::new(
@@ -323,6 +323,76 @@ mod union {
     }
 }
 
+mod char {
+    use super::*;
+    use crate::layout::tree::Endian;
+
+    #[test]
+    fn should_permit_valid_transmutation() {
+        for order in [Endian::Big, Endian::Little] {
+            use Answer::*;
+            let char_layout = layout::Tree::<Def, !>::char(order);
+
+            // `char`s can be in the following ranges:
+            // - [0, 0xD7FF]
+            // - [0xE000, 10FFFF]
+            //
+            // This loop synthesizes a singleton-validity type for the extremes
+            // of each range, and for one past the end of the extremes of each
+            // range.
+            let no = No(Reason::DstIsBitIncompatible);
+            for (src, answer) in [
+                (0u32, Yes),
+                (0xD7FF, Yes),
+                (0xD800, no.clone()),
+                (0xDFFF, no.clone()),
+                (0xE000, Yes),
+                (0x10FFFF, Yes),
+                (0x110000, no.clone()),
+                (0xFFFF0000, no.clone()),
+                (0xFFFFFFFF, no),
+            ] {
+                let src_layout =
+                    layout::tree::Tree::<Def, !>::from_big_endian(order, src.to_be_bytes());
+
+                let a = is_transmutable(&src_layout, &char_layout, Assume::default());
+                assert_eq!(a, answer, "endian:{order:?},\nsrc:{src:x}");
+            }
+        }
+    }
+}
+
+mod nonzero {
+    use super::*;
+    use crate::{Answer, Reason};
+
+    const NONZERO_BYTE_WIDTHS: [u64; 5] = [1, 2, 4, 8, 16];
+
+    #[test]
+    fn should_permit_identity_transmutation() {
+        for width in NONZERO_BYTE_WIDTHS {
+            let layout = layout::Tree::<Def, !>::nonzero(width);
+            assert_eq!(is_transmutable(&layout, &layout, Assume::default()), Answer::Yes);
+        }
+    }
+
+    #[test]
+    fn should_permit_valid_transmutation() {
+        for width in NONZERO_BYTE_WIDTHS {
+            use Answer::*;
+
+            let num = layout::Tree::<Def, !>::number(width);
+            let nz = layout::Tree::<Def, !>::nonzero(width);
+
+            let a = is_transmutable(&num, &nz, Assume::default());
+            assert_eq!(a, No(Reason::DstIsBitIncompatible), "width:{width}");
+
+            let a = is_transmutable(&nz, &num, Assume::default());
+            assert_eq!(a, Yes, "width:{width}");
+        }
+    }
+}
+
 mod r#ref {
     use super::*;
 
@@ -330,7 +400,7 @@ mod r#ref {
     fn should_permit_identity_transmutation() {
         type Tree = crate::layout::Tree<Def, [(); 1]>;
 
-        let layout = Tree::Seq(vec![Tree::from_bits(0), Tree::Ref([()])]);
+        let layout = Tree::Seq(vec![Tree::byte(0x00), Tree::Ref([()])]);
 
         let answer = crate::maybe_transmutable::MaybeTransmutableQuery::new(
             layout.clone(),
diff --git a/tests/ui/transmutability/char.rs b/tests/ui/transmutability/char.rs
new file mode 100644
index 0000000000000..55a6153732955
--- /dev/null
+++ b/tests/ui/transmutability/char.rs
@@ -0,0 +1,41 @@
+#![feature(never_type)]
+#![feature(transmutability)]
+
+use std::mem::{Assume, TransmuteFrom};
+
+pub fn is_transmutable<Src, Dst>()
+where
+    Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
+{
+}
+
+fn main() {
+    is_transmutable::<char, u32>();
+
+    // `char`s can be in the following ranges:
+    // - [0, 0xD7FF]
+    // - [0xE000, 10FFFF]
+    //
+    // `Char` has variants whose tags are in the top and bottom of each range.
+    // It also has generic variants which are out of bounds of these ranges, but
+    // are generic on types which may be set to `!` to "disable" them in the
+    // transmutability analysis.
+    #[repr(u32)]
+    enum Char<B, C, D> {
+        A = 0,
+        B = 0xD7FF,
+        OverB(B) = 0xD800,
+        UnderC(C) = 0xDFFF,
+        C = 0xE000,
+        D = 0x10FFFF,
+        OverD(D) = 0x110000,
+    }
+
+    is_transmutable::<Char<!, !, !>, char>();
+    is_transmutable::<Char<(), !, !>, char>();
+    //~^ ERROR cannot be safely transmuted into `char`
+    is_transmutable::<Char<!, (), !>, char>();
+    //~^ ERROR cannot be safely transmuted into `char`
+    is_transmutable::<Char<!, !, ()>, char>();
+    //~^ ERROR cannot be safely transmuted into `char`
+}
diff --git a/tests/ui/transmutability/char.stderr b/tests/ui/transmutability/char.stderr
new file mode 100644
index 0000000000000..98e7ae9c0d49c
--- /dev/null
+++ b/tests/ui/transmutability/char.stderr
@@ -0,0 +1,48 @@
+error[E0277]: `main::Char<(), !, !>` cannot be safely transmuted into `char`
+  --> $DIR/char.rs:35:39
+   |
+LL |     is_transmutable::<Char<(), !, !>, char>();
+   |                                       ^^^^ at least one value of `main::Char<(), !, !>` isn't a bit-valid value of `char`
+   |
+note: required by a bound in `is_transmutable`
+  --> $DIR/char.rs:8:10
+   |
+LL | pub fn is_transmutable<Src, Dst>()
+   |        --------------- required by a bound in this function
+LL | where
+LL |     Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `main::Char<!, (), !>` cannot be safely transmuted into `char`
+  --> $DIR/char.rs:37:39
+   |
+LL |     is_transmutable::<Char<!, (), !>, char>();
+   |                                       ^^^^ at least one value of `main::Char<!, (), !>` isn't a bit-valid value of `char`
+   |
+note: required by a bound in `is_transmutable`
+  --> $DIR/char.rs:8:10
+   |
+LL | pub fn is_transmutable<Src, Dst>()
+   |        --------------- required by a bound in this function
+LL | where
+LL |     Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `main::Char<!, !, ()>` cannot be safely transmuted into `char`
+  --> $DIR/char.rs:39:39
+   |
+LL |     is_transmutable::<Char<!, !, ()>, char>();
+   |                                       ^^^^ at least one value of `main::Char<!, !, ()>` isn't a bit-valid value of `char`
+   |
+note: required by a bound in `is_transmutable`
+  --> $DIR/char.rs:8:10
+   |
+LL | pub fn is_transmutable<Src, Dst>()
+   |        --------------- required by a bound in this function
+LL | where
+LL |     Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.


Reviews:
user: login: joshlf
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:42:44Z
user: login: joshlf
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T19:59:27Z
user: login: tmiasko
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T21:01:13Z
user: login: joshlf
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T16:45:17Z
user: login: jswrenn
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-25T14:56:37Z
user: login: jswrenn
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-25T15:55:08Z
user: login: joshlf
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T16:27:15Z
user: login: jswrenn
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-25T16:32:30Z
user: login: joshlf
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T19:55:41Z

Review comments:
diff_hunk: @@ -268,6 +366,10 @@ pub(crate) mod rustc {
                     }))
                 }
 
+                ty::Char => Ok(Self::char(cx.tcx().data_layout.endian.into())),
+
+                ty::Alias(_kind, ty) => Self::from_ty(ty.to_ty(cx.tcx()), cx),
path: compiler/rustc_transmute/src/layout/tree.rs
user: login: joshlf
body: (Copying [this comment](https://github.com/rust-lang/rust/commit/218364989b5940ecb71ec869a18124afed43b1ad#r155776593) from @jswrenn):

> Can you write a test for a type alias of a type alias?
created_at: 2025-04-23T18:42:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -268,6 +366,10 @@ pub(crate) mod rustc {
                     }))
                 }
 
+                ty::Char => Ok(Self::char(cx.tcx().data_layout.endian.into())),
+
+                ty::Alias(_kind, ty) => Self::from_ty(ty.to_ty(cx.tcx()), cx),
path: compiler/rustc_transmute/src/layout/tree.rs
user: login: joshlf
body: Done
created_at: 2025-04-23T19:59:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -89,6 +101,36 @@ mod safety {
     }
 }
 
+mod size {
+    use super::*;
+
+    #[test]
+    fn size() {
+        let small = Tree::number(1.try_into().unwrap());
path: compiler/rustc_transmute/src/maybe_transmutable/tests.rs
user: login: tmiasko
body: `try_into().unwrap()` looks redundant here. Similarly inside other calls to `Tree::number` in tests.
created_at: 2025-04-23T21:01:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -89,6 +101,36 @@ mod safety {
     }
 }
 
+mod size {
+    use super::*;
+
+    #[test]
+    fn size() {
+        let small = Tree::number(1.try_into().unwrap());
path: compiler/rustc_transmute/src/maybe_transmutable/tests.rs
user: login: joshlf
body: Artifact of an old version of the code; fixed.
created_at: 2025-04-24T16:45:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -249,11 +325,51 @@ pub(crate) mod rustc {
                         .fold(Tree::unit(), |tree, elt| tree.then(elt)))
                 }
 
-                ty::Adt(adt_def, _args_ref) if !ty.is_box() => match adt_def.adt_kind() {
-                    AdtKind::Struct => Self::from_struct((ty, layout), *adt_def, cx),
-                    AdtKind::Enum => Self::from_enum((ty, layout), *adt_def, cx),
-                    AdtKind::Union => Self::from_union((ty, layout), *adt_def, cx),
-                },
+                ty::Adt(adt_def, _args_ref) if !ty.is_box() => {
+                    let (lo, hi) = cx.tcx().layout_scalar_valid_range(adt_def.did());
+
+                    use core::ops::Bound::*;
+                    let is_transparent = adt_def.repr().transparent();
+                    match (adt_def.adt_kind(), lo, hi) {
+                        (AdtKind::Struct, Unbounded, Unbounded) => {
+                            Self::from_struct((ty, layout), *adt_def, cx)
+                        }
+                        (AdtKind::Struct, Included(1), Included(_hi)) if is_transparent => {
+                            // FIXME: Uncomment the code below and get it
path: compiler/rustc_transmute/src/layout/tree.rs
user: login: jswrenn
body: Do you want to tackle this in this PR, or a follow up? 
created_at: 2025-04-25T14:56:37Z
author_association: MEMBER
diff_hunk: @@ -268,6 +384,10 @@ pub(crate) mod rustc {
                     }))
                 }
 
+                ty::Char => Ok(Self::char(cx.tcx().data_layout.endian.into())),
+
+                ty::Alias(_kind, ty) => Self::from_ty(ty.to_ty(cx.tcx()), cx),
path: compiler/rustc_transmute/src/layout/tree.rs
user: login: jswrenn
body: ```suggestion
                ty::Alias(_kind, ty) => Self::from_ty(/* normalize ty */),
```
@tmiasko / @compiler-errors, what's the current way to normalize a type when we *do* care about regions?
created_at: 2025-04-25T15:55:07Z
author_association: MEMBER
diff_hunk: @@ -249,11 +325,51 @@ pub(crate) mod rustc {
                         .fold(Tree::unit(), |tree, elt| tree.then(elt)))
                 }
 
-                ty::Adt(adt_def, _args_ref) if !ty.is_box() => match adt_def.adt_kind() {
-                    AdtKind::Struct => Self::from_struct((ty, layout), *adt_def, cx),
-                    AdtKind::Enum => Self::from_enum((ty, layout), *adt_def, cx),
-                    AdtKind::Union => Self::from_union((ty, layout), *adt_def, cx),
-                },
+                ty::Adt(adt_def, _args_ref) if !ty.is_box() => {
+                    let (lo, hi) = cx.tcx().layout_scalar_valid_range(adt_def.did());
+
+                    use core::ops::Bound::*;
+                    let is_transparent = adt_def.repr().transparent();
+                    match (adt_def.adt_kind(), lo, hi) {
+                        (AdtKind::Struct, Unbounded, Unbounded) => {
+                            Self::from_struct((ty, layout), *adt_def, cx)
+                        }
+                        (AdtKind::Struct, Included(1), Included(_hi)) if is_transparent => {
+                            // FIXME: Uncomment the code below and get it
path: compiler/rustc_transmute/src/layout/tree.rs
user: login: joshlf
body: In a follow-up. I've removed the commented-out code for now.
created_at: 2025-04-25T16:27:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -268,6 +384,10 @@ pub(crate) mod rustc {
                     }))
                 }
 
+                ty::Char => Ok(Self::char(cx.tcx().data_layout.endian.into())),
+
+                ty::Alias(_kind, ty) => Self::from_ty(ty.to_ty(cx.tcx()), cx),
path: compiler/rustc_transmute/src/layout/tree.rs
user: login: jswrenn
body: If we're punting on normalization, can you remove this branch so we don't regress projections to an infinite loop?
created_at: 2025-04-25T16:32:30Z
author_association: MEMBER
diff_hunk: @@ -268,6 +384,10 @@ pub(crate) mod rustc {
                     }))
                 }
 
+                ty::Char => Ok(Self::char(cx.tcx().data_layout.endian.into())),
+
+                ty::Alias(_kind, ty) => Self::from_ty(ty.to_ty(cx.tcx()), cx),
path: compiler/rustc_transmute/src/layout/tree.rs
user: login: joshlf
body: > If we're punting on normalization, can you remove this branch so we don't regress projections to an infinite loop?

Done.

> @tmiasko / @compiler-errors, what's the current way to normalize a type when we _do_ care about regions?

Maybe, for the time being (but in a separate PR), we could at least support `'static` types by normalizing without caring about regions and returning an error when the type is non-`'static`? That would at least cover the `NonZero` case.
created_at: 2025-04-25T19:55:41Z
author_association: CONTRIBUTOR

PR comments:
user: login: rust-log-analyzer
created_at: 2025-04-23T18:52:19Z
body: 
The job **`x86_64-gnu-llvm-19`** failed! Check out the build log: [(web)](https://github.com/rust-lang/rust/actions/runs/14625718797/job/41036662941) [(plain)](https://github.com/rust-lang/rust/commit/b4af1e4467bb3a8dcafbe99807db66d56b3ee77f/checks/41036662941/logs)

<details><summary><i>Click to see the possible cause of the failure (guessed by this bot)</i></summary>

```plain
#18 exporting to docker image format
#18 sending tarball 20.2s done
#18 DONE 27.1s
##[endgroup]
Setting extra environment values for docker:  --env ENABLE_GCC_CODEGEN=1 --env GCC_EXEC_PREFIX=/usr/lib/gcc/
[CI_JOB_NAME=x86_64-gnu-llvm-19]
[CI_JOB_NAME=x86_64-gnu-llvm-19]
debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured.
---
sccache: Listening on address 127.0.0.1:4226
##[group]Configure the build
configure: processing command line
configure: 
configure: build.configure-args := ['--build=x86_64-unknown-linux-gnu', '--llvm-root=/usr/lib/llvm-19', '--enable-llvm-link-shared', '--set', 'rust.randomize-layout=true', '--set', 'rust.thin-lto-import-instr-limit=10', '--set', 'build.print-step-timings', '--enable-verbose-tests', '--set', 'build.metrics', '--enable-verbose-configure', '--enable-sccache', '--disable-manage-submodules', '--enable-locked-deps', '--enable-cargo-native-static', '--set', 'rust.codegen-units-std=1', '--set', 'dist.compression-profile=balanced', '--dist-compression-formats=xz', '--set', 'rust.lld=false', '--disable-dist-src', '--release-channel=nightly', '--enable-debug-assertions', '--enable-overflow-checks', '--enable-llvm-assertions', '--set', 'rust.verify-llvm-ir', '--set', 'rust.codegen-backends=llvm,cranelift,gcc', '--set', 'llvm.static-libstdcpp', '--enable-new-symbol-mangling']
configure: build.build          := x86_64-unknown-linux-gnu
configure: target.x86_64-unknown-linux-gnu.llvm-config := /usr/lib/llvm-19/bin/llvm-config
configure: llvm.link-shared     := True
configure: rust.randomize-layout := True
configure: rust.thin-lto-import-instr-limit := 10
---
   Compiling rustc_query_impl v0.0.0 (/checkout/compiler/rustc_query_impl)
error[E0283]: type annotations needed
   --> compiler/rustc_transmute/src/layout/tree.rs:338:42
    |
338 |                     let is_transparent = Ty::is_transparent(TyAndLayout { ty, layout });
    |                                          ^^ cannot infer type for type parameter `C`
    |
    = note: cannot satisfy `_: HasTyCtxt<'_>`
    = help: the following types implement trait `HasTyCtxt<'tcx>`:
              LayoutCx<'tcx>
              TyCtxt<'tcx>
```

</details>

author_association: COLLABORATOR
user: login: rust-log-analyzer
created_at: 2025-04-23T19:14:47Z
body: 
The job **`mingw-check-tidy`** failed! Check out the build log: [(web)](https://github.com/rust-lang/rust/actions/runs/14626049448/job/41037736472) [(plain)](https://github.com/rust-lang/rust/commit/5924db898ed65bcf04e3d3f181ab5db493e1759d/checks/41037736472/logs)

<details><summary><i>Click to see the possible cause of the failure (guessed by this bot)</i></summary>

```plain
info: removing rustup binaries
info: rustup is uninstalled
##[group]Image checksum input
mingw-check-tidy
# We use the ghcr base image because ghcr doesn't have a rate limit
# and the mingw-check-tidy job doesn't cache docker images in CI.
FROM ghcr.io/rust-lang/ubuntu:22.04

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
  g++ \
  make \
---

COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/

# NOTE: intentionally uses python2 for x.py so we can test it still works.
# validate-toolstate only runs in our CI, so it's ok for it to only support python3.
ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test \
           --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile --allow-unsafe --generate-hashes reuse-requirements.in
---
#12 2.868 Building wheels for collected packages: reuse
#12 2.869   Building wheel for reuse (pyproject.toml): started
#12 3.083   Building wheel for reuse (pyproject.toml): finished with status 'done'
#12 3.085   Created wheel for reuse: filename=reuse-4.0.3-cp310-cp310-manylinux_2_35_x86_64.whl size=132719 sha256=5bb60f62728aaedff7162745ce743c7f2f55069b3e7f82e6a37d70df455797cc
#12 3.085   Stored in directory: /tmp/pip-ephem-wheel-cache-y7zic34o/wheels/3d/8d/0a/e0fc6aba4494b28a967ab5eaf951c121d9c677958714e34532
#12 3.087 Successfully built reuse
#12 3.088 Installing collected packages: boolean-py, binaryornot, tomlkit, reuse, python-debian, markupsafe, license-expression, jinja2, chardet, attrs
#12 3.496 Successfully installed attrs-23.2.0 binaryornot-0.4.4 boolean-py-4.0 chardet-5.2.0 jinja2-3.1.4 license-expression-30.3.0 markupsafe-2.1.5 python-debian-0.1.49 reuse-4.0.3 tomlkit-0.13.0
#12 3.496 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#12 4.043 Collecting virtualenv
#12 4.083   Downloading virtualenv-20.30.0-py3-none-any.whl (4.3 MB)
#12 4.149      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 MB 68.1 MB/s eta 0:00:00
#12 4.206 Collecting platformdirs<5,>=3.9.1
#12 4.210   Downloading platformdirs-4.3.7-py3-none-any.whl (18 kB)
#12 4.228 Collecting distlib<1,>=0.3.7
#12 4.231   Downloading distlib-0.3.9-py2.py3-none-any.whl (468 kB)
#12 4.239      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 469.0/469.0 KB 85.4 MB/s eta 0:00:00
#12 4.274 Collecting filelock<4,>=3.12.2
#12 4.278   Downloading filelock-3.18.0-py3-none-any.whl (16 kB)
#12 4.362 Installing collected packages: distlib, platformdirs, filelock, virtualenv
#12 4.549 Successfully installed distlib-0.3.9 filelock-3.18.0 platformdirs-4.3.7 virtualenv-20.30.0
#12 4.550 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#12 DONE 4.6s

#13 [7/8] COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
#13 DONE 0.0s
---
DirectMap4k:      122816 kB
DirectMap2M:     7217152 kB
DirectMap1G:    11534336 kB
##[endgroup]
Executing TIDY_PRINT_DIFF=1 python2.7 ../x.py test            --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
+ TIDY_PRINT_DIFF=1 python2.7 ../x.py test --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
##[group]Building bootstrap
    Finished `dev` profile [unoptimized] target(s) in 0.05s
##[endgroup]
WARN: currently no CI rustc builds have rustc debug assertions enabled. Please either set `rust.debug-assertions` to `false` if you want to use download CI rustc or set `rust.download-rustc` to `false`.
[TIMING] core::build_steps::tool::LibcxxVersionTool { target: x86_64-unknown-linux-gnu } -- 0.216
---
fmt check
fmt: checked 5982 files
tidy check
tidy: Skipping binary file check, read-only filesystem
##[error]tidy error: /checkout/tests/ui/transmutability/char.rs:17: trailing whitespace
##[error]tidy error: /checkout/compiler/rustc_transmute/src/layout/tree.rs:334: TODO is used for tasks that should be done before merging a PR; If you want to leave a message in the codebase use FIXME
removing old virtual environment
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'venv'
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'virtualenv'
Requirement already satisfied: pip in ./build/venv/lib/python3.10/site-packages (25.0.1)
linting python files
All checks passed!
checking python file formatting
26 files already formatted
checking C++ file formatting
some tidy checks failed
Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:01:41
  local time: Wed Apr 23 19:14:33 UTC 2025
  network time: Wed, 23 Apr 2025 19:14:33 GMT
##[error]Process completed with exit code 1.
Post job cleanup.
```

</details>

author_association: COLLABORATOR
user: login: rust-log-analyzer
created_at: 2025-04-23T19:49:34Z
body: 
The job **`mingw-check-tidy`** failed! Check out the build log: [(web)](https://github.com/rust-lang/rust/actions/runs/14626650471/job/41039691965) [(plain)](https://github.com/rust-lang/rust/commit/1a22b85cd27cffabbbdf27cc8385d4af033eb1fb/checks/41039691965/logs)

<details><summary><i>Click to see the possible cause of the failure (guessed by this bot)</i></summary>

```plain
info: removing rustup binaries
info: rustup is uninstalled
##[group]Image checksum input
mingw-check-tidy
# We use the ghcr base image because ghcr doesn't have a rate limit
# and the mingw-check-tidy job doesn't cache docker images in CI.
FROM ghcr.io/rust-lang/ubuntu:22.04

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
  g++ \
  make \
---

COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/

# NOTE: intentionally uses python2 for x.py so we can test it still works.
# validate-toolstate only runs in our CI, so it's ok for it to only support python3.
ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test \
           --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile --allow-unsafe --generate-hashes reuse-requirements.in
---
#12 3.164 Building wheels for collected packages: reuse
#12 3.166   Building wheel for reuse (pyproject.toml): started
#12 3.378   Building wheel for reuse (pyproject.toml): finished with status 'done'
#12 3.379   Created wheel for reuse: filename=reuse-4.0.3-cp310-cp310-manylinux_2_35_x86_64.whl size=132719 sha256=5bb60f62728aaedff7162745ce743c7f2f55069b3e7f82e6a37d70df455797cc
#12 3.379   Stored in directory: /tmp/pip-ephem-wheel-cache-9zejlvqb/wheels/3d/8d/0a/e0fc6aba4494b28a967ab5eaf951c121d9c677958714e34532
#12 3.382 Successfully built reuse
#12 3.382 Installing collected packages: boolean-py, binaryornot, tomlkit, reuse, python-debian, markupsafe, license-expression, jinja2, chardet, attrs
#12 3.799 Successfully installed attrs-23.2.0 binaryornot-0.4.4 boolean-py-4.0 chardet-5.2.0 jinja2-3.1.4 license-expression-30.3.0 markupsafe-2.1.5 python-debian-0.1.49 reuse-4.0.3 tomlkit-0.13.0
#12 3.799 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#12 4.346 Collecting virtualenv
#12 4.451   Downloading virtualenv-20.30.0-py3-none-any.whl (4.3 MB)
#12 4.627      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 MB 25.4 MB/s eta 0:00:00
#12 4.686 Collecting platformdirs<5,>=3.9.1
#12 4.711   Downloading platformdirs-4.3.7-py3-none-any.whl (18 kB)
#12 4.733 Collecting distlib<1,>=0.3.7
#12 4.759   Downloading distlib-0.3.9-py2.py3-none-any.whl (468 kB)
#12 4.767      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 469.0/469.0 KB 76.7 MB/s eta 0:00:00
#12 4.809 Collecting filelock<4,>=3.12.2
#12 4.835   Downloading filelock-3.18.0-py3-none-any.whl (16 kB)
#12 4.918 Installing collected packages: distlib, platformdirs, filelock, virtualenv
#12 5.105 Successfully installed distlib-0.3.9 filelock-3.18.0 platformdirs-4.3.7 virtualenv-20.30.0
#12 5.105 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#12 DONE 5.2s

#13 [7/8] COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
#13 DONE 0.0s
---
DirectMap4k:      133056 kB
DirectMap2M:     7206912 kB
DirectMap1G:    11534336 kB
##[endgroup]
Executing TIDY_PRINT_DIFF=1 python2.7 ../x.py test            --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
+ TIDY_PRINT_DIFF=1 python2.7 ../x.py test --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
##[group]Building bootstrap
    Finished `dev` profile [unoptimized] target(s) in 0.05s
##[endgroup]
WARN: currently no CI rustc builds have rustc debug assertions enabled. Please either set `rust.debug-assertions` to `false` if you want to use download CI rustc or set `rust.download-rustc` to `false`.
[TIMING] core::build_steps::tool::LibcxxVersionTool { target: x86_64-unknown-linux-gnu } -- 0.227
---
fmt check
fmt: checked 5982 files
tidy check
tidy: Skipping binary file check, read-only filesystem
##[error]tidy error: /checkout/tests/ui/transmutability/char.rs:17: trailing whitespace
removing old virtual environment
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'venv'
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'virtualenv'
Requirement already satisfied: pip in ./build/venv/lib/python3.10/site-packages (25.0.1)
linting python files
All checks passed!
checking python file formatting
26 files already formatted
checking C++ file formatting
some tidy checks failed
Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:02:00
  local time: Wed Apr 23 19:49:22 UTC 2025
  network time: Wed, 23 Apr 2025 19:49:22 GMT
##[error]Process completed with exit code 1.
Post job cleanup.
```

</details>

author_association: COLLABORATOR
user: login: rust-log-analyzer
created_at: 2025-04-23T20:10:41Z
body: 
The job **`mingw-check-tidy`** failed! Check out the build log: [(web)](https://github.com/rust-lang/rust/actions/runs/14626972258/job/41040796459) [(plain)](https://github.com/rust-lang/rust/commit/3df7f0641a39c3acc4f3798ea5d1754c164452c8/checks/41040796459/logs)

<details><summary><i>Click to see the possible cause of the failure (guessed by this bot)</i></summary>

```plain
info: removing rustup binaries
info: rustup is uninstalled
##[group]Image checksum input
mingw-check-tidy
# We use the ghcr base image because ghcr doesn't have a rate limit
# and the mingw-check-tidy job doesn't cache docker images in CI.
FROM ghcr.io/rust-lang/ubuntu:22.04

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
  g++ \
  make \
---

COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/

# NOTE: intentionally uses python2 for x.py so we can test it still works.
# validate-toolstate only runs in our CI, so it's ok for it to only support python3.
ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test \
           --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile --allow-unsafe --generate-hashes reuse-requirements.in
---
#12 4.378   Downloading distlib-0.3.9-py2.py3-none-any.whl (468 kB)
#12 4.387      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 469.0/469.0 KB 60.7 MB/s eta 0:00:00
#12 4.425 Collecting filelock<4,>=3.12.2
#12 4.430   Downloading filelock-3.18.0-py3-none-any.whl (16 kB)
#12 4.467 Collecting platformdirs<5,>=3.9.1
#12 4.471   Downloading platformdirs-4.3.7-py3-none-any.whl (18 kB)
#12 4.555 Installing collected packages: distlib, platformdirs, filelock, virtualenv
#12 4.739 Successfully installed distlib-0.3.9 filelock-3.18.0 platformdirs-4.3.7 virtualenv-20.30.0
#12 4.739 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#12 DONE 4.8s

#13 [7/8] COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
#13 DONE 0.0s
---
DirectMap4k:      116672 kB
DirectMap2M:     6174720 kB
DirectMap1G:    12582912 kB
##[endgroup]
Executing TIDY_PRINT_DIFF=1 python2.7 ../x.py test            --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
+ TIDY_PRINT_DIFF=1 python2.7 ../x.py test --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
##[group]Building bootstrap
    Finished `dev` profile [unoptimized] target(s) in 0.05s
##[endgroup]
WARN: currently no CI rustc builds have rustc debug assertions enabled. Please either set `rust.debug-assertions` to `false` if you want to use download CI rustc or set `rust.download-rustc` to `false`.
[TIMING] core::build_steps::tool::LibcxxVersionTool { target: x86_64-unknown-linux-gnu } -- 0.215
---
fmt check
fmt: checked 5982 files
tidy check
tidy: Skipping binary file check, read-only filesystem
##[error]tidy error: /checkout/tests/ui/transmutability/char.rs:17: trailing whitespace
removing old virtual environment
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'venv'
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'virtualenv'
Requirement already satisfied: pip in ./build/venv/lib/python3.10/site-packages (25.0.1)
linting python files
All checks passed!
checking python file formatting
26 files already formatted
checking C++ file formatting
some tidy checks failed
Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:01:53
  local time: Wed Apr 23 20:10:29 UTC 2025
  network time: Wed, 23 Apr 2025 20:10:29 GMT
##[error]Process completed with exit code 1.
Post job cleanup.
```

</details>

author_association: COLLABORATOR
user: login: bors
created_at: 2025-04-24T09:59:19Z
body: :umbrella: The latest upstream changes (presumably #140168) made this pull request unmergeable. Please [resolve the merge conflicts](https://rustc-dev-guide.rust-lang.org/git.html#rebasing-and-conflicts).
author_association: COLLABORATOR
user: login: joshlf
created_at: 2025-04-24T16:49:07Z
body: @tmiasko Since you've expressed an interest in this, maybe you have a few cycles to poke at a bug that's been stumping me? Running the UI test `transmutability/nonzero.rs` is causing rustc to segfault. It appears to be somewhere in [this match arm](https://github.com/rust-lang/rust/pull/140215/files#diff-d09ef7d4fc4c0bb080e9ecd83b79136d8b1b90be5ec69ae772abf10ce7f12d08R330-R364). No worries if not, obviously, but I figured that maybe something would jump out to you that isn't jumping out to me (as someone without much familiarity with the rustc codebase).
author_association: CONTRIBUTOR
user: login: rust-log-analyzer
created_at: 2025-04-24T16:55:43Z
body: 
The job **`mingw-check-tidy`** failed! Check out the build log: [(web)](https://github.com/rust-lang/rust/actions/runs/14647011831/job/41103703575) [(plain)](https://github.com/rust-lang/rust/commit/b70553b178a2aa706a8449c802463070a4595a28/checks/41103703575/logs)

<details><summary><i>Click to see the possible cause of the failure (guessed by this bot)</i></summary>

```plain
info: removing rustup binaries
info: rustup is uninstalled
##[group]Image checksum input
mingw-check-tidy
# We use the ghcr base image because ghcr doesn't have a rate limit
# and the mingw-check-tidy job doesn't cache docker images in CI.
FROM ghcr.io/rust-lang/ubuntu:22.04

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
  g++ \
  make \
---

COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/

# NOTE: intentionally uses python2 for x.py so we can test it still works.
# validate-toolstate only runs in our CI, so it's ok for it to only support python3.
ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test \
           --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile --allow-unsafe --generate-hashes reuse-requirements.in
---
#12 2.921 Building wheels for collected packages: reuse
#12 2.922   Building wheel for reuse (pyproject.toml): started
#12 3.135   Building wheel for reuse (pyproject.toml): finished with status 'done'
#12 3.136   Created wheel for reuse: filename=reuse-4.0.3-cp310-cp310-manylinux_2_35_x86_64.whl size=132719 sha256=5bb60f62728aaedff7162745ce743c7f2f55069b3e7f82e6a37d70df455797cc
#12 3.136   Stored in directory: /tmp/pip-ephem-wheel-cache-naq8sfqt/wheels/3d/8d/0a/e0fc6aba4494b28a967ab5eaf951c121d9c677958714e34532
#12 3.139 Successfully built reuse
#12 3.139 Installing collected packages: boolean-py, binaryornot, tomlkit, reuse, python-debian, markupsafe, license-expression, jinja2, chardet, attrs
#12 3.550 Successfully installed attrs-23.2.0 binaryornot-0.4.4 boolean-py-4.0 chardet-5.2.0 jinja2-3.1.4 license-expression-30.3.0 markupsafe-2.1.5 python-debian-0.1.49 reuse-4.0.3 tomlkit-0.13.0
#12 3.550 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#12 4.097 Collecting virtualenv
#12 4.145   Downloading virtualenv-20.30.0-py3-none-any.whl (4.3 MB)
#12 4.341      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 MB 22.3 MB/s eta 0:00:00
#12 4.385 Collecting distlib<1,>=0.3.7
#12 4.392   Downloading distlib-0.3.9-py2.py3-none-any.whl (468 kB)
#12 4.406      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 469.0/469.0 KB 40.4 MB/s eta 0:00:00
#12 4.445 Collecting filelock<4,>=3.12.2
#12 4.453   Downloading filelock-3.18.0-py3-none-any.whl (16 kB)
#12 4.490 Collecting platformdirs<5,>=3.9.1
#12 4.498   Downloading platformdirs-4.3.7-py3-none-any.whl (18 kB)
#12 4.580 Installing collected packages: distlib, platformdirs, filelock, virtualenv
#12 4.766 Successfully installed distlib-0.3.9 filelock-3.18.0 platformdirs-4.3.7 virtualenv-20.30.0
#12 4.767 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#12 DONE 4.8s

#13 [7/8] COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
#13 DONE 0.0s
---
DirectMap4k:      131008 kB
DirectMap2M:     7208960 kB
DirectMap1G:    11534336 kB
##[endgroup]
Executing TIDY_PRINT_DIFF=1 python2.7 ../x.py test            --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
+ TIDY_PRINT_DIFF=1 python2.7 ../x.py test --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
##[group]Building bootstrap
    Finished `dev` profile [unoptimized] target(s) in 0.05s
##[endgroup]
WARN: currently no CI rustc builds have rustc debug assertions enabled. Please either set `rust.debug-assertions` to `false` if you want to use download CI rustc or set `rust.download-rustc` to `false`.
[TIMING] core::build_steps::tool::LibcxxVersionTool { target: x86_64-unknown-linux-gnu } -- 0.219
---
fmt check
fmt: checked 5983 files
tidy check
tidy: Skipping binary file check, read-only filesystem
##[error]tidy error: /checkout/tests/ui/transmutability/char.rs:17: trailing whitespace
removing old virtual environment
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'venv'
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'virtualenv'
Requirement already satisfied: pip in ./build/venv/lib/python3.10/site-packages (25.0.1)
linting python files
All checks passed!
checking python file formatting
26 files already formatted
checking C++ file formatting
some tidy checks failed
Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:01:54
  local time: Thu Apr 24 16:55:30 UTC 2025
  network time: Thu, 24 Apr 2025 16:55:30 GMT
##[error]Process completed with exit code 1.
Post job cleanup.
```

</details>

author_association: COLLABORATOR
user: login: jswrenn
created_at: 2025-04-24T16:58:16Z
body: @joshlf I recommend doing an `rr` trace of the `stage1` rustc. 
author_association: MEMBER
user: login: joshlf
created_at: 2025-04-24T19:17:13Z
body: @jswrenn I'll work on that in parallel. In the meantime, this is ready for review (without wiring up `NonZero` types).
author_association: CONTRIBUTOR
user: login: rust-log-analyzer
created_at: 2025-04-24T19:55:06Z
body: 
The job **`x86_64-gnu-llvm-19`** failed! Check out the build log: [(web)](https://github.com/rust-lang/rust/actions/runs/14649910851/job/41113012314) [(plain)](https://github.com/rust-lang/rust/commit/700899ab86147c79bba89a11de8f6c5394a3870f/checks/41113012314/logs)

<details><summary><i>Click to see the possible cause of the failure (guessed by this bot)</i></summary>

```plain
#19 exporting to docker image format
#19 sending tarball 20.4s done
#19 DONE 22.2s
##[endgroup]
Setting extra environment values for docker:  --env ENABLE_GCC_CODEGEN=1 --env GCC_EXEC_PREFIX=/usr/lib/gcc/
[CI_JOB_NAME=x86_64-gnu-llvm-19]
[CI_JOB_NAME=x86_64-gnu-llvm-19]
debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured.
---
sccache: Listening on address 127.0.0.1:4226
##[group]Configure the build
configure: processing command line
configure: 
configure: build.configure-args := ['--build=x86_64-unknown-linux-gnu', '--llvm-root=/usr/lib/llvm-19', '--enable-llvm-link-shared', '--set', 'rust.randomize-layout=true', '--set', 'rust.thin-lto-import-instr-limit=10', '--set', 'build.print-step-timings', '--enable-verbose-tests', '--set', 'build.metrics', '--enable-verbose-configure', '--enable-sccache', '--disable-manage-submodules', '--enable-locked-deps', '--enable-cargo-native-static', '--set', 'rust.codegen-units-std=1', '--set', 'dist.compression-profile=balanced', '--dist-compression-formats=xz', '--set', 'rust.lld=false', '--disable-dist-src', '--release-channel=nightly', '--enable-debug-assertions', '--enable-overflow-checks', '--enable-llvm-assertions', '--set', 'rust.verify-llvm-ir', '--set', 'rust.codegen-backends=llvm,cranelift,gcc', '--set', 'llvm.static-libstdcpp', '--enable-new-symbol-mangling']
configure: build.build          := x86_64-unknown-linux-gnu
configure: target.x86_64-unknown-linux-gnu.llvm-config := /usr/lib/llvm-19/bin/llvm-config
configure: llvm.link-shared     := True
configure: rust.randomize-layout := True
configure: rust.thin-lto-import-instr-limit := 10
---
  Number of decisions:   4447
  longest path:          1159 (code:    152)
  longest backtrack:       66 (code:    428)
Shared 86733 out of 152951 states by creating 14756 new states, saving 71977
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/expmed.cc: In function ‘rtx_def* extract_bit_field_1(rtx, poly_uint64, poly_uint64, int, rtx, machine_mode, machine_mode, bool, bool, rtx_def**)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/expmed.cc:1864:45: warning: ‘*(unsigned int*)((char*)&imode + offsetof(scalar_int_mode, scalar_int_mode::m_mode))’ may be used uninitialized [-Wmaybe-uninitialized]
 1864 |       rtx sub = extract_bit_field_as_subreg (mode1, op0, imode,
      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
 1865 |                                              bitsize, bitnum);
      |                                              ~~~~~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/expmed.cc:1824:19: note: ‘*(unsigned int*)((char*)&imode + offsetof(scalar_int_mode, scalar_int_mode::m_mode))’ was declared here
 1824 |   scalar_int_mode imode;
      |                   ^~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/gimple-range-gori.cc: In member function ‘void range_def_chain::dump(FILE*, basic_block, const char*)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/gimple-range-gori.cc:319:19: warning: format not a string literal and no format arguments [-Wformat-security]
  319 |           fprintf (f, prefix);
      |           ~~~~~~~~^~~~~~~~~~~
---
                 from /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/analyzer/region-model.h:33,
                 from /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/analyzer/access-diagram.cc:39:
In constructor ‘ana::byte_range::byte_range(ana::byte_offset_t, ana::byte_size_t)’,
    inlined from ‘virtual text_art::table ana::string_literal_spatial_item::make_table(const ana::bit_to_table_map&, text_art::style_manager&) const’ at /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/analyzer/access-diagram.cc:1812:18:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/analyzer/store.h:312:5: warning: ‘size_in_bytes.generic_wide_int<fixed_wide_int_storage<128> >::fixed_wide_int_storage<128>.fixed_wide_int_storage<128>::val[1]’ may be used uninitialized [-Wmaybe-uninitialized]
  312 |     m_size_in_bytes (size_in_bytes)
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/analyzer/access-diagram.cc: In member function ‘virtual text_art::table ana::string_literal_spatial_item::make_table(const ana::bit_to_table_map&, text_art::style_manager&) const’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/analyzer/access-diagram.cc:1808:28: note: ‘size_in_bytes.generic_wide_int<fixed_wide_int_storage<128> >::fixed_wide_int_storage<128>.fixed_wide_int_storage<128>::val[1]’ was declared here
 1808 |                byte_size_t size_in_bytes
      |                            ^~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/diagnostic.cc: In function ‘void fancy_abort(const char*, int, const char*)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/diagnostic.cc:1677:15: warning: format not a string literal and no format arguments [-Wformat-security]
 1677 |       fnotice (stderr, diagnostic_kind_text[DK_ICE]);
---
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/gcc.cc:7930:9: warning: ignoring return value of ‘ssize_t write(int, const void*, size_t)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
 7930 |   write (fd, "\n\n", 2);
      |   ~~~~~~^~~~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/gcc.cc: In member function ‘void driver::final_actions() const’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/gcc.cc:9307:13: warning: ignoring return value of ‘int truncate(const char*, __off_t)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
 9307 |     truncate(totruncate_file, 0);
      |     ~~~~~~~~^~~~~~~~~~~~~~~~~~~~
In file included from /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-playback.h:31,
                 from /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-builtins.cc:24:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.h: In member function ‘virtual bool gcc::jit::recording::type::is_same_type_as(gcc::jit::recording::type*)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.h:640:20: warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses]
---
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/lto/lto-common.cc: In function ‘void lto_resolution_read(splay_tree, FILE*, lto_file*)’:
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/lto/lto-common.cc:2091:10: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
 2091 |   fscanf (resolution, " ");   /* Read white space.  */
      |   ~~~~~~~^~~~~~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/lto/lto-common.cc:2093:9: warning: ignoring return value of ‘size_t fread(void*, size_t, size_t, FILE*)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
 2093 |   fread (obj_name, sizeof (char), name_len, resolution);
      |   ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/lto/lto-common.cc:2113:10: warning: ignoring return value of ‘int fscanf(FILE*, const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result]
 2113 |   fscanf (resolution, "%u", &num_symbols);
      |   ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /checkout/obj/build/x86_64-unknown-linux-gnu/gcc/src/gcc/jit/jit-recording.cc:32:
---
Applying machine_name             to sys/rseq.h
Applying io_quotes_use            to sys/epoll.h
Applying io_quotes_use            to sys/raw.h
Applying io_quotes_use            to misc/cxl.h
Applying io_quotes_use            to misc/xilinx_sdfec.h
Applying io_quotes_use            to misc/mrvl_cn10k_dpi.h
Applying io_quotes_use            to misc/ocxl.h
Applying io_quotes_def            to sudo_plugin.h
Applying io_quotes_use            to sudo_plugin.h
Applying io_quotes_def            to unicode/platform.h
Applying glibc_stdint             to stdint.h
Applying hpux8_bogus_inlines      to math.h
---
Applying io_quotes_use            to scsi/cxlflash_ioctl.h
Applying machine_name             to openssl/e_os2.h
Applying io_quotes_use            to drm/tegra_drm.h
Applying io_quotes_use            to drm/vgem_drm.h
Applying io_quotes_use            to drm/pvr_drm.h
Applying io_quotes_use            to drm/i915_drm.h
Applying io_quotes_use            to drm/exynos_drm.h
Applying io_quotes_use            to drm/vc4_drm.h
Applying io_quotes_use            to drm/nouveau_drm.h
Applying io_quotes_use            to drm/xe_drm.h
Applying io_quotes_use            to drm/amdgpu_drm.h
Applying io_quotes_use            to drm/v3d_drm.h
Applying io_quotes_use            to drm/lima_drm.h
Applying io_quotes_use            to drm/etnaviv_drm.h
Applying io_quotes_use            to drm/qaic_accel.h
Applying io_quotes_use            to drm/radeon_drm.h
Applying io_quotes_use            to drm/msm_drm.h
Applying io_quotes_use            to drm/drm.h
Applying io_quotes_use            to drm/habanalabs_accel.h
Applying io_quotes_use            to drm/omap_drm.h
Applying io_quotes_use            to drm/panfrost_drm.h
Applying io_quotes_use            to linux/dma-heap.h
Applying io_quotes_def            to linux/version.h
Applying io_quotes_use            to linux/omapfb.h
---
Applying io_quotes_use            to linux/ndctl.h
Applying io_quotes_use            to linux/dm-ioctl.h
Applying io_quotes_use            to linux/vfio.h
Applying io_quotes_use            to linux/rfkill.h
Applying io_quotes_use            to linux/tps6594_pfsm.h
Applying io_quotes_use            to linux/genwqe/genwqe_card.h
Applying io_quotes_use            to linux/agpgart.h
Applying io_quotes_use            to linux/i2o-dev.h
Applying io_quotes_use            to linux/pidfd.h
Applying io_quotes_use            to linux/psp-dbc.h
---
---- [ui] tests/ui/transmutability/char.rs stdout ----
Saved the actual stderr to "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/transmutability/char/char.stderr"
diff of stderr:

10 LL | pub fn is_transmutable<Src, Dst>()
11    |        --------------- required by a bound in this function
12 LL | where
- LL |     Dst: TransmuteFrom<Src, {Assume::SAFETY}>,
-    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+ LL |     Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
+    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
15 
16 error[E0277]: `main::Char<!, (), !>` cannot be safely transmuted into `char`
17   --> $DIR/char.rs:37:39

25 LL | pub fn is_transmutable<Src, Dst>()
26    |        --------------- required by a bound in this function
27 LL | where
- LL |     Dst: TransmuteFrom<Src, {Assume::SAFETY}>,
-    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+ LL |     Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
+    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
30 
31 error[E0277]: `main::Char<!, !, ()>` cannot be safely transmuted into `char`
32   --> $DIR/char.rs:39:39

40 LL | pub fn is_transmutable<Src, Dst>()
41    |        --------------- required by a bound in this function
42 LL | where
- LL |     Dst: TransmuteFrom<Src, {Assume::SAFETY}>,
-    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+ LL |     Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
+    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
45 
46 error: aborting due to 3 previous errors
47 


The actual stderr differed from the expected stderr.
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args transmutability/char.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/transmutability/char.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/transmutability/char" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers"
stdout: none
--- stderr -------------------------------
error[E0277]: `main::Char<(), !, !>` cannot be safely transmuted into `char`
##[error]  --> /checkout/tests/ui/transmutability/char.rs:35:39
   |
LL |     is_transmutable::<Char<(), !, !>, char>();
   |                                       ^^^^ at least one value of `main::Char<(), !, !>` isn't a bit-valid value of `char`
   |
note: required by a bound in `is_transmutable`
  --> /checkout/tests/ui/transmutability/char.rs:8:10
   |
LL | pub fn is_transmutable<Src, Dst>()
   |        --------------- required by a bound in this function
LL | where
LL |     Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`

error[E0277]: `main::Char<!, (), !>` cannot be safely transmuted into `char`
##[error]  --> /checkout/tests/ui/transmutability/char.rs:37:39
   |
LL |     is_transmutable::<Char<!, (), !>, char>();
   |                                       ^^^^ at least one value of `main::Char<!, (), !>` isn't a bit-valid value of `char`
   |
note: required by a bound in `is_transmutable`
  --> /checkout/tests/ui/transmutability/char.rs:8:10
   |
LL | pub fn is_transmutable<Src, Dst>()
   |        --------------- required by a bound in this function
LL | where
LL |     Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`

error[E0277]: `main::Char<!, !, ()>` cannot be safely transmuted into `char`
##[error]  --> /checkout/tests/ui/transmutability/char.rs:39:39
   |
LL |     is_transmutable::<Char<!, !, ()>, char>();
   |                                       ^^^^ at least one value of `main::Char<!, !, ()>` isn't a bit-valid value of `char`
   |
note: required by a bound in `is_transmutable`
  --> /checkout/tests/ui/transmutability/char.rs:8:10
   |
LL | pub fn is_transmutable<Src, Dst>()
   |        --------------- required by a bound in this function
LL | where
LL |     Dst: TransmuteFrom<Src, { Assume::SAFETY }>,
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0277`.
------------------------------------------
```

</details>

author_association: COLLABORATOR
user: login: tmiasko
created_at: 2025-04-25T06:54:41Z
body: > Running the UI test `transmutability/nonzero.rs` is causing rustc to segfault. It appears to be somewhere in [this match arm](https://github.com/rust-lang/rust/pull/140215/files#diff-d09ef7d4fc4c0bb080e9ecd83b79136d8b1b90be5ec69ae772abf10ce7f12d08R330-R364).

There is an infinite recursion in `ty::Alias` match arm. `AliasTy::to_ty` reconstructs `ty::Alias`, and then recurses without making any progress. The actual problem is probably missing normalization when computing a field type.
author_association: CONTRIBUTOR
user: login: jswrenn
created_at: 2025-04-25T16:28:18Z
body: @joshlf Happy for us to punt `NonZeroXxx` and aliases to a future PR, but can you edit the commit message and PR title accordingly?
author_association: MEMBER
user: login: joshlf
created_at: 2025-04-25T19:56:17Z
body: > @joshlf Happy for us to punt `NonZeroXxx` and aliases to a future PR, but can you edit the commit message and PR title accordingly?

Done.
author_association: CONTRIBUTOR
user: login: jswrenn
created_at: 2025-04-26T00:14:07Z
body: Thanks! I'll follow up with a normalization fix as soon as I unbork my devbox...

@bors r+
author_association: MEMBER
user: login: bors
created_at: 2025-04-26T00:14:09Z
body: :pushpin: Commit ae0c2fe3d8173f03878671e0bba38a03efa44c93 has been approved by `jswrenn`

It is now in the [queue](https://bors.rust-lang.org/homu/queue/rust) for this repository.

<!-- @bors r=jswrenn ae0c2fe3d8173f03878671e0bba38a03efa44c93 -->
<!-- homu: {"type":"Approved","sha":"ae0c2fe3d8173f03878671e0bba38a03efa44c93","approver":"jswrenn","queue":"https://bors.rust-lang.org/homu/queue/rust"} -->
author_association: COLLABORATOR