Skip to content

Commit

Permalink
Rollup merge of #131112 - jswrenn:fix-130413, r=compiler-errors
Browse files Browse the repository at this point in the history
TransmuteFrom: Gracefully handle unnormalized types and normalization errors

~~Refactor to share code between `TransmuteFrom`'s trait selection and error reporting code paths. Additionally normalizes the source and destination types, and gracefully handles normalization errors.~~

Fixes #130413

r​? `@compiler-errors`
  • Loading branch information
matthiaskrgr authored Oct 3, 2024
2 parents 0d65f12 + bc5f952 commit 33b4947
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -2226,6 +2229,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
) -> GetSafeTransmuteErrorAndReason {
use rustc_transmute::Answer;

// We don't assemble a transmutability candidate for types that are generic
// and we should have ambiguity for types that still have non-region infer.
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));
Expand All @@ -2248,6 +2257,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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub struct ImplCandidate<'tcx> {

enum GetSafeTransmuteErrorAndReason {
Silent,
Default,
Error { err_msg: String, safe_transmute_explanation: Option<String> },
}

Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_transmute/src/layout/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
}
}
Expand Down
8 changes: 0 additions & 8 deletions tests/crashes/125881.rs

This file was deleted.

29 changes: 0 additions & 29 deletions tests/crashes/126377.rs

This file was deleted.

17 changes: 0 additions & 17 deletions tests/crashes/130413.rs

This file was deleted.

25 changes: 25 additions & 0 deletions tests/ui/transmutability/assoc-bound.rs
Original file line number Diff line number Diff line change
@@ -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`
}
31 changes: 31 additions & 0 deletions tests/ui/transmutability/assoc-bound.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 33b4947

Please sign in to comment.