diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 50c30f4252703..19c59df0604c3 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -118,6 +118,11 @@ bitflags::bitflags! { /// Does this have any `ReErased` regions? const HAS_RE_ERASED = 1 << 21; + /// Does this have any regions of any kind? + const HAS_REGIONS = TypeFlags::HAS_FREE_REGIONS.bits() + | TypeFlags::HAS_RE_BOUND.bits() + | TypeFlags::HAS_RE_ERASED.bits(); + /// Does this value have parameters/placeholders/inference variables which could be /// replaced later, in a way that would change the results of `impl` specialization? const STILL_FURTHER_SPECIALIZABLE = TypeFlags::HAS_TY_PARAM.bits() @@ -139,7 +144,7 @@ bitflags::bitflags! { /// Does this type have any coroutines in it? const HAS_TY_CORO = 1 << 25; - /// Does this have have a `Bound(BoundVarIndexKind::Canonical, _)`? + /// Does this have a `Bound(BoundVarIndexKind::Canonical, _)`? const HAS_CANONICAL_BOUND = 1 << 26; } } @@ -192,7 +197,7 @@ impl FlagComputation { } fn add_flags(&mut self, flags: TypeFlags) { - self.flags = self.flags | flags; + self.flags |= flags; } /// indicates that `self` refers to something at binding level `binder` diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index d1a50599e8b9c..0fe68b5256691 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -55,7 +55,7 @@ use tracing::{debug, instrument}; use crate::inherent::*; use crate::visit::{TypeVisitable, TypeVisitableExt as _}; -use crate::{self as ty, BoundVarIndexKind, Interner, TypeFlags}; +use crate::{self as ty, BoundVarIndexKind, Interner}; /// This trait is implemented for every type that can be folded, /// providing the skeleton of the traversal. @@ -121,10 +121,6 @@ pub trait TypeSuperFoldable: TypeFoldable { /// 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: Sized { fn cx(&self) -> I; @@ -437,6 +433,10 @@ impl TypeFolder for Shifter { fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p } } + + fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses { + if c.has_vars_bound_at_or_above(self.current_index) { c.super_fold_with(self) } else { c } + } } pub fn shift_region(cx: I, region: I::Region, amount: u32) -> I::Region { @@ -477,10 +477,10 @@ where /// Folds over the substructure of a type, visiting its component /// types and all regions that occur *free* within it. /// -/// That is, function pointer types and trait object can introduce -/// new bound regions which are not visited by this visitors as +/// That is, function pointer types and trait objects can introduce +/// new bound regions which are not visited by this visitor as /// they are not free; only regions that occur free will be -/// visited by `fld_r`. +/// visited by `fold_region_fn`. pub struct RegionFolder { cx: I, @@ -489,7 +489,7 @@ pub struct RegionFolder { /// binder, it is incremented (via `shift_in`). current_index: ty::DebruijnIndex, - /// Callback invokes for each free region. The `DebruijnIndex` + /// Callback invoked for each free region. The `DebruijnIndex` /// points to the binder *just outside* the ones we have passed /// through. fold_region_fn: F, @@ -539,32 +539,18 @@ where } fn fold_ty(&mut self, t: I::Ty) -> I::Ty { - if t.has_type_flags( - TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_RE_BOUND | TypeFlags::HAS_RE_ERASED, - ) { - t.super_fold_with(self) - } else { - t - } + if t.has_regions() { t.super_fold_with(self) } else { t } } fn fold_const(&mut self, ct: I::Const) -> I::Const { - if ct.has_type_flags( - TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_RE_BOUND | TypeFlags::HAS_RE_ERASED, - ) { - ct.super_fold_with(self) - } else { - ct - } + if ct.has_regions() { ct.super_fold_with(self) } else { ct } } fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { - if p.has_type_flags( - TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_RE_BOUND | TypeFlags::HAS_RE_ERASED, - ) { - p.super_fold_with(self) - } else { - p - } + if p.has_regions() { p.super_fold_with(self) } else { p } + } + + fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses { + if c.has_regions() { c.super_fold_with(self) } else { c } } } diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index a078b860be774..492c37481298b 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -67,7 +67,7 @@ pub trait TypeVisitable: fmt::Debug { /// 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 + /// calls a visitor method specifically for that type (such as /// `V::visit_ty`). This is where control transfers from `TypeVisitable` to /// `TypeVisitor`. fn visit_with>(&self, visitor: &mut V) -> V::Result; @@ -102,8 +102,8 @@ pub trait TypeVisitor: Sized { t.super_visit_with(self) } - // The default region visitor is a no-op because `Region` is non-recursive - // and has no `super_visit_with` method to call. + // `Region` is non-recursive so the default region visitor has no + // `super_visit_with` method to call. fn visit_region(&mut self, r: I::Region) -> Self::Result { if let ty::ReError(guar) = r.kind() { self.visit_error(guar) @@ -251,10 +251,10 @@ pub trait TypeVisitableExt: TypeVisitable { 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. + /// Returns `true` if this type has regions that are not a part of the + /// type. For example, given a `for<'a> fn(&'a i32)` this function returns + /// `false`, while given a `fn(&'a i32)` it returns `true`. The latter can + /// occur when traversing through the former. /// /// See [`HasEscapingVarsVisitor`] for more information. fn has_escaping_bound_vars(&self) -> bool { @@ -285,6 +285,10 @@ pub trait TypeVisitableExt: TypeVisitable { self.has_type_flags(TypeFlags::HAS_PARAM - TypeFlags::HAS_RE_PARAM) } + fn has_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_REGIONS) + } + fn has_infer_regions(&self) -> bool { self.has_type_flags(TypeFlags::HAS_RE_INFER) } @@ -363,13 +367,12 @@ pub trait TypeVisitableExt: TypeVisitable { impl> TypeVisitableExt for T { fn has_type_flags(&self, flags: TypeFlags) -> bool { - let res = - self.visit_with(&mut HasTypeFlagsVisitor { flags }) == ControlFlow::Break(FoundFlags); - res + self.visit_with(&mut HasTypeFlagsVisitor { flags }) == ControlFlow::Break(FoundFlags) } fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool { - self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break() + self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }) + == ControlFlow::Break(FoundEscapingVars) } fn error_reported(&self) -> Result<(), I::ErrorGuaranteed> { @@ -438,8 +441,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { #[inline] fn visit_ty(&mut self, t: I::Ty) -> Self::Result { // Note: no `super_visit_with` call. - let flags = t.flags(); - if flags.intersects(self.flags) { + if t.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { ControlFlow::Continue(()) @@ -449,8 +451,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { #[inline] fn visit_region(&mut self, r: I::Region) -> Self::Result { // Note: no `super_visit_with` call, as usual for `Region`. - let flags = r.flags(); - if flags.intersects(self.flags) { + if r.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) } else { ControlFlow::Continue(()) @@ -571,7 +572,7 @@ impl TypeVisitor for HasEscapingVarsVisitor { // `outer_index`, that means that `ct` contains some content // bound at `outer_index` or above (because // `outer_exclusive_binder` is always 1 higher than the - // content in `t`). Therefore, `t` has some escaping vars. + // content in `ct`). Therefore, `ct` has some escaping vars. if ct.outer_exclusive_binder() > self.outer_index { ControlFlow::Break(FoundEscapingVars) } else {