summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/ty/visit.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/ty/visit.rs')
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs135
1 files changed, 22 insertions, 113 deletions
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index bee3cc4d7..6814cadb9 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -1,69 +1,13 @@
-//! A visiting traversal mechanism for complex data structures that contain type
-//! information.
-//!
-//! This is a read-only traversal of the data structure.
-//!
-//! This traversal has limited flexibility. Only a small number of "types of
-//! interest" within the complex data structures can receive custom
-//! 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.
-//! - `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`.
-//! It defines a "skeleton" of how they should be visited.
-//! - `TypeSuperVisitable`. This is implemented only for each type of interest,
-//! and defines the visiting "skeleton" for these types.
-//! - `TypeVisitor`. This is implemented for each visitor. This defines how
-//! types of interest are visited.
-//!
-//! This means each visit is a mixture of (a) generic visiting operations, and (b)
-//! custom visit operations that are specific to the visitor.
-//! - The `TypeVisitable` impls handle most of the traversal, and call into
-//! `TypeVisitor` when they encounter a type of interest.
-//! - A `TypeVisitor` may call into another `TypeVisitable` impl, because some of
-//! the types of interest are recursive and can contain other types of interest.
-//! - A `TypeVisitor` may also call into a `TypeSuperVisitable` impl, because each
-//! visitor might provide custom handling only for some types of interest, or
-//! only for some variants of each type of interest, and then use default
-//! traversal for the remaining cases.
-//!
-//! For example, if you have `struct S(Ty, U)` where `S: TypeVisitable` and `U:
-//! TypeVisitable`, and an instance `s = S(ty, u)`, it would be visited like so:
-//! ```text
-//! s.visit_with(visitor) calls
-//! - ty.visit_with(visitor) calls
-//! - visitor.visit_ty(ty) may call
-//! - ty.super_visit_with(visitor)
-//! - u.visit_with(visitor)
-//! ```
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
use rustc_errors::ErrorGuaranteed;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sso::SsoHashSet;
-use std::fmt;
use std::ops::ControlFlow;
-/// This trait is implemented for every type that can be visited,
-/// providing the skeleton of the traversal.
-///
-/// To implement this conveniently, use the derive macro located in
-/// `rustc_macros`.
-pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
- /// The entry point for visiting. To visit a value `t` with a visitor `v`
- /// call: `t.visit_with(v)`.
- ///
- /// For most types, this just traverses the value, calling `visit_with` on
- /// each field/element.
- ///
- /// 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
- /// `TypeVisitor`.
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
+pub use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
/// Returns `true` if `self` has any late-bound regions that are either
/// bound by `binder` or bound by some binder outside of `binder`.
/// If `binder` is `ty::INNERMOST`, this indicates whether
@@ -100,6 +44,9 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
fn has_opaque_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
}
+ fn has_generators(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_TY_GENERATOR)
+ }
fn references_error(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_ERROR)
}
@@ -182,45 +129,7 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
}
}
-pub trait TypeSuperVisitable<'tcx>: TypeVisitable<'tcx> {
- /// Provides a default visit for a type of interest. This should only be
- /// called within `TypeVisitor` methods, when a non-custom traversal is
- /// desired for the value of the type of interest passed to that method.
- /// For example, in `MyVisitor::visit_ty(ty)`, it is valid to call
- /// `ty.super_visit_with(self)`, but any other visiting should be done
- /// with `xyz.visit_with(self)`.
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
-}
-
-/// This trait is implemented for every visiting traversal. There is a visit
-/// method defined for every type of interest. Each such method has a default
-/// that recurses into the type's fields in a non-custom fashion.
-pub trait TypeVisitor<'tcx>: Sized {
- type BreakTy = !;
-
- fn visit_binder<T: TypeVisitable<'tcx>>(
- &mut self,
- t: &Binder<'tcx, T>,
- ) -> ControlFlow<Self::BreakTy> {
- t.super_visit_with(self)
- }
-
- fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- t.super_visit_with(self)
- }
-
- fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
- r.super_visit_with(self)
- }
-
- fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
- c.super_visit_with(self)
- }
-
- fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
- p.super_visit_with(self)
- }
-}
+impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitableExt<'tcx> for T {}
///////////////////////////////////////////////////////////////////////////
// Region folder
@@ -229,7 +138,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Invoke `callback` on every region appearing free in `value`.
pub fn for_each_free_region(
self,
- value: &impl TypeVisitable<'tcx>,
+ value: &impl TypeVisitable<TyCtxt<'tcx>>,
mut callback: impl FnMut(ty::Region<'tcx>),
) {
self.any_free_region_meets(value, |r| {
@@ -241,7 +150,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Returns `true` if `callback` returns true for every region appearing free in `value`.
pub fn all_free_regions_meet(
self,
- value: &impl TypeVisitable<'tcx>,
+ value: &impl TypeVisitable<TyCtxt<'tcx>>,
mut callback: impl FnMut(ty::Region<'tcx>) -> bool,
) -> bool {
!self.any_free_region_meets(value, |r| !callback(r))
@@ -250,7 +159,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Returns `true` if `callback` returns true for some region appearing free in `value`.
pub fn any_free_region_meets(
self,
- value: &impl TypeVisitable<'tcx>,
+ value: &impl TypeVisitable<TyCtxt<'tcx>>,
callback: impl FnMut(ty::Region<'tcx>) -> bool,
) -> bool {
struct RegionVisitor<F> {
@@ -275,13 +184,13 @@ impl<'tcx> TyCtxt<'tcx> {
callback: F,
}
- impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F>
+ impl<'tcx, F> TypeVisitor<TyCtxt<'tcx>> for RegionVisitor<F>
where
F: FnMut(ty::Region<'tcx>) -> bool,
{
type BreakTy = ();
- fn visit_binder<T: TypeVisitable<'tcx>>(
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -328,7 +237,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: &Binder<'tcx, T>,
) -> FxHashSet<ty::BoundRegionKind>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
self.collect_late_bound_regions(value, true)
}
@@ -339,7 +248,7 @@ impl<'tcx> TyCtxt<'tcx> {
value: &Binder<'tcx, T>,
) -> FxHashSet<ty::BoundRegionKind>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
self.collect_late_bound_regions(value, false)
}
@@ -350,7 +259,7 @@ impl<'tcx> TyCtxt<'tcx> {
just_constraint: bool,
) -> FxHashSet<ty::BoundRegionKind>
where
- T: TypeVisitable<'tcx>,
+ T: TypeVisitable<TyCtxt<'tcx>>,
{
let mut collector = LateBoundRegionsCollector::new(just_constraint);
let result = value.as_ref().skip_binder().visit_with(&mut collector);
@@ -377,10 +286,10 @@ impl<'tcx> ValidateBoundVars<'tcx> {
}
}
-impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
type BreakTy = ();
- fn visit_binder<T: TypeVisitable<'tcx>>(
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -489,10 +398,10 @@ struct HasEscapingVarsVisitor {
outer_index: ty::DebruijnIndex,
}
-impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasEscapingVarsVisitor {
type BreakTy = FoundEscapingVars;
- fn visit_binder<T: TypeVisitable<'tcx>>(
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -566,7 +475,7 @@ impl std::fmt::Debug for HasTypeFlagsVisitor {
}
}
-impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasTypeFlagsVisitor {
type BreakTy = FoundFlags;
#[inline]
@@ -636,8 +545,8 @@ impl LateBoundRegionsCollector {
}
}
-impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
- fn visit_binder<T: TypeVisitable<'tcx>>(
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -698,7 +607,7 @@ impl MaxUniverse {
}
}
-impl<'tcx> TypeVisitor<'tcx> for MaxUniverse {
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Placeholder(placeholder) = t.kind() {
self.max_universe = ty::UniverseIndex::from_u32(