-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Safe Transmute: Fix ICE (Inconsistent is_transmutable result) #113867
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -340,12 +340,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | |
let predicate = | ||
self.tcx().erase_regions(self.tcx().erase_late_bound_regions(obligation.predicate)); | ||
|
||
let Some(assume) = rustc_transmute::Assume::from_const( | ||
let assume = match rustc_transmute::Assume::from_const( | ||
self.infcx.tcx, | ||
obligation.param_env, | ||
predicate.trait_ref.args.const_at(3), | ||
) else { | ||
return Err(Unimplemented); | ||
) { | ||
Ok(Some(assume)) => assume, | ||
Ok(None) => return Ok(vec![]), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's wrong. We would consider transmute to always be possible if the assume is ambig '^^ it's annoying because confirmation cannot handle ambiguity. We have to instead check that we can build the |
||
Err(_guar) => return Err(Unimplemented), | ||
}; | ||
|
||
let dst = predicate.trait_ref.args.type_at(0); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,7 +59,7 @@ pub enum Reason { | |
/// Can't go from shared pointer to unique pointer | ||
DstIsMoreUnique, | ||
/// Encountered a type error | ||
TypeError, | ||
ErrorGuaranteed(ErrorGuaranteed), | ||
/// The layout of src is unknown | ||
SrcLayoutUnknown, | ||
/// The layout of dst is unknown | ||
|
@@ -79,6 +79,7 @@ mod rustc { | |
use rustc_middle::ty::Ty; | ||
use rustc_middle::ty::TyCtxt; | ||
use rustc_middle::ty::ValTree; | ||
use rustc_span::ErrorGuaranteed; | ||
|
||
/// The source and destination types of a transmutation. | ||
#[derive(TypeVisitable, Debug, Clone, Copy)] | ||
|
@@ -123,23 +124,20 @@ mod rustc { | |
tcx: TyCtxt<'tcx>, | ||
param_env: ParamEnv<'tcx>, | ||
c: Const<'tcx>, | ||
) -> Option<Self> { | ||
) -> Result<Option<Self>, ErrorGuaranteed> { | ||
use rustc_middle::ty::ScalarInt; | ||
use rustc_middle::ty::TypeVisitableExt; | ||
use rustc_span::symbol::sym; | ||
|
||
let c = c.eval(tcx, param_env); | ||
|
||
if let Err(err) = c.error_reported() { | ||
return Some(Self { | ||
alignment: true, | ||
lifetimes: true, | ||
safety: true, | ||
validity: true, | ||
}); | ||
return Err(err); | ||
} | ||
|
||
let adt_def = c.ty().ty_adt_def()?; | ||
let adt_def = match c.ty().ty_adt_def() { | ||
Some(adt_def) => adt_def, | ||
None => return Ok(None), | ||
}; | ||
|
||
assert_eq!( | ||
tcx.require_lang_item(LangItem::TransmuteOpts, None), | ||
|
@@ -151,14 +149,7 @@ mod rustc { | |
let variant = adt_def.non_enum_variant(); | ||
let fields = match c.try_to_valtree() { | ||
Some(ValTree::Branch(branch)) => branch, | ||
_ => { | ||
lcnr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return Some(Self { | ||
alignment: true, | ||
lifetimes: true, | ||
safety: true, | ||
validity: true, | ||
}); | ||
} | ||
_ => return Ok(None), | ||
}; | ||
|
||
let get_field = |name| { | ||
|
@@ -171,15 +162,19 @@ mod rustc { | |
fields[field_idx].unwrap_leaf() == ScalarInt::TRUE | ||
}; | ||
|
||
Some(Self { | ||
Ok(Some(Self { | ||
alignment: get_field(sym::alignment), | ||
lifetimes: get_field(sym::lifetimes), | ||
safety: get_field(sym::safety), | ||
validity: get_field(sym::validity), | ||
}) | ||
})) | ||
} | ||
} | ||
} | ||
|
||
// FIXME(bryangarza): This prevents `cargo build` from building. | ||
// Need to remove this dependency on `ErrorGuaranteed` so the crate can | ||
// build/test independently of rustc again. | ||
#[cfg(feature = "rustc")] | ||
pub use rustc::*; | ||
use rustc_span::ErrorGuaranteed; | ||
Comment on lines
179
to
+180
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this import should live in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, we are trying to make it so that rustc_transmute can build independently of rustc, so pulling in |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
error[E0308]: mismatched types | ||
--> $DIR/inconsistent-is-transmutable.rs:27:74 | ||
| | ||
LL | const FALSE: bool = assert::is_transmutable::<Src, Dst, Context, {}>(); | ||
| ^^ expected `Assume`, found `()` | ||
|
||
error[E0308]: mismatched types | ||
--> $DIR/inconsistent-is-transmutable.rs:27:29 | ||
| | ||
LL | const FALSE: bool = assert::is_transmutable::<Src, Dst, Context, {}>(); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0308`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
error[E0308]: mismatched types | ||
--> $DIR/inconsistent-is-transmutable.rs:27:74 | ||
| | ||
LL | const FALSE: bool = assert::is_transmutable::<Src, Dst, Context, {}>(); | ||
| ^^ expected `Assume`, found `()` | ||
|
||
error[E0308]: mismatched types | ||
--> $DIR/inconsistent-is-transmutable.rs:27:29 | ||
| | ||
LL | const FALSE: bool = assert::is_transmutable::<Src, Dst, Context, {}>(); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0308`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// check-fail | ||
// revisions: current next | ||
//[next] compile-flags: -Ztrait-solver=next | ||
// https://github.com/rust-lang/rust/issues/110969 | ||
#![feature(adt_const_params, generic_const_exprs, transmutability)] | ||
#![allow(incomplete_features)] | ||
|
||
mod assert { | ||
use std::mem::BikeshedIntrinsicFrom; | ||
|
||
pub fn is_transmutable<Src, Dst, Context, const ASSUME: std::mem::Assume>() | ||
where | ||
Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME>, | ||
{ | ||
} | ||
} | ||
|
||
fn main() { | ||
struct Context; | ||
#[repr(C)] | ||
struct Src; | ||
#[repr(C)] | ||
struct Dst; | ||
|
||
trait Trait { | ||
// The `{}` should not cause an ICE | ||
const FALSE: bool = assert::is_transmutable::<Src, Dst, Context, {}>(); | ||
//~^ ERROR mismatched types | ||
//~^^ ERROR mismatched types | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
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: expected parameter name, found `,` | ||
--> $DIR/issue-110892.rs:31:9 | ||
| | ||
LL | , | ||
| ^ expected parameter name | ||
|
||
error: expected parameter name, found `,` | ||
--> $DIR/issue-110892.rs:32:9 | ||
| | ||
LL | , | ||
| ^ expected parameter name | ||
|
||
error[E0284]: type annotations needed: cannot satisfy `the constant `{ from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }` can be evaluated` | ||
--> $DIR/issue-110892.rs:23:13 | ||
| | ||
LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `{ from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }` can be evaluated` | ||
| | ||
note: required by a bound in `is_transmutable` | ||
--> $DIR/issue-110892.rs:23:13 | ||
| | ||
LL | pub fn is_transmutable< | ||
| --------------- required by a bound in this function | ||
... | ||
LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` | ||
|
||
error: aborting due to 5 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0284`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this feels somewhat dangerous to me 🤷 i guess it's fine because fulfillment error reporting uses
delay_span_bug
so if it's wrong we just ICEThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah it's not ideal :/ I could emit a warning or something maybe 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, maybe add
tcx.sess.delay_span_bug("expected another error here")
or sth to get a better ICE if it does go wrong. THis should simplify debugging if it blows up