Auto merge of #113677 - bryangarza:unevaluated-const-ice_issue-110892, r=davidtwco

Safe Transmute: Fix ICE (due to UnevaluatedConst)

This patch updates the code that looks at the `Assume` type when evaluating if transmutation is possible. An ICE was being triggered in the case that the `Assume` parameter contained an unevaluated const (in this test case, due to a function with missing parameter names).

Fixes #110892
This commit is contained in:
bors 2023-07-18 09:07:32 +00:00
commit c44324a4fe
4 changed files with 96 additions and 1 deletions

View File

@ -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<ty::ValTree<'tcx>> {
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

View File

@ -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

View File

@ -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::<Src, Dst, Context, false, false, { true }, false>();
}

View File

@ -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`.