Move folding and visiting traits into type library
This commit is contained in:
parent
9fa6bb2aa0
commit
459e142413
10 changed files with 805 additions and 755 deletions
|
@ -1,20 +1,19 @@
|
|||
//! This module contains implements of the `Lift` and `TypeFoldable`
|
||||
//! traits for various types in the Rust compiler. Most are written by
|
||||
//! hand, though we've recently added some macros and proc-macros to help with the tedium.
|
||||
//! This module contains implementations of the `Lift`, `TypeFoldable` and
|
||||
//! `TypeVisitable` traits for various types in the Rust compiler. Most are
|
||||
//! written by hand, though we've recently added some macros and proc-macros
|
||||
//! to help with the tedium.
|
||||
|
||||
use crate::mir::interpret;
|
||||
use crate::mir::{Field, ProjectionKind};
|
||||
use crate::ty::fold::{ir::TypeSuperFoldable, FallibleTypeFolder, TypeFoldable};
|
||||
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
|
||||
use crate::ty::visit::{ir::TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
||||
use crate::ty::{self, ir, AliasTy, InferConst, Interner, Lift, Term, TermKind, Ty, TyCtxt};
|
||||
use rustc_data_structures::functor::IdFunctor;
|
||||
use crate::ty::{self, ir, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
|
||||
use rustc_hir::def::Namespace;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_target::abi::TyAndLayout;
|
||||
|
||||
use std::fmt;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::ops::ControlFlow;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
@ -195,17 +194,27 @@ impl<'tcx> fmt::Debug for AliasTy<'tcx> {
|
|||
// Atomic structs
|
||||
//
|
||||
// For things that don't carry any arena-allocated data (and are
|
||||
// copy...), just add them to this list.
|
||||
// copy...), just add them to one of these lists as appropriat.
|
||||
|
||||
TrivialTypeTraversalAndLiftImpls! {
|
||||
// For things for which the type library provides traversal implementations
|
||||
// for all Interners, we only need to provide a Lift implementation:
|
||||
CloneLiftImpls! {
|
||||
(),
|
||||
bool,
|
||||
usize,
|
||||
::rustc_target::abi::VariantIdx,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
String,
|
||||
rustc_type_ir::DebruijnIndex,
|
||||
}
|
||||
|
||||
// For things about which the type library does not know, or does not
|
||||
// provide any traversal implementations, we need to provide both a Lift
|
||||
// implementation and traversal implementations (the latter only for
|
||||
// TyCtxt<'_> interners).
|
||||
TrivialTypeTraversalAndLiftImpls! {
|
||||
::rustc_target::abi::VariantIdx,
|
||||
crate::middle::region::Scope,
|
||||
crate::ty::FloatTy,
|
||||
::rustc_ast::InlineAsmOptions,
|
||||
|
@ -257,7 +266,6 @@ TrivialTypeTraversalAndLiftImpls! {
|
|||
Field,
|
||||
interpret::Scalar,
|
||||
rustc_target::abi::Size,
|
||||
rustc_type_ir::DebruijnIndex,
|
||||
ty::BoundVar,
|
||||
ty::Placeholder<ty::BoundVar>,
|
||||
}
|
||||
|
@ -360,7 +368,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> {
|
|||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// TypeFoldable implementations.
|
||||
// Traversal implementations.
|
||||
|
||||
/// AdtDefs are basically the same as a DefId.
|
||||
impl<'tcx> ir::TypeFoldable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
|
||||
|
@ -375,209 +383,6 @@ impl<'tcx> ir::TypeVisitable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeFoldable<I>, U: ir::TypeFoldable<I>> ir::TypeFoldable<I> for (T, U) {
|
||||
fn try_fold_with<F: ir::FallibleTypeFolder<I>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<(T, U), F::Error> {
|
||||
Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeVisitable<I>, U: ir::TypeVisitable<I>> ir::TypeVisitable<I>
|
||||
for (T, U)
|
||||
{
|
||||
fn visit_with<V: ir::TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.0.visit_with(visitor)?;
|
||||
self.1.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, A: ir::TypeFoldable<I>, B: ir::TypeFoldable<I>, C: ir::TypeFoldable<I>>
|
||||
ir::TypeFoldable<I> for (A, B, C)
|
||||
{
|
||||
fn try_fold_with<F: ir::FallibleTypeFolder<I>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<(A, B, C), F::Error> {
|
||||
Ok((
|
||||
self.0.try_fold_with(folder)?,
|
||||
self.1.try_fold_with(folder)?,
|
||||
self.2.try_fold_with(folder)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, A: ir::TypeVisitable<I>, B: ir::TypeVisitable<I>, C: ir::TypeVisitable<I>>
|
||||
ir::TypeVisitable<I> for (A, B, C)
|
||||
{
|
||||
fn visit_with<V: ir::TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.0.visit_with(visitor)?;
|
||||
self.1.visit_with(visitor)?;
|
||||
self.2.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
EnumTypeTraversalImpl! {
|
||||
impl<I, T> TypeFoldable<I> for Option<T> {
|
||||
(Some)(a),
|
||||
(None),
|
||||
} where I: Interner, T: ir::TypeFoldable<I>
|
||||
}
|
||||
EnumTypeTraversalImpl! {
|
||||
impl<I, T> TypeVisitable<I> for Option<T> {
|
||||
(Some)(a),
|
||||
(None),
|
||||
} where I: Interner, T: ir::TypeVisitable<I>
|
||||
}
|
||||
|
||||
EnumTypeTraversalImpl! {
|
||||
impl<I, T, E> TypeFoldable<I> for Result<T, E> {
|
||||
(Ok)(a),
|
||||
(Err)(a),
|
||||
} where I: Interner, T: ir::TypeFoldable<I>, E: ir::TypeFoldable<I>,
|
||||
}
|
||||
EnumTypeTraversalImpl! {
|
||||
impl<I, T, E> TypeVisitable<I> for Result<T, E> {
|
||||
(Ok)(a),
|
||||
(Err)(a),
|
||||
} where I: Interner, T: ir::TypeVisitable<I>, E: ir::TypeVisitable<I>,
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeFoldable<I>> ir::TypeFoldable<I> for Rc<T> {
|
||||
fn try_fold_with<F: ir::FallibleTypeFolder<I>>(
|
||||
mut self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
// We merely want to replace the contained `T`, if at all possible,
|
||||
// so that we don't needlessly allocate a new `Rc` or indeed clone
|
||||
// the contained type.
|
||||
unsafe {
|
||||
// First step is to ensure that we have a unique reference to
|
||||
// the contained type, which `Rc::make_mut` will accomplish (by
|
||||
// allocating a new `Rc` and cloning the `T` only if required).
|
||||
// This is done *before* casting to `Rc<ManuallyDrop<T>>` so that
|
||||
// panicking during `make_mut` does not leak the `T`.
|
||||
Rc::make_mut(&mut self);
|
||||
|
||||
// Casting to `Rc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
|
||||
// is `repr(transparent)`.
|
||||
let ptr = Rc::into_raw(self).cast::<ManuallyDrop<T>>();
|
||||
let mut unique = Rc::from_raw(ptr);
|
||||
|
||||
// Call to `Rc::make_mut` above guarantees that `unique` is the
|
||||
// sole reference to the contained value, so we can avoid doing
|
||||
// a checked `get_mut` here.
|
||||
let slot = Rc::get_mut_unchecked(&mut unique);
|
||||
|
||||
// Semantically move the contained type out from `unique`, fold
|
||||
// it, then move the folded value back into `unique`. Should
|
||||
// folding fail, `ManuallyDrop` ensures that the "moved-out"
|
||||
// value is not re-dropped.
|
||||
let owned = ManuallyDrop::take(slot);
|
||||
let folded = owned.try_fold_with(folder)?;
|
||||
*slot = ManuallyDrop::new(folded);
|
||||
|
||||
// Cast back to `Rc<T>`.
|
||||
Ok(Rc::from_raw(Rc::into_raw(unique).cast()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeVisitable<I>> ir::TypeVisitable<I> for Rc<T> {
|
||||
fn visit_with<V: ir::TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
(**self).visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeFoldable<I>> ir::TypeFoldable<I> for Arc<T> {
|
||||
fn try_fold_with<F: ir::FallibleTypeFolder<I>>(
|
||||
mut self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
// We merely want to replace the contained `T`, if at all possible,
|
||||
// so that we don't needlessly allocate a new `Arc` or indeed clone
|
||||
// the contained type.
|
||||
unsafe {
|
||||
// First step is to ensure that we have a unique reference to
|
||||
// the contained type, which `Arc::make_mut` will accomplish (by
|
||||
// allocating a new `Arc` and cloning the `T` only if required).
|
||||
// This is done *before* casting to `Arc<ManuallyDrop<T>>` so that
|
||||
// panicking during `make_mut` does not leak the `T`.
|
||||
Arc::make_mut(&mut self);
|
||||
|
||||
// Casting to `Arc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
|
||||
// is `repr(transparent)`.
|
||||
let ptr = Arc::into_raw(self).cast::<ManuallyDrop<T>>();
|
||||
let mut unique = Arc::from_raw(ptr);
|
||||
|
||||
// Call to `Arc::make_mut` above guarantees that `unique` is the
|
||||
// sole reference to the contained value, so we can avoid doing
|
||||
// a checked `get_mut` here.
|
||||
let slot = Arc::get_mut_unchecked(&mut unique);
|
||||
|
||||
// Semantically move the contained type out from `unique`, fold
|
||||
// it, then move the folded value back into `unique`. Should
|
||||
// folding fail, `ManuallyDrop` ensures that the "moved-out"
|
||||
// value is not re-dropped.
|
||||
let owned = ManuallyDrop::take(slot);
|
||||
let folded = owned.try_fold_with(folder)?;
|
||||
*slot = ManuallyDrop::new(folded);
|
||||
|
||||
// Cast back to `Arc<T>`.
|
||||
Ok(Arc::from_raw(Arc::into_raw(unique).cast()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeVisitable<I>> ir::TypeVisitable<I> for Arc<T> {
|
||||
fn visit_with<V: ir::TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
(**self).visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeFoldable<I>> ir::TypeFoldable<I> for Box<T> {
|
||||
fn try_fold_with<F: ir::FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
self.try_map_id(|value| value.try_fold_with(folder))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeVisitable<I>> ir::TypeVisitable<I> for Box<T> {
|
||||
fn visit_with<V: ir::TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
(**self).visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeFoldable<I>> ir::TypeFoldable<I> for Vec<T> {
|
||||
fn try_fold_with<F: ir::FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
self.try_map_id(|t| t.try_fold_with(folder))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeVisitable<I>> ir::TypeVisitable<I> for Vec<T> {
|
||||
fn visit_with<V: ir::TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeVisitable<I>> ir::TypeVisitable<I> for &[T] {
|
||||
fn visit_with<V: ir::TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeFoldable<I>> ir::TypeFoldable<I> for Box<[T]> {
|
||||
fn try_fold_with<F: ir::FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
self.try_map_id(|t| t.try_fold_with(folder))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeVisitable<I>> ir::TypeVisitable<I> for Box<[T]> {
|
||||
fn visit_with<V: ir::TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> ir::TypeFoldable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
folder.try_fold_binder(self)
|
||||
|
@ -790,18 +595,6 @@ impl<'tcx> ir::TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Predicate<'tcx>
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeFoldable<I>, Ix: Idx> ir::TypeFoldable<I> for IndexVec<Ix, T> {
|
||||
fn try_fold_with<F: ir::FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
self.try_map_id(|x| x.try_fold_with(folder))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: ir::TypeVisitable<I>, Ix: Idx> ir::TypeVisitable<I> for IndexVec<Ix, T> {
|
||||
fn visit_with<V: ir::TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ir::TypeFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
folder.try_fold_const(self)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue