Skip to content

Commit

Permalink
Rollup merge of rust-lang#101520 - oli-obk:transmute_lifetimes, r=com…
Browse files Browse the repository at this point in the history
…piler-errors

Allow transmutes between the same types after erasing lifetimes

r? ```@compiler-errors```  on the impl

fixes rust-lang#101081

See discussion in the issue and at https://rust-lang.zulipchat.com/#narrow/stream/326866-t-types.2Fnominated/topic/.23101081.3A.20Regression.20transmuting.20.60RwLockReadGuard.3CT.3A.20.3FSized.3E.E2.80.A6

I think this may need lang team signoff as its implications may go beyond the jurisdiction of T-types

I'll write up a proper summary later
  • Loading branch information
Dylan-DPC authored Oct 8, 2022
2 parents 3afafca + d90d055 commit ad8e04b
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 27 deletions.
20 changes: 15 additions & 5 deletions compiler/rustc_hir_analysis/src/check/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn check_transmute(&self, from: Ty<'tcx>, to: Ty<'tcx>, hir_id: HirId) {
let tcx = self.tcx;
let span = tcx.hir().span(hir_id);
let convert = |ty: Ty<'tcx>| {
let normalize = |ty| {
let ty = self.resolve_vars_if_possible(ty);
let ty = tcx.normalize_erasing_regions(self.param_env, ty);
(SizeSkeleton::compute(ty, tcx, self.param_env), ty)
self.tcx.normalize_erasing_regions(self.param_env, ty)
};
let (sk_from, from) = convert(from);
let (sk_to, to) = convert(to);
let from = normalize(from);
let to = normalize(to);
trace!(?from, ?to);

// Transmutes that are only changing lifetimes are always ok.
if from == to {
return;
}

let skel = |ty| SizeSkeleton::compute(ty, tcx, self.param_env);
let sk_from = skel(from);
let sk_to = skel(to);
trace!(?sk_from, ?sk_to);

// Check for same size using the skeletons.
if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) {
Expand Down
4 changes: 3 additions & 1 deletion src/test/ui/transmute-equal-assoc-types.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// check-pass

trait Foo {
type Bar;
}

unsafe fn noop<F: Foo>(foo: F::Bar) -> F::Bar {
::std::mem::transmute(foo) //~ ERROR cannot transmute between types of different sizes
::std::mem::transmute(foo)
}

fn main() {}
11 changes: 0 additions & 11 deletions src/test/ui/transmute-equal-assoc-types.stderr

This file was deleted.

23 changes: 23 additions & 0 deletions src/test/ui/transmute/lifetimes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// check-pass

use std::ptr::NonNull;

struct Foo<'a, T: ?Sized>(&'a (), NonNull<T>);

fn foo<'a, 'b, T: ?Sized>(x: Foo<'a, T>) -> Foo<'b, T> {
unsafe { std::mem::transmute(x) }
}

struct Bar<'a, T: ?Sized>(&'a T);

fn bar<'a, 'b, T: ?Sized>(x: Bar<'a, T>) -> Bar<'b, T> {
unsafe { std::mem::transmute(x) }
}

struct Boo<'a, T: ?Sized>(&'a T, u32);

fn boo<'a, 'b, T: ?Sized>(x: Boo<'a, T>) -> Boo<'b, T> {
unsafe { std::mem::transmute(x) }
}

fn main() {}
2 changes: 1 addition & 1 deletion src/test/ui/transmute/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub trait TypeConstructor<'a> {
unsafe fn transmute_lifetime<'a, 'b, C>(x: <C as TypeConstructor<'a>>::T)
-> <C as TypeConstructor<'b>>::T
where for<'z> C: TypeConstructor<'z> {
transmute(x) //~ ERROR cannot transmute between types of different sizes
transmute(x)
}

unsafe fn sizes() {
Expand Down
10 changes: 1 addition & 9 deletions src/test/ui/transmute/main.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/main.rs:13:5
|
LL | transmute(x)
| ^^^^^^^^^
|
= note: `<C as TypeConstructor<'_>>::T` does not have a fixed size

error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/main.rs:17:17
|
Expand Down Expand Up @@ -33,6 +25,6 @@ LL | let x: Foo = transmute(10);
= note: source type: `i32` (32 bits)
= note: target type: `Foo` (0 bits)

error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0512`.

0 comments on commit ad8e04b

Please sign in to comment.