Skip to content

Safe Transmute: Fix ICE (due to UnevaluatedConst) #113677

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 12 additions & 1 deletion compiler/rustc_transmute/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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
Expand Down
40 changes: 40 additions & 0 deletions tests/ui/transmutability/issue-110892.rs
Original file line number Diff line number Diff line change
@@ -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>();
}
36 changes: 36 additions & 0 deletions tests/ui/transmutability/issue-110892.stderr
Original file line number Diff line number Diff line change
@@ -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`.