diff options
| author | Bryan Garza <1396101+bryangarza@users.noreply.github.com> | 2023-04-27 17:19:16 -0700 | 
|---|---|---|
| committer | Bryan Garza <1396101+bryangarza@users.noreply.github.com> | 2023-05-24 14:52:19 -0700 | 
| commit | 94ad084ac611b7c21d4f08b1eb30623f09db2cd0 (patch) | |
| tree | 10214d71cf1548ea8426c626b514c41908ccc256 /compiler | |
| parent | 263a4f2cb6b455f9c4ae46493d59369c378a85ea (diff) | |
| download | rust-94ad084ac611b7c21d4f08b1eb30623f09db2cd0.tar.gz rust-94ad084ac611b7c21d4f08b1eb30623f09db2cd0.zip | |
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
Diffstat (limited to 'compiler')
4 files changed, 33 insertions, 18 deletions
| diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 71419fe0eee..8224fdf591a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -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}`") } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 528a5f9dc61..e3d982b5c3f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -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)]) } } diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index baf63e6d3a2..60adbc1b470 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -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)] diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index de00efb1614..47f61a80840 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -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); | 
