diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index bf9f5846ed9..4ef70107f19 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -294,6 +294,14 @@ impl<'tcx> Const<'tcx> { Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) } + /// Attempts to convert to a `ValTree` + pub fn try_to_valtree(self) -> Option> { + match self.kind() { + ty::ConstKind::Value(valtree) => Some(valtree), + _ => None, + } + } + #[inline] /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 34ad6bd8c69..05ad4a4a12a 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -78,6 +78,7 @@ mod rustc { use rustc_middle::ty::ParamEnv; use rustc_middle::ty::Ty; use rustc_middle::ty::TyCtxt; + use rustc_middle::ty::ValTree; /// The source and destination types of a transmutation. #[derive(TypeVisitable, Debug, Clone, Copy)] @@ -148,7 +149,17 @@ mod rustc { ); let variant = adt_def.non_enum_variant(); - let fields = c.to_valtree().unwrap_branch(); + let fields = match c.try_to_valtree() { + Some(ValTree::Branch(branch)) => branch, + _ => { + return Some(Self { + alignment: true, + lifetimes: true, + safety: true, + validity: true, + }); + } + }; let get_field = |name| { let (field_idx, _) = variant diff --git a/tests/ui/transmutability/issue-110892.rs b/tests/ui/transmutability/issue-110892.rs new file mode 100644 index 00000000000..ce926b39996 --- /dev/null +++ b/tests/ui/transmutability/issue-110892.rs @@ -0,0 +1,40 @@ +// check-fail +#![feature(generic_const_exprs, transmutability)] +#![allow(incomplete_features)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable< + Src, + Dst, + Context, + const ASSUME_ALIGNMENT: bool, + const ASSUME_LIFETIMES: bool, + const ASSUME_SAFETY: bool, + const ASSUME_VALIDITY: bool, + >() + where + Dst: BikeshedIntrinsicFrom< + Src, + Context, + { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } + >, + {} + + // This should not cause an ICE + const fn from_options( + , //~ ERROR expected parameter name, found `,` + , //~ ERROR expected parameter name, found `,` + , //~ ERROR expected parameter name, found `,` + , //~ ERROR expected parameter name, found `,` + ) -> Assume {} //~ ERROR mismatched types +} + +fn main() { + struct Context; + #[repr(C)] struct Src; + #[repr(C)] struct Dst; + + assert::is_transmutable::(); +} diff --git a/tests/ui/transmutability/issue-110892.stderr b/tests/ui/transmutability/issue-110892.stderr new file mode 100644 index 00000000000..13654307aee --- /dev/null +++ b/tests/ui/transmutability/issue-110892.stderr @@ -0,0 +1,36 @@ +error: expected parameter name, found `,` + --> $DIR/issue-110892.rs:27:9 + | +LL | , + | ^ expected parameter name + +error: expected parameter name, found `,` + --> $DIR/issue-110892.rs:28:9 + | +LL | , + | ^ expected parameter name + +error: expected parameter name, found `,` + --> $DIR/issue-110892.rs:29:9 + | +LL | , + | ^ expected parameter name + +error: expected parameter name, found `,` + --> $DIR/issue-110892.rs:30:9 + | +LL | , + | ^ expected parameter name + +error[E0308]: mismatched types + --> $DIR/issue-110892.rs:31:10 + | +LL | const fn from_options( + | ------------ implicitly returns `()` as its body has no tail or `return` expression +... +LL | ) -> Assume {} + | ^^^^^^ expected `Assume`, found `()` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`.