diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_middle/src/mir/tcx.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 28 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/gvn.rs | 19 |
3 files changed, 34 insertions, 27 deletions
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 126387db1d9..412cfc1fc7a 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -289,19 +289,7 @@ impl<'tcx> UnOp { pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> { match self { UnOp::Not | UnOp::Neg => arg_ty, - UnOp::PtrMetadata => { - let pointee_ty = arg_ty - .builtin_deref(true) - .unwrap_or_else(|| bug!("PtrMetadata of non-dereferenceable ty {arg_ty:?}")); - if pointee_ty.is_trivially_sized(tcx) { - tcx.types.unit - } else { - let Some(metadata_def_id) = tcx.lang_items().metadata_type() else { - bug!("No metadata_type lang item while looking at {arg_ty:?}") - }; - Ty::new_projection(tcx, metadata_def_id, [pointee_ty]) - } - } + UnOp::PtrMetadata => arg_ty.pointee_metadata_ty_or_projection(tcx), } } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9c8a3484aa5..709c5fe2305 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1638,6 +1638,34 @@ impl<'tcx> Ty<'tcx> { } } + /// Given a pointer or reference type, returns the type of the *pointee*'s + /// metadata. If it can't be determined exactly (perhaps due to still + /// being generic) then a projection through `ptr::Pointee` will be returned. + /// + /// This is particularly useful for getting the type of the result of + /// [`UnOp::PtrMetadata`](crate::mir::UnOp::PtrMetadata). + /// + /// Panics if `self` is not dereferencable. + #[track_caller] + pub fn pointee_metadata_ty_or_projection(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + let Some(pointee_ty) = self.builtin_deref(true) else { + bug!("Type {self:?} is not a pointer or reference type") + }; + if pointee_ty.is_trivially_sized(tcx) { + tcx.types.unit + } else { + match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) { + Ok(metadata_ty) => metadata_ty, + Err(tail_ty) => { + let Some(metadata_def_id) = tcx.lang_items().metadata_type() else { + bug!("No metadata_type lang item while looking at {self:?}") + }; + Ty::new_projection(tcx, metadata_def_id, [tail_ty]) + } + } + } + } + /// When we create a closure, we record its kind (i.e., what trait /// it implements, constrained by how it uses its borrows) into its /// [`ty::ClosureArgs`] or [`ty::CoroutineClosureArgs`] using a type diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index bfdefd5a7d6..23124523f17 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -987,23 +987,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // `*const [T]` -> `*const T` which remove metadata. // We run on potentially-generic MIR, though, so unlike codegen // we can't always know exactly what the metadata are. - // Thankfully, equality on `ptr_metadata_ty_or_tail` gives us - // what we need: `Ok(meta_ty)` if the metadata is known, or - // `Err(tail_ty)` if not. Matching metadata is ok, but if - // that's not known, then matching tail types is also ok, - // allowing things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`. + // To allow things like `*mut (?A, ?T)` <-> `*mut (?B, ?T)`, + // it's fine to get a projection as the type. // FIXME: Would it be worth trying to normalize, rather than - // passing the identity closure? Or are the types in the + // just accepting the projection? Or are the types in the // Cast realistically about as normalized as we can get anyway? Value::Cast { kind: CastKind::PtrToPtr, value: inner, from, to } - if from - .builtin_deref(true) - .unwrap() - .ptr_metadata_ty_or_tail(self.tcx, |t| t) - == to - .builtin_deref(true) - .unwrap() - .ptr_metadata_ty_or_tail(self.tcx, |t| t) => + if from.pointee_metadata_ty_or_projection(self.tcx) + == to.pointee_metadata_ty_or_projection(self.tcx) => { arg_index = *inner; was_updated = true; |
