Skip to content

Commit 5b1a2b8

Browse files
committed
TransmuteFrom: Gracefully handle unnormalized types and normalization errors
Fixes #130413
1 parent c817d5d commit 5b1a2b8

File tree

5 files changed

+68
-2
lines changed

5 files changed

+68
-2
lines changed

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

+8
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
245245
span, "silent safe transmute error"
246246
);
247247
}
248+
GetSafeTransmuteErrorAndReason::Default => {
249+
(err_msg, None)
250+
}
248251
GetSafeTransmuteErrorAndReason::Error {
249252
err_msg,
250253
safe_transmute_explanation,
@@ -2221,6 +2224,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
22212224
) -> GetSafeTransmuteErrorAndReason {
22222225
use rustc_transmute::Answer;
22232226

2227+
if obligation.predicate.has_non_region_param() || obligation.has_non_region_infer() {
2228+
return GetSafeTransmuteErrorAndReason::Default;
2229+
}
2230+
22242231
// Erase regions because layout code doesn't particularly care about regions.
22252232
let trait_ref =
22262233
self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_ref));
@@ -2243,6 +2250,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
22432250

22442251
let dst = trait_ref.args.type_at(0);
22452252
let src = trait_ref.args.type_at(1);
2253+
22462254
let err_msg = format!("`{src}` cannot be safely transmuted into `{dst}`");
22472255

22482256
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(

compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub struct ImplCandidate<'tcx> {
4343

4444
enum GetSafeTransmuteErrorAndReason {
4545
Silent,
46+
Default,
4647
Error { err_msg: String, safe_transmute_explanation: Option<String> },
4748
}
4849

compiler/rustc_transmute/src/layout/tree.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,11 @@ pub(crate) mod rustc {
195195
impl<'tcx> From<&LayoutError<'tcx>> for Err {
196196
fn from(err: &LayoutError<'tcx>) -> Self {
197197
match err {
198-
LayoutError::Unknown(..) | LayoutError::ReferencesError(..) => Self::UnknownLayout,
198+
LayoutError::Unknown(..)
199+
| LayoutError::ReferencesError(..)
200+
| LayoutError::NormalizationFailure(..) => Self::UnknownLayout,
199201
LayoutError::SizeOverflow(..) => Self::SizeOverflow,
200202
LayoutError::Cycle(err) => Self::TypeError(*err),
201-
err => unimplemented!("{:?}", err),
202203
}
203204
}
204205
}
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#![crate_type = "lib"]
2+
#![feature(transmutability)]
3+
4+
trait A {
5+
type AssocA;
6+
}
7+
8+
trait B {
9+
type AssocB: std::mem::TransmuteFrom<()>;
10+
}
11+
12+
impl<T> B for (T, u8)
13+
where
14+
T: A,
15+
{
16+
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]
17+
}
18+
19+
20+
impl<T> B for (T, u16)
21+
where
22+
for<'a> &'a i32: A,
23+
{
24+
type AssocB = <&'static i32 as A>::AssocA; //~ERROR: `()` cannot be safely transmuted into `<&i32 as A>::AssocA`
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error[E0277]: the trait bound `<T as A>::AssocA: TransmuteFrom<(), Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not satisfied
2+
--> $DIR/assoc-bound.rs:16:19
3+
|
4+
LL | type AssocB = T::AssocA;
5+
| ^^^^^^^^^ the trait `TransmuteFrom<(), Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `<T as A>::AssocA`
6+
|
7+
note: required by a bound in `B::AssocB`
8+
--> $DIR/assoc-bound.rs:9:18
9+
|
10+
LL | type AssocB: std::mem::TransmuteFrom<()>;
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `B::AssocB`
12+
help: consider further restricting the associated type
13+
|
14+
LL | T: A, <T as A>::AssocA: TransmuteFrom<(), Assume { alignment: false, lifetimes: false, safety: false, validity: false }>
15+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16+
17+
error[E0277]: `()` cannot be safely transmuted into `<&i32 as A>::AssocA`
18+
--> $DIR/assoc-bound.rs:24:19
19+
|
20+
LL | type AssocB = <&'static i32 as A>::AssocA;
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<&i32 as A>::AssocA` has an unknown layout
22+
|
23+
note: required by a bound in `B::AssocB`
24+
--> $DIR/assoc-bound.rs:9:18
25+
|
26+
LL | type AssocB: std::mem::TransmuteFrom<()>;
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `B::AssocB`
28+
29+
error: aborting due to 2 previous errors
30+
31+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)