about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJack Wrenn <jack@wrenn.fyi>2024-10-01 20:52:17 +0000
committerJack Wrenn <jack@wrenn.fyi>2024-10-01 20:52:17 +0000
commit5b1a2b8712887fff7e0295d4e87aac24ea73797d (patch)
treefb239e7960f1ef675abe4a278e88bb1393339584
parentc817d5dc2050ec443516f9700c19b1419593a83d (diff)
downloadrust-5b1a2b8712887fff7e0295d4e87aac24ea73797d.tar.gz
rust-5b1a2b8712887fff7e0295d4e87aac24ea73797d.zip
TransmuteFrom: Gracefully handle unnormalized types and normalization errors
Fixes #130413
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs8
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs1
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs5
-rw-r--r--tests/ui/transmutability/assoc-bound.rs25
-rw-r--r--tests/ui/transmutability/assoc-bound.stderr31
5 files changed, 68 insertions, 2 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 34a0f182ab4..f494d9637f3 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -245,6 +245,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                         span, "silent safe transmute error"
                                     );
                                 }
+                                GetSafeTransmuteErrorAndReason::Default => {
+                                    (err_msg, None)
+                                }
                                 GetSafeTransmuteErrorAndReason::Error {
                                     err_msg,
                                     safe_transmute_explanation,
@@ -2221,6 +2224,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     ) -> GetSafeTransmuteErrorAndReason {
         use rustc_transmute::Answer;
 
+        if obligation.predicate.has_non_region_param() || obligation.has_non_region_infer() {
+            return GetSafeTransmuteErrorAndReason::Default;
+        }
+
         // Erase regions because layout code doesn't particularly care about regions.
         let trait_ref =
             self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_ref));
@@ -2243,6 +2250,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
         let dst = trait_ref.args.type_at(0);
         let src = trait_ref.args.type_at(1);
+
         let err_msg = format!("`{src}` cannot be safely transmuted into `{dst}`");
 
         match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
index 109bae10b54..becc1acfb66 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
@@ -43,6 +43,7 @@ pub struct ImplCandidate<'tcx> {
 
 enum GetSafeTransmuteErrorAndReason {
     Silent,
+    Default,
     Error { err_msg: String, safe_transmute_explanation: Option<String> },
 }
 
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 6d5859a5a65..17eddbfcd7f 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -195,10 +195,11 @@ pub(crate) mod rustc {
     impl<'tcx> From<&LayoutError<'tcx>> for Err {
         fn from(err: &LayoutError<'tcx>) -> Self {
             match err {
-                LayoutError::Unknown(..) | LayoutError::ReferencesError(..) => Self::UnknownLayout,
+                LayoutError::Unknown(..)
+                | LayoutError::ReferencesError(..)
+                | LayoutError::NormalizationFailure(..) => Self::UnknownLayout,
                 LayoutError::SizeOverflow(..) => Self::SizeOverflow,
                 LayoutError::Cycle(err) => Self::TypeError(*err),
-                err => unimplemented!("{:?}", err),
             }
         }
     }
diff --git a/tests/ui/transmutability/assoc-bound.rs b/tests/ui/transmutability/assoc-bound.rs
new file mode 100644
index 00000000000..e8a20b45cde
--- /dev/null
+++ b/tests/ui/transmutability/assoc-bound.rs
@@ -0,0 +1,25 @@
+#![crate_type = "lib"]
+#![feature(transmutability)]
+
+trait A {
+    type AssocA;
+}
+
+trait B {
+    type AssocB: std::mem::TransmuteFrom<()>;
+}
+
+impl<T> B for (T, u8)
+where
+    T: A,
+{
+    type AssocB = T::AssocA; //~ERROR: the trait bound `<T as A>::AssocA: TransmuteFrom<(), Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not satisfied [E0277]
+}
+
+
+impl<T> B for (T, u16)
+where
+    for<'a> &'a i32: A,
+{
+    type AssocB = <&'static i32 as A>::AssocA; //~ERROR: `()` cannot be safely transmuted into `<&i32 as A>::AssocA`
+}
diff --git a/tests/ui/transmutability/assoc-bound.stderr b/tests/ui/transmutability/assoc-bound.stderr
new file mode 100644
index 00000000000..08d90894396
--- /dev/null
+++ b/tests/ui/transmutability/assoc-bound.stderr
@@ -0,0 +1,31 @@
+error[E0277]: the trait bound `<T as A>::AssocA: TransmuteFrom<(), Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not satisfied
+  --> $DIR/assoc-bound.rs:16:19
+   |
+LL |     type AssocB = T::AssocA;
+   |                   ^^^^^^^^^ the trait `TransmuteFrom<(), Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `<T as A>::AssocA`
+   |
+note: required by a bound in `B::AssocB`
+  --> $DIR/assoc-bound.rs:9:18
+   |
+LL |     type AssocB: std::mem::TransmuteFrom<()>;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `B::AssocB`
+help: consider further restricting the associated type
+   |
+LL |     T: A, <T as A>::AssocA: TransmuteFrom<(), Assume { alignment: false, lifetimes: false, safety: false, validity: false }>
+   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0277]: `()` cannot be safely transmuted into `<&i32 as A>::AssocA`
+  --> $DIR/assoc-bound.rs:24:19
+   |
+LL |     type AssocB = <&'static i32 as A>::AssocA;
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<&i32 as A>::AssocA` has an unknown layout
+   |
+note: required by a bound in `B::AssocB`
+  --> $DIR/assoc-bound.rs:9:18
+   |
+LL |     type AssocB: std::mem::TransmuteFrom<()>;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `B::AssocB`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.