Safe Transmute: Fix propagation of errors

- Make sure that the most specific Reason is the one that bubbles up when we
  are folding over the `Answer` tree. `Reason::DstIsBitIncompatible` is the
  least specific, so that should be used only when there isn't anything else
  available.
- Small fixes where we used the wrong Reason variant.
- Tiny cleanups
This commit is contained in:
Bryan Garza 2023-04-27 17:19:16 -07:00
parent 263a4f2cb6
commit 94ad084ac6
12 changed files with 67 additions and 52 deletions

View File

@ -2751,7 +2751,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.substs.const_at(3)) else {
span_bug!(span, "Unable to construct rustc_transmute::Assume where it was previously possible");
};
// FIXME(bryangarza): Need to flatten here too
// FIXME(bryangarza): Is this enough, or should we resolve all nested
// obligations like we do for `confirm_transmutability_candidate(...)?`
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
obligation.cause,
src_and_dst,
@ -2780,7 +2781,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
rustc_transmute::Reason::DstIsPrivate => format!(
"`{dst}` is or contains a type or field that is not visible in that scope"
),
// FIXME(bryangarza): Include the number of bytes of src and dst
rustc_transmute::Reason::DstIsTooBig => {
format!("The size of `{src}` is smaller than the size of `{dst}`")
}

View File

@ -329,7 +329,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)
};
// // FIXME(bryangarza): Check src.mutability or dst.mutability to know whether dst -> src obligation is needed
// FIXME(bryangarza): Check src.mutability or dst.mutability to know whether dst -> src obligation is needed
Ok(vec![make_obl(src.ty, dst.ty), make_obl(dst.ty, src.ty)])
}
}

View File

@ -1,4 +1,4 @@
#![feature(alloc_layout_extra, decl_macro, iterator_try_reduce, never_type)]
#![feature(alloc_layout_extra, decl_macro, iterator_try_reduce, never_type, let_chains)]
#![allow(dead_code, unused_variables)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]

View File

@ -78,11 +78,12 @@ mod rustc {
match (src, dst) {
// Answer `Ok(None)` here, because 'unknown layout' and type errors will already
// be reported by rustc. No need to spam the user with more errors.
(Err(Err::TypeError(_)), _) | (_, Err(Err::TypeError(_))) => Err(Ok(None)),
(Err(Err::Unknown), _) | (_, Err(Err::Unknown)) => Err(Ok(None)),
(Err(Err::Unspecified), _) | (_, Err(Err::Unspecified)) => {
Err(Err(Reason::SrcIsUnspecified))
}
(Err(Err::TypeError(_)), _)
| (_, Err(Err::TypeError(_)))
| (Err(Err::Unknown), _)
| (_, Err(Err::Unknown)) => Err(Ok(None)),
(Err(Err::Unspecified), _) => Err(Err(Reason::SrcIsUnspecified)),
(_, Err(Err::Unspecified)) => Err(Err(Reason::DstIsUnspecified)),
(Ok(src), Ok(dst)) => Ok((src, dst)),
}
});
@ -316,12 +317,19 @@ where
}
}
fn and<R>(lhs: Answer<R>, rhs: Answer<R>) -> Answer<R> {
// Should propagate errors on the right side, because the initial value
// used in `apply` is on the left side.
let rhs = rhs?;
let lhs = lhs?;
Ok(match (lhs, rhs) {
fn and<R>(lhs: Answer<R>, rhs: Answer<R>) -> Answer<R>
where
R: PartialEq,
{
// If both are errors, then we should return the more specific one
if lhs.is_err() && rhs.is_err() {
if lhs == Err(Reason::DstIsBitIncompatible) {
return rhs;
} else {
return lhs;
}
}
Ok(match (lhs?, rhs?) {
// If only one side has a condition, pass it along
(None, other) | (other, None) => other,
// If both sides have IfAll conditions, merge them
@ -340,10 +348,17 @@ fn and<R>(lhs: Answer<R>, rhs: Answer<R>) -> Answer<R> {
})
}
fn or<R>(lhs: Answer<R>, rhs: Answer<R>) -> Answer<R> {
// If both are errors, then we should return the one on the right
fn or<R>(lhs: Answer<R>, rhs: Answer<R>) -> Answer<R>
where
R: PartialEq,
{
// If both are errors, then we should return the more specific one
if lhs.is_err() && rhs.is_err() {
return rhs;
if lhs == Err(Reason::DstIsBitIncompatible) {
return rhs;
} else {
return lhs;
}
}
// Otherwise, errors can be ignored for the rest of the pattern matching
let lhs = lhs.unwrap_or(None);

View File

@ -23,7 +23,7 @@ error[E0277]: `u128` cannot be safely transmuted into `[String; 0]` in the defin
--> $DIR/should_require_well_defined_layout.rs:27:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` does not have a well-specified layout
| ^^^^^^^^^ `[String; 0]` does not have a well-specified layout
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
@ -65,7 +65,7 @@ error[E0277]: `u128` cannot be safely transmuted into `[String; 1]` in the defin
--> $DIR/should_require_well_defined_layout.rs:33:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` does not have a well-specified layout
| ^^^^^^^^^ `[String; 1]` does not have a well-specified layout
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
@ -107,7 +107,7 @@ error[E0277]: `u128` cannot be safely transmuted into `[String; 2]` in the defin
--> $DIR/should_require_well_defined_layout.rs:39:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` does not have a well-specified layout
| ^^^^^^^^^ `[String; 2]` does not have a well-specified layout
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14

View File

@ -24,7 +24,7 @@ error[E0277]: `V0i8` cannot be safely transmuted into `u16` in the defining scop
--> $DIR/primitive_reprs_should_have_correct_length.rs:50:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ At least one value of `V0i8` isn't a bit-valid value of `u16`
| ^^^^^^ The size of `V0i8` is smaller than the size of `u16`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -68,7 +68,7 @@ error[E0277]: `V0u8` cannot be safely transmuted into `u16` in the defining scop
--> $DIR/primitive_reprs_should_have_correct_length.rs:58:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ At least one value of `V0u8` isn't a bit-valid value of `u16`
| ^^^^^^ The size of `V0u8` is smaller than the size of `u16`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -90,7 +90,7 @@ error[E0277]: `u8` cannot be safely transmuted into `V0i16` in the defining scop
--> $DIR/primitive_reprs_should_have_correct_length.rs:72:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ At least one value of `u8` isn't a bit-valid value of `V0i16`
| ^^^^^^^ The size of `u8` is smaller than the size of `V0i16`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -112,7 +112,7 @@ error[E0277]: `V0i16` cannot be safely transmuted into `u32` in the defining sco
--> $DIR/primitive_reprs_should_have_correct_length.rs:74:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ At least one value of `V0i16` isn't a bit-valid value of `u32`
| ^^^^^^ The size of `V0i16` is smaller than the size of `u32`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -134,7 +134,7 @@ error[E0277]: `u8` cannot be safely transmuted into `V0u16` in the defining scop
--> $DIR/primitive_reprs_should_have_correct_length.rs:80:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ At least one value of `u8` isn't a bit-valid value of `V0u16`
| ^^^^^^^ The size of `u8` is smaller than the size of `V0u16`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -156,7 +156,7 @@ error[E0277]: `V0u16` cannot be safely transmuted into `u32` in the defining sco
--> $DIR/primitive_reprs_should_have_correct_length.rs:82:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ At least one value of `V0u16` isn't a bit-valid value of `u32`
| ^^^^^^ The size of `V0u16` is smaller than the size of `u32`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -178,7 +178,7 @@ error[E0277]: `u16` cannot be safely transmuted into `V0i32` in the defining sco
--> $DIR/primitive_reprs_should_have_correct_length.rs:96:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ At least one value of `u16` isn't a bit-valid value of `V0i32`
| ^^^^^^^ The size of `u16` is smaller than the size of `V0i32`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -200,7 +200,7 @@ error[E0277]: `V0i32` cannot be safely transmuted into `u64` in the defining sco
--> $DIR/primitive_reprs_should_have_correct_length.rs:98:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ At least one value of `V0i32` isn't a bit-valid value of `u64`
| ^^^^^^ The size of `V0i32` is smaller than the size of `u64`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -222,7 +222,7 @@ error[E0277]: `u16` cannot be safely transmuted into `V0u32` in the defining sco
--> $DIR/primitive_reprs_should_have_correct_length.rs:104:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ At least one value of `u16` isn't a bit-valid value of `V0u32`
| ^^^^^^^ The size of `u16` is smaller than the size of `V0u32`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -244,7 +244,7 @@ error[E0277]: `V0u32` cannot be safely transmuted into `u64` in the defining sco
--> $DIR/primitive_reprs_should_have_correct_length.rs:106:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ At least one value of `V0u32` isn't a bit-valid value of `u64`
| ^^^^^^ The size of `V0u32` is smaller than the size of `u64`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -266,7 +266,7 @@ error[E0277]: `u32` cannot be safely transmuted into `V0i64` in the defining sco
--> $DIR/primitive_reprs_should_have_correct_length.rs:120:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ At least one value of `u32` isn't a bit-valid value of `V0i64`
| ^^^^^^^ The size of `u32` is smaller than the size of `V0i64`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -288,7 +288,7 @@ error[E0277]: `V0i64` cannot be safely transmuted into `u128` in the defining sc
--> $DIR/primitive_reprs_should_have_correct_length.rs:122:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ At least one value of `V0i64` isn't a bit-valid value of `u128`
| ^^^^^^ The size of `V0i64` is smaller than the size of `u128`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -310,7 +310,7 @@ error[E0277]: `u32` cannot be safely transmuted into `V0u64` in the defining sco
--> $DIR/primitive_reprs_should_have_correct_length.rs:128:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ At least one value of `u32` isn't a bit-valid value of `V0u64`
| ^^^^^^^ The size of `u32` is smaller than the size of `V0u64`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -332,7 +332,7 @@ error[E0277]: `V0u64` cannot be safely transmuted into `u128` in the defining sc
--> $DIR/primitive_reprs_should_have_correct_length.rs:130:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ At least one value of `V0u64` isn't a bit-valid value of `u128`
| ^^^^^^ The size of `V0u64` is smaller than the size of `u128`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -354,7 +354,7 @@ error[E0277]: `u8` cannot be safely transmuted into `V0isize` in the defining sc
--> $DIR/primitive_reprs_should_have_correct_length.rs:144:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ At least one value of `u8` isn't a bit-valid value of `V0isize`
| ^^^^^^^ The size of `u8` is smaller than the size of `V0isize`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -376,7 +376,7 @@ error[E0277]: `V0isize` cannot be safely transmuted into `[usize; 2]` in the def
--> $DIR/primitive_reprs_should_have_correct_length.rs:146:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ At least one value of `V0isize` isn't a bit-valid value of `[usize; 2]`
| ^^^^^^ The size of `V0isize` is smaller than the size of `[usize; 2]`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -398,7 +398,7 @@ error[E0277]: `u8` cannot be safely transmuted into `V0usize` in the defining sc
--> $DIR/primitive_reprs_should_have_correct_length.rs:152:44
|
LL | assert::is_transmutable::<Smaller, Current, Context>();
| ^^^^^^^ At least one value of `u8` isn't a bit-valid value of `V0usize`
| ^^^^^^^ The size of `u8` is smaller than the size of `V0usize`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@ -420,7 +420,7 @@ error[E0277]: `V0usize` cannot be safely transmuted into `[usize; 2]` in the def
--> $DIR/primitive_reprs_should_have_correct_length.rs:154:44
|
LL | assert::is_transmutable::<Current, Larger, Context>();
| ^^^^^^ At least one value of `V0usize` isn't a bit-valid value of `[usize; 2]`
| ^^^^^^ The size of `V0usize` is smaller than the size of `[usize; 2]`
|
note: required by a bound in `is_transmutable`
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14

View File

@ -24,7 +24,7 @@ error[E0277]: `u128` cannot be safely transmuted into `void::repr_rust` in the d
--> $DIR/should_require_well_defined_layout.rs:29:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` does not have a well-specified layout
| ^^^^^^^^^ `void::repr_rust` does not have a well-specified layout
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
@ -68,7 +68,7 @@ error[E0277]: `u128` cannot be safely transmuted into `singleton::repr_rust` in
--> $DIR/should_require_well_defined_layout.rs:35:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` does not have a well-specified layout
| ^^^^^^^^^ `singleton::repr_rust` does not have a well-specified layout
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14
@ -112,7 +112,7 @@ error[E0277]: `u128` cannot be safely transmuted into `duplex::repr_rust` in the
--> $DIR/should_require_well_defined_layout.rs:41:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` does not have a well-specified layout
| ^^^^^^^^^ `duplex::repr_rust` does not have a well-specified layout
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:14:14

View File

@ -2,7 +2,7 @@ error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope
--> $DIR/should_pad_variants.rs:44:36
|
LL | assert::is_transmutable::<Src, Dst, Context>();
| ^^^ At least one value of `Src` isn't a bit-valid value of `Dst`
| ^^^ The size of `Src` is smaller than the size of `Dst`
|
note: required by a bound in `is_transmutable`
--> $DIR/should_pad_variants.rs:13:14

View File

@ -24,7 +24,7 @@ error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::
--> $DIR/should_require_well_defined_layout.rs:29:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` does not have a well-specified layout
| ^^^^^^^^^ `should_reject_repr_rust::unit::repr_rust` does not have a well-specified layout
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
@ -68,7 +68,7 @@ error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::
--> $DIR/should_require_well_defined_layout.rs:35:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` does not have a well-specified layout
| ^^^^^^^^^ `should_reject_repr_rust::tuple::repr_rust` does not have a well-specified layout
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
@ -112,7 +112,7 @@ error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::
--> $DIR/should_require_well_defined_layout.rs:41:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` does not have a well-specified layout
| ^^^^^^^^^ `should_reject_repr_rust::braces::repr_rust` does not have a well-specified layout
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
@ -156,7 +156,7 @@ error[E0277]: `u128` cannot be safely transmuted into `aligned::repr_rust` in th
--> $DIR/should_require_well_defined_layout.rs:47:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` does not have a well-specified layout
| ^^^^^^^^^ `aligned::repr_rust` does not have a well-specified layout
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
@ -200,7 +200,7 @@ error[E0277]: `u128` cannot be safely transmuted into `packed::repr_rust` in the
--> $DIR/should_require_well_defined_layout.rs:53:47
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` does not have a well-specified layout
| ^^^^^^^^^ `packed::repr_rust` does not have a well-specified layout
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14
@ -244,7 +244,7 @@ error[E0277]: `u128` cannot be safely transmuted into `nested::repr_c` in the de
--> $DIR/should_require_well_defined_layout.rs:60:47
|
LL | assert::is_maybe_transmutable::<u128, repr_c>();
| ^^^^^^ `u128` does not have a well-specified layout
| ^^^^^^ `nested::repr_c` does not have a well-specified layout
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14

View File

@ -24,7 +24,7 @@ error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::
--> $DIR/should_require_well_defined_layout.rs:31:43
|
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
| ^^^^^^^^^ `u128` does not have a well-specified layout
| ^^^^^^^^^ `should_reject_repr_rust::repr_rust` does not have a well-specified layout
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/should_require_well_defined_layout.rs:13:14

View File

@ -2,7 +2,7 @@ error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope
--> $DIR/should_pad_variants.rs:44:36
|
LL | assert::is_transmutable::<Src, Dst, Context>();
| ^^^ At least one value of `Src` isn't a bit-valid value of `Dst`
| ^^^ The size of `Src` is smaller than the size of `Dst`
|
note: required by a bound in `is_transmutable`
--> $DIR/should_pad_variants.rs:13:14

View File

@ -2,7 +2,7 @@ error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of
--> $DIR/transmute-padding-ice.rs:27:40
|
LL | assert::is_maybe_transmutable::<B, A>();
| ^ At least one value of `B` isn't a bit-valid value of `A`
| ^ The size of `B` is smaller than the size of `A`
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/transmute-padding-ice.rs:11:14