diff options
| author | Bryan Garza <1396101+bryangarza@users.noreply.github.com> | 2023-05-24 17:47:13 -0700 |
|---|---|---|
| committer | Bryan Garza <1396101+bryangarza@users.noreply.github.com> | 2023-05-24 17:49:56 -0700 |
| commit | d2164d5c9a17a7c2eefeccf623c278612b2650de (patch) | |
| tree | b1dd74d0baeb833d0da51390c42cd91a8faf702c | |
| parent | 62663582375d7dedf42c0a30bfe04c7b53b452d7 (diff) | |
| download | rust-d2164d5c9a17a7c2eefeccf623c278612b2650de.tar.gz rust-d2164d5c9a17a7c2eefeccf623c278612b2650de.zip | |
Safe Transmute: Update definition of Condition type
- Change `Condition` to not contain `Answer`s but instead just contain other `Condition`s directly. - Also improve error reporting for `DstHasStricterAlignment`
5 files changed, 39 insertions, 33 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 82ce2c2fa8d..23126f2cb52 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2751,8 +2751,7 @@ 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): 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, @@ -2784,10 +2783,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { rustc_transmute::Reason::DstIsTooBig => { format!("The size of `{src}` is smaller than the size of `{dst}`") } - // FIXME(bryangarza): Say exactly what the minimum alignments of src and dst are - rustc_transmute::Reason::DstHasStricterAlignment => { + rustc_transmute::Reason::DstHasStricterAlignment { + src_min_align, + dst_min_align, + } => { format!( - "The minimum alignment of `{src}` should be greater than that of `{dst}`, but it is not" + "The minimum alignment of `{src}` ({src_min_align}) should be greater than that of `{dst}` ({dst_min_align})" ) } rustc_transmute::Reason::DstIsMoreUnique => { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 6b8d8a947ea..3f07ad814ff 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -290,25 +290,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { tcx: TyCtxt<'tcx>, obligation: &TraitObligation<'tcx>, predicate: TraitPredicate<'tcx>, - answer: rustc_transmute::Answer<rustc_transmute::layout::rustc::Ref<'tcx>>, - ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> { + answer: rustc_transmute::Condition<rustc_transmute::layout::rustc::Ref<'tcx>>, + ) -> Vec<PredicateObligation<'tcx>> { match answer { - Ok(None) => Ok(vec![]), - Err(_) => Err(Unimplemented), // FIXME(bryangarza): Add separate `IfAny` case, instead of treating as `IfAll` // Not possible until the trait solver supports disjunctions of obligations - Ok(Some(rustc_transmute::Condition::IfAll(answers))) - | Ok(Some(rustc_transmute::Condition::IfAny(answers))) => { + rustc_transmute::Condition::IfAll(answers) + | rustc_transmute::Condition::IfAny(answers) => { let mut nested = vec![]; for flattened in answers .into_iter() .map(|answer| flatten_answer_tree(tcx, obligation, predicate, answer)) { - nested.extend(flattened?); + nested.extend(flattened); } - Ok(nested) + nested } - Ok(Some(rustc_transmute::Condition::IfTransmutable { src, dst })) => { + rustc_transmute::Condition::IfTransmutable { src, dst } => { let trait_def_id = obligation.predicate.def_id(); let scope = predicate.trait_ref.substs.type_at(2); let assume_const = predicate.trait_ref.substs.const_at(3); @@ -339,7 +337,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if dst.mutability == Mutability::Mut { obligations.push(make_obl(dst.ty, src.ty)); } - Ok(obligations) + obligations } } } @@ -371,8 +369,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { assume, ); - let fully_flattened = - flatten_answer_tree(self.tcx(), obligation, predicate, maybe_transmutable)?; + let fully_flattened = match maybe_transmutable { + Err(_) => Err(Unimplemented)?, + Ok(Some(mt)) => flatten_answer_tree(self.tcx(), obligation, predicate, mt), + Ok(None) => vec![], + }; + debug!(?fully_flattened); Ok(ImplSourceBuiltinData { nested: fully_flattened }) } diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index baf63e6d3a2..7a8cbd50d45 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -29,10 +29,10 @@ pub enum Condition<R> { IfTransmutable { src: R, dst: R }, /// `Src` is transmutable into `Dst`, if all of the enclosed requirements are met. - IfAll(Vec<Answer<R>>), + IfAll(Vec<Condition<R>>), /// `Src` is transmutable into `Dst` if any of the enclosed requirements are met. - IfAny(Vec<Answer<R>>), + IfAny(Vec<Condition<R>>), } /// Answers: Why wasn't the source type transmutable into the destination type? @@ -49,7 +49,7 @@ pub enum Reason { /// `Dst` is larger than `Src`, and the excess bytes were not exclusively uninitialized. DstIsTooBig, /// Src should have a stricter alignment than Dst, but it does not. - DstHasStricterAlignment, + DstHasStricterAlignment { src_min_align: usize, dst_min_align: usize }, /// Can't go from shared pointer to unique pointer DstIsMoreUnique, } diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index 0f4a096cdae..80e3489e99b 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -303,7 +303,10 @@ where } else if !self.assume.alignment && src_ref.min_align() < dst_ref.min_align() { - Err(Reason::DstHasStricterAlignment) + Err(Reason::DstHasStricterAlignment { + src_min_align: src_ref.min_align(), + dst_min_align: dst_ref.min_align(), + }) } else { // ...such that `src` is transmutable into `dst`, if // `src_ref` is transmutability into `dst_ref`. @@ -360,13 +363,13 @@ where Some(Condition::IfAll(lhs)) } // If only one side is an IfAll, add the other Condition to it - (constraint, Some(Condition::IfAll(mut constraints))) - | (Some(Condition::IfAll(mut constraints)), constraint) => { - constraints.push(Ok(constraint)); - Some(Condition::IfAll(constraints)) + (Some(cond), Some(Condition::IfAll(mut conds))) + | (Some(Condition::IfAll(mut conds)), Some(cond)) => { + conds.push(cond); + Some(Condition::IfAll(conds)) } // Otherwise, both lhs and rhs conditions can be combined in a parent IfAll - (lhs, rhs) => Some(Condition::IfAll(vec![Ok(lhs), Ok(rhs)])), + (Some(lhs), Some(rhs)) => Some(Condition::IfAll(vec![lhs, rhs])), }) } @@ -394,13 +397,13 @@ where Some(Condition::IfAny(lhs)) } // If only one side is an IfAny, add the other Condition to it - (constraint, Some(Condition::IfAny(mut constraints))) - | (Some(Condition::IfAny(mut constraints)), constraint) => { - constraints.push(Ok(constraint)); - Some(Condition::IfAny(constraints)) + (Some(cond), Some(Condition::IfAny(mut conds))) + | (Some(Condition::IfAny(mut conds)), Some(cond)) => { + conds.push(cond); + Some(Condition::IfAny(conds)) } // Otherwise, both lhs and rhs conditions can be combined in a parent IfAny - (lhs, rhs) => Some(Condition::IfAny(vec![Ok(lhs), Ok(rhs)])), + (Some(lhs), Some(rhs)) => Some(Condition::IfAny(vec![lhs, rhs])), }) } diff --git a/tests/ui/transmutability/alignment/align-fail.stderr b/tests/ui/transmutability/alignment/align-fail.stderr index 8ace98a3ed7..59246fb1b03 100644 --- a/tests/ui/transmutability/alignment/align-fail.stderr +++ b/tests/ui/transmutability/alignment/align-fail.stderr @@ -1,8 +1,8 @@ error[E0277]: `&[u8; 0]` cannot be safely transmuted into `&[u16; 0]` in the defining scope of `assert::Context` --> $DIR/align-fail.rs:22:55 | -LL | ...c [u8; 0], &'static [u16; 0]>(); - | ^^^^^^^^^^^^^^^^^ The minimum alignment of `&[u8; 0]` should be greater than that of `&[u16; 0]`, but it is not +LL | ...tatic [u8; 0], &'static [u16; 0]>(); + | ^^^^^^^^^^^^^^^^^ The minimum alignment of `&[u8; 0]` (1) should be greater than that of `&[u16; 0]` (2) | note: required by a bound in `is_maybe_transmutable` --> $DIR/align-fail.rs:10:14 |
