1
Fork 0

old solver: improve normalization of Pointee::Metadata

This commit is contained in:
Lukas Markeffsky 2024-02-05 14:54:24 +01:00
parent 77fb540684
commit 0c1f401d98
5 changed files with 113 additions and 39 deletions

View file

@ -1957,12 +1957,12 @@ impl<'tcx> Ty<'tcx> {
}
/// Returns the type of metadata for (potentially fat) pointers to this type,
/// and a boolean signifying if this is conditional on this type being `Sized`.
pub fn ptr_metadata_ty(
/// or the struct tail if the metadata type cannot be determined.
pub fn ptr_metadata_ty_or_tail(
self,
tcx: TyCtxt<'tcx>,
normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
) -> (Ty<'tcx>, bool) {
) -> Result<Ty<'tcx>, Ty<'tcx>> {
let tail = tcx.struct_tail_with_normalize(self, normalize, || {});
match tail.kind() {
// Sized types
@ -1984,31 +1984,47 @@ impl<'tcx> Ty<'tcx> {
| ty::Error(_)
// Extern types have metadata = ().
| ty::Foreign(..)
// `dyn*` has no metadata
// `dyn*` has metadata = ().
| ty::Dynamic(_, _, ty::DynStar)
// If returned by `struct_tail_without_normalization` this is a unit struct
// If returned by `struct_tail_with_normalize` this is a unit struct
// without any fields, or not a struct, and therefore is Sized.
| ty::Adt(..)
// If returned by `struct_tail_without_normalization` this is the empty tuple,
// If returned by `struct_tail_with_normalize` this is the empty tuple,
// a.k.a. unit type, which is Sized
| ty::Tuple(..) => (tcx.types.unit, false),
| ty::Tuple(..) => Ok(tcx.types.unit),
ty::Str | ty::Slice(_) => Ok(tcx.types.usize),
ty::Str | ty::Slice(_) => (tcx.types.usize, false),
ty::Dynamic(_, _, ty::Dyn) => {
let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
(tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()]), false)
},
Ok(tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()]))
}
// type parameters only have unit metadata if they're sized, so return true
// to make sure we double check this during confirmation
ty::Param(_) | ty::Alias(..) => (tcx.types.unit, true),
// We don't know the metadata of `self`, but it must be equal to the
// metadata of `tail`.
ty::Param(_) | ty::Alias(..) => Err(tail),
ty::Infer(ty::TyVar(_))
| ty::Bound(..)
| ty::Placeholder(..)
| ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
bug!("`ptr_metadata_ty` applied to unexpected type: {:?} (tail = {:?})", self, tail)
}
| ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => bug!(
"`ptr_metadata_ty_or_tail` applied to unexpected type: {self:?} (tail = {tail:?})"
),
}
}
/// Returns the type of metadata for (potentially fat) pointers to this type.
/// Causes an ICE if the metadata type cannot be determined.
pub fn ptr_metadata_ty(
self,
tcx: TyCtxt<'tcx>,
normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
) -> Ty<'tcx> {
match self.ptr_metadata_ty_or_tail(tcx, normalize) {
Ok(metadata) => metadata,
Err(tail) => bug!(
"`ptr_metadata_ty` failed to get metadata for type: {self:?} (tail = {tail:?})"
),
}
}