Auto merge of #115810 - nnethercote:folding-comments, r=WaffleLapkin
Folding comments r? `@WaffleLapkin`
This commit is contained in:
commit
38a16ef731
3 changed files with 20 additions and 15 deletions
|
@ -33,14 +33,6 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
|
|||
}
|
||||
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
// N.B. Even though this uses a visitor, the visitor does not actually
|
||||
// recurse through the whole `TypeVisitable` implementor type.
|
||||
//
|
||||
// Instead it stops on the first "level", visiting types, regions,
|
||||
// consts and predicates just fetches their type flags.
|
||||
//
|
||||
// Thus this is a lot faster than it might seem and should be
|
||||
// optimized to a simple field access.
|
||||
let res =
|
||||
self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags);
|
||||
trace!(?self, ?flags, ?res, "has_type_flags");
|
||||
|
@ -485,11 +477,16 @@ impl std::fmt::Debug for HasTypeFlagsVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
// Note: this visitor traverses values down to the level of
|
||||
// `Ty`/`Const`/`Predicate`, but not within those types. This is because the
|
||||
// type flags at the outer layer are enough. So it's faster than it first
|
||||
// looks, particular for `Ty`/`Predicate` where it's just a field access.
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
|
||||
type BreakTy = FoundFlags;
|
||||
|
||||
#[inline]
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// Note: no `super_visit_with` call.
|
||||
let flags = t.flags();
|
||||
if flags.intersects(self.flags) {
|
||||
ControlFlow::Break(FoundFlags)
|
||||
|
@ -500,6 +497,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
|
|||
|
||||
#[inline]
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// Note: no `super_visit_with` call, as usual for `Region`.
|
||||
let flags = r.type_flags();
|
||||
if flags.intersects(self.flags) {
|
||||
ControlFlow::Break(FoundFlags)
|
||||
|
@ -510,6 +508,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
|
|||
|
||||
#[inline]
|
||||
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// Note: no `super_visit_with` call.
|
||||
let flags = FlagComputation::for_const(c);
|
||||
trace!(r.flags=?flags);
|
||||
if flags.intersects(self.flags) {
|
||||
|
@ -521,6 +520,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
|
|||
|
||||
#[inline]
|
||||
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// Note: no `super_visit_with` call.
|
||||
if predicate.flags().intersects(self.flags) {
|
||||
ControlFlow::Break(FoundFlags)
|
||||
} else {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
//! modification. These are the ones containing the most important type-related
|
||||
//! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
|
||||
//!
|
||||
//! There are three groups of traits involved in each traversal.
|
||||
//! There are three traits involved in each traversal.
|
||||
//! - `TypeFoldable`. This is implemented once for many types, including:
|
||||
//! - Types of interest, for which the methods delegate to the folder.
|
||||
//! - All other types, including generic containers like `Vec` and `Option`.
|
||||
|
@ -51,6 +51,12 @@ use crate::{visit::TypeVisitable, Interner};
|
|||
///
|
||||
/// To implement this conveniently, use the derive macro located in
|
||||
/// `rustc_macros`.
|
||||
///
|
||||
/// This trait is a sub-trait of `TypeVisitable`. This is because many
|
||||
/// `TypeFolder` instances use the methods in `TypeVisitableExt` while folding,
|
||||
/// which means in practice almost every foldable type needs to also be
|
||||
/// visitable. (However, there are some types that are visitable without being
|
||||
/// foldable.)
|
||||
pub trait TypeFoldable<I: Interner>: TypeVisitable<I> {
|
||||
/// The entry point for folding. To fold a value `t` with a folder `f`
|
||||
/// call: `t.try_fold_with(f)`.
|
||||
|
@ -58,7 +64,7 @@ pub trait TypeFoldable<I: Interner>: TypeVisitable<I> {
|
|||
/// For most types, this just traverses the value, calling `try_fold_with`
|
||||
/// on each field/element.
|
||||
///
|
||||
/// For types of interest (such as `Ty`), the implementation of method
|
||||
/// For types of interest (such as `Ty`), the implementation of this method
|
||||
/// calls a folder method specifically for that type (such as
|
||||
/// `F::try_fold_ty`). This is where control transfers from `TypeFoldable`
|
||||
/// to `TypeFolder`.
|
||||
|
@ -121,7 +127,7 @@ pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = !> {
|
|||
}
|
||||
|
||||
// The default region folder is a no-op because `Region` is non-recursive
|
||||
// and has no `super_visit_with` method to call. That also explains the
|
||||
// and has no `super_fold_with` method to call. That also explains the
|
||||
// lack of `I::Region: TypeSuperFoldable<I>` bound on this method.
|
||||
fn fold_region(&mut self, r: I::Region) -> I::Region {
|
||||
r
|
||||
|
@ -170,7 +176,7 @@ pub trait FallibleTypeFolder<I: Interner>: Sized {
|
|||
}
|
||||
|
||||
// The default region folder is a no-op because `Region` is non-recursive
|
||||
// and has no `super_visit_with` method to call. That also explains the
|
||||
// and has no `super_fold_with` method to call. That also explains the
|
||||
// lack of `I::Region: TypeSuperFoldable<I>` bound on this method.
|
||||
fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, Self::Error> {
|
||||
Ok(r)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
//! visitation. These are the ones containing the most important type-related
|
||||
//! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
|
||||
//!
|
||||
//! There are three groups of traits involved in each traversal.
|
||||
//! There are three traits involved in each traversal.
|
||||
//! - `TypeVisitable`. This is implemented once for many types, including:
|
||||
//! - Types of interest, for which the methods delegate to the visitor.
|
||||
//! - All other types, including generic containers like `Vec` and `Option`.
|
||||
|
@ -17,7 +17,6 @@
|
|||
//! interest, and defines the visiting "skeleton" for these types. (This
|
||||
//! excludes `Region` because it is non-recursive, i.e. it never contains
|
||||
//! other types of interest.)
|
||||
//!
|
||||
//! - `TypeVisitor`. This is implemented for each visitor. This defines how
|
||||
//! types of interest are visited.
|
||||
//!
|
||||
|
@ -60,7 +59,7 @@ pub trait TypeVisitable<I: Interner>: fmt::Debug + Clone {
|
|||
///
|
||||
/// For types of interest (such as `Ty`), the implementation of this method
|
||||
/// that calls a visitor method specifically for that type (such as
|
||||
/// `V::visit_ty`). This is where control transfers from `TypeFoldable` to
|
||||
/// `V::visit_ty`). This is where control transfers from `TypeVisitable` to
|
||||
/// `TypeVisitor`.
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue