diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2022-10-08 14:38:18 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-10-08 14:38:18 +0200 |
| commit | 6bcdf8aa7435a3c72a7ea3f5e54b67f5faec9264 (patch) | |
| tree | d515261fb8e1e3860c945e506182d0f4b4e943cb | |
| parent | a688a0305fad9219505a8f2576446510601bafe8 (diff) | |
| parent | d90d055691267447f319b0f240bfe60cacb1d266 (diff) | |
Rollup merge of #101520 - oli-obk:transmute_lifetimes, r=compiler-errors
Allow transmutes between the same types after erasing lifetimes r? ````@compiler-errors```` on the impl fixes #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
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/intrinsicck.rs | 20 | ||||
| -rw-r--r-- | src/test/ui/transmute-equal-assoc-types.rs | 4 | ||||
| -rw-r--r-- | src/test/ui/transmute-equal-assoc-types.stderr | 11 | ||||
| -rw-r--r-- | src/test/ui/transmute/lifetimes.rs | 23 | ||||
| -rw-r--r-- | src/test/ui/transmute/main.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/transmute/main.stderr | 10 |
6 files changed, 43 insertions, 27 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 4abc00cefb6..25228f424cd 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -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) { diff --git a/src/test/ui/transmute-equal-assoc-types.rs b/src/test/ui/transmute-equal-assoc-types.rs index 6f357543e5c..d1b593b7f0a 100644 --- a/src/test/ui/transmute-equal-assoc-types.rs +++ b/src/test/ui/transmute-equal-assoc-types.rs @@ -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() {} diff --git a/src/test/ui/transmute-equal-assoc-types.stderr b/src/test/ui/transmute-equal-assoc-types.stderr deleted file mode 100644 index ce7657f9640..00000000000 --- a/src/test/ui/transmute-equal-assoc-types.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-equal-assoc-types.rs:6:5 - | -LL | ::std::mem::transmute(foo) - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: `<F as Foo>::Bar` does not have a fixed size - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0512`. diff --git a/src/test/ui/transmute/lifetimes.rs b/src/test/ui/transmute/lifetimes.rs new file mode 100644 index 00000000000..94319155139 --- /dev/null +++ b/src/test/ui/transmute/lifetimes.rs @@ -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() {} diff --git a/src/test/ui/transmute/main.rs b/src/test/ui/transmute/main.rs index cb46fc5ec46..da4a0a660c8 100644 --- a/src/test/ui/transmute/main.rs +++ b/src/test/ui/transmute/main.rs @@ -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() { diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr index d519f03682b..6cb0d7f67e0 100644 --- a/src/test/ui/transmute/main.stderr +++ b/src/test/ui/transmute/main.stderr @@ -1,12 +1,4 @@ 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 | LL | let x: u8 = transmute(10u16); @@ -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`. |
