about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBryan Garza <1396101+bryangarza@users.noreply.github.com>2023-05-24 17:47:13 -0700
committerBryan Garza <1396101+bryangarza@users.noreply.github.com>2023-05-24 17:49:56 -0700
commitd2164d5c9a17a7c2eefeccf623c278612b2650de (patch)
treeb1dd74d0baeb833d0da51390c42cd91a8faf702c
parent62663582375d7dedf42c0a30bfe04c7b53b452d7 (diff)
downloadrust-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`
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs26
-rw-r--r--compiler/rustc_transmute/src/lib.rs6
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/mod.rs25
-rw-r--r--tests/ui/transmutability/alignment/align-fail.stderr4
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