From 62846d7c99ca4e17be8c6867fc4b50d10c8a6ec1 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Thu, 9 Feb 2023 12:56:33 +0000 Subject: [PATCH] Move folding & visiting traits to ir submodules --- compiler/rustc_middle/src/ty/fold.rs | 290 +++++++++++----------- compiler/rustc_middle/src/ty/mod.rs | 4 + compiler/rustc_middle/src/ty/visit.rs | 338 ++++++++++++++------------ 3 files changed, 331 insertions(+), 301 deletions(-) diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index c0d319edf76..1b8f6e12c3f 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -48,161 +48,173 @@ use rustc_hir::def_id::DefId; use std::collections::BTreeMap; -/// This trait is implemented for every type that can be folded, -/// providing the skeleton of the traversal. -/// -/// To implement this conveniently, use the derive macro located in -/// `rustc_macros`. -pub trait TypeFoldable<'tcx>: TypeVisitable<'tcx> { - /// The entry point for folding. To fold a value `t` with a folder `f` - /// call: `t.try_fold_with(f)`. +pub use ir::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; + +pub mod ir { + use crate::ty::{self, ir::TypeVisitable, Binder, Ty, TyCtxt}; + + /// This trait is implemented for every type that can be folded, + /// providing the skeleton of the traversal. /// - /// For most types, this just traverses the value, calling `try_fold_with` - /// on each field/element. + /// To implement this conveniently, use the derive macro located in + /// `rustc_macros`. + pub trait TypeFoldable<'tcx>: TypeVisitable<'tcx> { + /// The entry point for folding. To fold a value `t` with a folder `f` + /// call: `t.try_fold_with(f)`. + /// + /// 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 + /// calls a folder method specifically for that type (such as + /// `F::try_fold_ty`). This is where control transfers from `TypeFoldable` + /// to `TypeFolder`. + fn try_fold_with>( + self, + folder: &mut F, + ) -> Result; + + /// A convenient alternative to `try_fold_with` for use with infallible + /// folders. Do not override this method, to ensure coherence with + /// `try_fold_with`. + fn fold_with>(self, folder: &mut F) -> Self { + self.try_fold_with(folder).into_ok() + } + } + + // This trait is implemented for types of interest. + pub trait TypeSuperFoldable<'tcx>: TypeFoldable<'tcx> { + /// Provides a default fold for a type of interest. This should only be + /// called within `TypeFolder` methods, when a non-custom traversal is + /// desired for the value of the type of interest passed to that method. + /// For example, in `MyFolder::try_fold_ty(ty)`, it is valid to call + /// `ty.try_super_fold_with(self)`, but any other folding should be done + /// with `xyz.try_fold_with(self)`. + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result; + + /// A convenient alternative to `try_super_fold_with` for use with + /// infallible folders. Do not override this method, to ensure coherence + /// with `try_super_fold_with`. + fn super_fold_with>(self, folder: &mut F) -> Self { + self.try_super_fold_with(folder).into_ok() + } + } + + /// This trait is implemented for every infallible folding traversal. There is + /// a fold method defined for every type of interest. Each such method has a + /// default that does an "identity" fold. Implementations of these methods + /// often fall back to a `super_fold_with` method if the primary argument + /// doesn't satisfy a particular condition. /// - /// For types of interest (such as `Ty`), the implementation of method - /// calls a folder method specifically for that type (such as - /// `F::try_fold_ty`). This is where control transfers from `TypeFoldable` - /// to `TypeFolder`. - fn try_fold_with>(self, folder: &mut F) -> Result; + /// A blanket implementation of [`FallibleTypeFolder`] will defer to + /// the infallible methods of this trait to ensure that the two APIs + /// are coherent. + pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> { + fn tcx(&self) -> TyCtxt<'tcx>; - /// A convenient alternative to `try_fold_with` for use with infallible - /// folders. Do not override this method, to ensure coherence with - /// `try_fold_with`. - fn fold_with>(self, folder: &mut F) -> Self { - self.try_fold_with(folder).into_ok() + fn fold_binder(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> + where + T: TypeFoldable<'tcx>, + { + t.super_fold_with(self) + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + t.super_fold_with(self) + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + r.super_fold_with(self) + } + + fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { + c.super_fold_with(self) + } + + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + p.super_fold_with(self) + } } -} -// This trait is implemented for types of interest. -pub trait TypeSuperFoldable<'tcx>: TypeFoldable<'tcx> { - /// Provides a default fold for a type of interest. This should only be - /// called within `TypeFolder` methods, when a non-custom traversal is - /// desired for the value of the type of interest passed to that method. - /// For example, in `MyFolder::try_fold_ty(ty)`, it is valid to call - /// `ty.try_super_fold_with(self)`, but any other folding should be done - /// with `xyz.try_fold_with(self)`. - fn try_super_fold_with>( - self, - folder: &mut F, - ) -> Result; + /// This trait is implemented for every folding traversal. There is a fold + /// method defined for every type of interest. Each such method has a default + /// that does an "identity" fold. + /// + /// A blanket implementation of this trait (that defers to the relevant + /// method of [`TypeFolder`]) is provided for all infallible folders in + /// order to ensure the two APIs are coherent. + pub trait FallibleTypeFolder<'tcx>: Sized { + type Error; - /// A convenient alternative to `try_super_fold_with` for use with - /// infallible folders. Do not override this method, to ensure coherence - /// with `try_super_fold_with`. - fn super_fold_with>(self, folder: &mut F) -> Self { - self.try_super_fold_with(folder).into_ok() + fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; + + fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, Self::Error> + where + T: TypeFoldable<'tcx>, + { + t.try_super_fold_with(self) + } + + fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { + t.try_super_fold_with(self) + } + + fn try_fold_region( + &mut self, + r: ty::Region<'tcx>, + ) -> Result, Self::Error> { + r.try_super_fold_with(self) + } + + fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result, Self::Error> { + c.try_super_fold_with(self) + } + + fn try_fold_predicate( + &mut self, + p: ty::Predicate<'tcx>, + ) -> Result, Self::Error> { + p.try_super_fold_with(self) + } } -} -/// This trait is implemented for every infallible folding traversal. There is -/// a fold method defined for every type of interest. Each such method has a -/// default that does an "identity" fold. Implementations of these methods -/// often fall back to a `super_fold_with` method if the primary argument -/// doesn't satisfy a particular condition. -/// -/// A blanket implementation of [`FallibleTypeFolder`] will defer to -/// the infallible methods of this trait to ensure that the two APIs -/// are coherent. -pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> { - fn tcx(&self) -> TyCtxt<'tcx>; - - fn fold_binder(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> + // This blanket implementation of the fallible trait for infallible folders + // delegates to infallible methods to ensure coherence. + impl<'tcx, F> FallibleTypeFolder<'tcx> for F where - T: TypeFoldable<'tcx>, + F: TypeFolder<'tcx>, { - t.super_fold_with(self) - } + type Error = !; - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - t.super_fold_with(self) - } + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + TypeFolder::tcx(self) + } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - r.super_fold_with(self) - } + fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, !> + where + T: TypeFoldable<'tcx>, + { + Ok(self.fold_binder(t)) + } - fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { - c.super_fold_with(self) - } + fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, !> { + Ok(self.fold_ty(t)) + } - fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { - p.super_fold_with(self) - } -} + fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { + Ok(self.fold_region(r)) + } -/// This trait is implemented for every folding traversal. There is a fold -/// method defined for every type of interest. Each such method has a default -/// that does an "identity" fold. -/// -/// A blanket implementation of this trait (that defers to the relevant -/// method of [`TypeFolder`]) is provided for all infallible folders in -/// order to ensure the two APIs are coherent. -pub trait FallibleTypeFolder<'tcx>: Sized { - type Error; + fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result, !> { + Ok(self.fold_const(c)) + } - fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; - - fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, Self::Error> - where - T: TypeFoldable<'tcx>, - { - t.try_super_fold_with(self) - } - - fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { - t.try_super_fold_with(self) - } - - fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { - r.try_super_fold_with(self) - } - - fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result, Self::Error> { - c.try_super_fold_with(self) - } - - fn try_fold_predicate( - &mut self, - p: ty::Predicate<'tcx>, - ) -> Result, Self::Error> { - p.try_super_fold_with(self) - } -} - -// This blanket implementation of the fallible trait for infallible folders -// delegates to infallible methods to ensure coherence. -impl<'tcx, F> FallibleTypeFolder<'tcx> for F -where - F: TypeFolder<'tcx>, -{ - type Error = !; - - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { - TypeFolder::tcx(self) - } - - fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, !> - where - T: TypeFoldable<'tcx>, - { - Ok(self.fold_binder(t)) - } - - fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, !> { - Ok(self.fold_ty(t)) - } - - fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, !> { - Ok(self.fold_region(r)) - } - - fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result, !> { - Ok(self.fold_const(c)) - } - - fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result, !> { - Ok(self.fold_predicate(p)) + fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result, !> { + Ok(self.fold_predicate(p)) + } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index fa2d3b89cf4..f378c6fd8ad 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -146,6 +146,10 @@ mod structural_impls; mod sty; mod typeck_results; +pub mod ir { + pub use super::{fold::ir::*, visit::ir::*}; +} + // Data types pub type RegisteredTools = FxHashSet; diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index d7b7a094737..fe3fc4c88c5 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -39,189 +39,203 @@ //! - 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)`. +pub use ir::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; + +pub mod ir { + use crate::ty::{self, Binder, Ty, TypeFlags}; + use rustc_errors::ErrorGuaranteed; + + use std::fmt; + use std::ops::ControlFlow; + + use super::{FoundFlags, HasEscapingVarsVisitor, HasTypeFlagsVisitor}; + + /// This trait is implemented for every type that can be visited, + /// providing the skeleton of the traversal. /// - /// 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>(&self, visitor: &mut V) -> ControlFlow; + /// 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>(&self, visitor: &mut V) -> ControlFlow; - /// 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 - /// there are any late-bound regions that appear free. - fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { - self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break() - } + /// 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 + /// there are any late-bound regions that appear free. + fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { + self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break() + } - /// Returns `true` if this type has any regions that escape `binder` (and - /// hence are not bound by it). - fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool { - self.has_vars_bound_at_or_above(binder.shifted_in(1)) - } + /// Returns `true` if this type has any regions that escape `binder` (and + /// hence are not bound by it). + fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool { + self.has_vars_bound_at_or_above(binder.shifted_in(1)) + } - /// Return `true` if this type has regions that are not a part of the type. - /// For example, `for<'a> fn(&'a i32)` return `false`, while `fn(&'a i32)` - /// would return `true`. The latter can occur when traversing through the - /// former. - /// - /// See [`HasEscapingVarsVisitor`] for more information. - fn has_escaping_bound_vars(&self) -> bool { - self.has_vars_bound_at_or_above(ty::INNERMOST) - } + /// Return `true` if this type has regions that are not a part of the type. + /// For example, `for<'a> fn(&'a i32)` return `false`, while `fn(&'a i32)` + /// would return `true`. The latter can occur when traversing through the + /// former. + /// + /// See [`HasEscapingVarsVisitor`] for more information. + fn has_escaping_bound_vars(&self) -> bool { + self.has_vars_bound_at_or_above(ty::INNERMOST) + } - fn has_type_flags(&self, flags: TypeFlags) -> bool { - let res = - self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags); - trace!(?self, ?flags, ?res, "has_type_flags"); - res - } - fn has_projections(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_PROJECTION) - } - 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) - } - fn error_reported(&self) -> Result<(), ErrorGuaranteed> { - if self.references_error() { - if let Some(reported) = ty::tls::with(|tcx| tcx.sess.is_compilation_going_to_fail()) { - Err(reported) + fn has_type_flags(&self, flags: TypeFlags) -> bool { + let res = self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() + == Some(FoundFlags); + trace!(?self, ?flags, ?res, "has_type_flags"); + res + } + fn has_projections(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_PROJECTION) + } + 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) + } + fn error_reported(&self) -> Result<(), ErrorGuaranteed> { + if self.references_error() { + if let Some(reported) = ty::tls::with(|tcx| tcx.sess.is_compilation_going_to_fail()) + { + Err(reported) + } else { + bug!("expect tcx.sess.is_compilation_going_to_fail return `Some`"); + } } else { - bug!("expect tcx.sess.is_compilation_going_to_fail return `Some`"); + Ok(()) } - } else { - Ok(()) + } + fn has_non_region_param(&self) -> bool { + self.has_type_flags(TypeFlags::NEEDS_SUBST - TypeFlags::HAS_RE_PARAM) + } + fn has_infer_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_INFER) + } + fn has_infer_types(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_INFER) + } + fn has_non_region_infer(&self) -> bool { + self.has_type_flags(TypeFlags::NEEDS_INFER - TypeFlags::HAS_RE_INFER) + } + fn needs_infer(&self) -> bool { + self.has_type_flags(TypeFlags::NEEDS_INFER) + } + fn has_placeholders(&self) -> bool { + self.has_type_flags( + TypeFlags::HAS_RE_PLACEHOLDER + | TypeFlags::HAS_TY_PLACEHOLDER + | TypeFlags::HAS_CT_PLACEHOLDER, + ) + } + fn needs_subst(&self) -> bool { + self.has_type_flags(TypeFlags::NEEDS_SUBST) + } + /// "Free" regions in this context means that it has any region + /// that is not (a) erased or (b) late-bound. + fn has_free_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) + } + + fn has_erased_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_ERASED) + } + + /// True if there are any un-erased free regions. + fn has_erasable_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) + } + + /// Indicates whether this value references only 'global' + /// generic parameters that are the same regardless of what fn we are + /// in. This is used for caching. + fn is_global(&self) -> bool { + !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES) + } + + /// True if there are any late-bound regions + fn has_late_bound_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND) + } + /// True if there are any late-bound non-region variables + fn has_non_region_late_bound(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_LATE_BOUND - TypeFlags::HAS_RE_LATE_BOUND) + } + /// True if there are any late-bound variables + fn has_late_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_LATE_BOUND) + } + + /// Indicates whether this value still has parameters/placeholders/inference variables + /// which could be replaced later, in a way that would change the results of `impl` + /// specialization. + fn still_further_specializable(&self) -> bool { + self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE) } } - fn has_non_region_param(&self) -> bool { - self.has_type_flags(TypeFlags::NEEDS_SUBST - TypeFlags::HAS_RE_PARAM) - } - fn has_infer_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_INFER) - } - fn has_infer_types(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_TY_INFER) - } - fn has_non_region_infer(&self) -> bool { - self.has_type_flags(TypeFlags::NEEDS_INFER - TypeFlags::HAS_RE_INFER) - } - fn needs_infer(&self) -> bool { - self.has_type_flags(TypeFlags::NEEDS_INFER) - } - fn has_placeholders(&self) -> bool { - self.has_type_flags( - TypeFlags::HAS_RE_PLACEHOLDER - | TypeFlags::HAS_TY_PLACEHOLDER - | TypeFlags::HAS_CT_PLACEHOLDER, - ) - } - fn needs_subst(&self) -> bool { - self.has_type_flags(TypeFlags::NEEDS_SUBST) - } - /// "Free" regions in this context means that it has any region - /// that is not (a) erased or (b) late-bound. - fn has_free_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) + + 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>( + &self, + visitor: &mut V, + ) -> ControlFlow; } - fn has_erased_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_ERASED) - } + /// 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 = !; - /// True if there are any un-erased free regions. - fn has_erasable_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) - } + fn visit_binder>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { + t.super_visit_with(self) + } - /// Indicates whether this value references only 'global' - /// generic parameters that are the same regardless of what fn we are - /// in. This is used for caching. - fn is_global(&self) -> bool { - !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES) - } + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + t.super_visit_with(self) + } - /// True if there are any late-bound regions - fn has_late_bound_regions(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND) - } - /// True if there are any late-bound non-region variables - fn has_non_region_late_bound(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_LATE_BOUND - TypeFlags::HAS_RE_LATE_BOUND) - } - /// True if there are any late-bound variables - fn has_late_bound_vars(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_LATE_BOUND) - } + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + r.super_visit_with(self) + } - /// Indicates whether this value still has parameters/placeholders/inference variables - /// which could be replaced later, in a way that would change the results of `impl` - /// specialization. - fn still_further_specializable(&self) -> bool { - self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE) - } -} + fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + c.super_visit_with(self) + } -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>(&self, visitor: &mut V) -> ControlFlow; -} - -/// 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>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow { - t.super_visit_with(self) - } - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - t.super_visit_with(self) - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - r.super_visit_with(self) - } - - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { - c.super_visit_with(self) - } - - fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow { - p.super_visit_with(self) + fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow { + p.super_visit_with(self) + } } }