TypeVisitor: use std::ops::ControlFlow instead of bool

This commit is contained in:
LeSeulArtichaut 2020-10-21 14:22:44 +02:00
parent 8df58ae03a
commit 2c85b6fae0
10 changed files with 243 additions and 165 deletions

View File

@ -15,8 +15,12 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
}
})
});
let body_visit = s.fold(false, |acc, bind| {
quote! { #acc || ::rustc_middle::ty::fold::TypeFoldable::visit_with(#bind, __folder) }
let body_visit = s.fold(quote!(), |acc, bind| {
quote! {
#acc
::rustc_middle::ty::fold::TypeFoldable::visit_with(#bind, __folder)?;
}
});
s.bound_impl(
@ -32,8 +36,9 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
fn super_visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>(
&self,
__folder: &mut __F
) -> bool {
) -> ::std::ops::ControlFlow<(), ()> {
match *self { #body_visit }
::std::ops::ControlFlow::CONTINUE
}
},
)

View File

@ -49,6 +49,7 @@
#![feature(int_error_matching)]
#![feature(half_open_range_patterns)]
#![feature(exclusive_range_pattern)]
#![feature(control_flow_enum)]
#![recursion_limit = "512"]
#[macro_use]

View File

@ -62,9 +62,9 @@ macro_rules! CloneTypeFoldableImpls {
fn super_visit_with<F: $crate::ty::fold::TypeVisitor<$tcx>>(
&self,
_: &mut F)
-> bool
-> ::std::ops::ControlFlow<(), ()>
{
false
::std::ops::ControlFlow::CONTINUE
}
}
)+
@ -105,7 +105,7 @@ macro_rules! EnumTypeFoldableImpl {
fn super_visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
&self,
visitor: &mut V,
) -> bool {
) -> ::std::ops::ControlFlow<(), ()> {
EnumTypeFoldableImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
}
}
@ -179,9 +179,10 @@ macro_rules! EnumTypeFoldableImpl {
input($($input)*)
output(
$variant ( $($variant_arg),* ) => {
false $(|| $crate::ty::fold::TypeFoldable::visit_with(
$($crate::ty::fold::TypeFoldable::visit_with(
$variant_arg, $visitor
))*
)?;)*
::std::ops::ControlFlow::CONTINUE
}
$($output)*
)
@ -196,9 +197,10 @@ macro_rules! EnumTypeFoldableImpl {
input($($input)*)
output(
$variant { $($variant_arg),* } => {
false $(|| $crate::ty::fold::TypeFoldable::visit_with(
$($crate::ty::fold::TypeFoldable::visit_with(
$variant_arg, $visitor
))*
)?;)*
::std::ops::ControlFlow::CONTINUE
}
$($output)*
)
@ -212,7 +214,7 @@ macro_rules! EnumTypeFoldableImpl {
@VisitVariants($this, $visitor)
input($($input)*)
output(
$variant => { false }
$variant => { ::std::ops::ControlFlow::CONTINUE }
$($output)*
)
)

View File

@ -32,7 +32,7 @@ use rustc_target::abi;
use rustc_target::asm::InlineAsmRegOrRegClass;
use std::borrow::Cow;
use std::fmt::{self, Debug, Display, Formatter, Write};
use std::ops::{Index, IndexMut};
use std::ops::{ControlFlow, Index, IndexMut};
use std::slice;
use std::{iter, mem, option};
@ -2489,7 +2489,7 @@ impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
UserTypeProjection { base, projs }
}
fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> ControlFlow<(), ()> {
self.base.visit_with(visitor)
// Note: there's nothing in `self.proj` to visit.
}

View File

@ -87,41 +87,46 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
Terminator { source_info: self.source_info, kind }
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
use crate::mir::TerminatorKind::*;
match self.kind {
SwitchInt { ref discr, switch_ty, .. } => {
discr.visit_with(visitor) || switch_ty.visit_with(visitor)
discr.visit_with(visitor)?;
switch_ty.visit_with(visitor)
}
Drop { ref place, .. } => place.visit_with(visitor),
DropAndReplace { ref place, ref value, .. } => {
place.visit_with(visitor) || value.visit_with(visitor)
place.visit_with(visitor)?;
value.visit_with(visitor)
}
Yield { ref value, .. } => value.visit_with(visitor),
Call { ref func, ref args, ref destination, .. } => {
let dest = if let Some((ref loc, _)) = *destination {
loc.visit_with(visitor)
} else {
false
if let Some((ref loc, _)) = *destination {
loc.visit_with(visitor)?;
};
dest || func.visit_with(visitor) || args.visit_with(visitor)
func.visit_with(visitor)?;
args.visit_with(visitor)
}
Assert { ref cond, ref msg, .. } => {
if cond.visit_with(visitor) {
if cond.visit_with(visitor) == ControlFlow::BREAK {
use AssertKind::*;
match msg {
BoundsCheck { ref len, ref index } => {
len.visit_with(visitor) || index.visit_with(visitor)
len.visit_with(visitor)?;
index.visit_with(visitor)
}
Overflow(_, l, r) => {
l.visit_with(visitor)?;
r.visit_with(visitor)
}
Overflow(_, l, r) => l.visit_with(visitor) || r.visit_with(visitor),
OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
op.visit_with(visitor)
}
ResumedAfterReturn(_) | ResumedAfterPanic(_) => false,
ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE,
}
} else {
false
ControlFlow::CONTINUE
}
}
InlineAsm { ref operands, .. } => operands.visit_with(visitor),
@ -132,7 +137,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
| GeneratorDrop
| Unreachable
| FalseEdge { .. }
| FalseUnwind { .. } => false,
| FalseUnwind { .. } => ControlFlow::CONTINUE,
}
}
}
@ -142,8 +147,8 @@ impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<(), ()> {
ControlFlow::CONTINUE
}
}
@ -152,8 +157,9 @@ impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) }
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.local.visit_with(visitor) || self.projection.visit_with(visitor)
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.local.visit_with(visitor)?;
self.projection.visit_with(visitor)
}
}
@ -163,8 +169,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
folder.tcx().intern_place_elems(&v)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|t| t.visit_with(visitor))
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
@ -213,32 +219,47 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
use crate::mir::Rvalue::*;
match *self {
Use(ref op) => op.visit_with(visitor),
Repeat(ref op, _) => op.visit_with(visitor),
ThreadLocalRef(did) => did.visit_with(visitor),
Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
Ref(region, _, ref place) => {
region.visit_with(visitor)?;
place.visit_with(visitor)
}
AddressOf(_, ref place) => place.visit_with(visitor),
Len(ref place) => place.visit_with(visitor),
Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
Cast(_, ref op, ty) => {
op.visit_with(visitor)?;
ty.visit_with(visitor)
}
BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => {
rhs.visit_with(visitor) || lhs.visit_with(visitor)
rhs.visit_with(visitor)?;
lhs.visit_with(visitor)
}
UnaryOp(_, ref val) => val.visit_with(visitor),
Discriminant(ref place) => place.visit_with(visitor),
NullaryOp(_, ty) => ty.visit_with(visitor),
Aggregate(ref kind, ref fields) => {
(match **kind {
AggregateKind::Array(ty) => ty.visit_with(visitor),
AggregateKind::Tuple => false,
AggregateKind::Adt(_, _, substs, user_ty, _) => {
substs.visit_with(visitor) || user_ty.visit_with(visitor)
match **kind {
AggregateKind::Array(ty) => {
ty.visit_with(visitor)?;
}
AggregateKind::Closure(_, substs) => substs.visit_with(visitor),
AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor),
}) || fields.visit_with(visitor)
AggregateKind::Tuple => {}
AggregateKind::Adt(_, _, substs, user_ty, _) => {
substs.visit_with(visitor)?;
user_ty.visit_with(visitor)?;
}
AggregateKind::Closure(_, substs) => {
substs.visit_with(visitor)?;
}
AggregateKind::Generator(_, substs, _) => {
substs.visit_with(visitor)?;
}
}
fields.visit_with(visitor)
}
}
}
@ -253,7 +274,7 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
match *self {
Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
Operand::Constant(ref c) => c.visit_with(visitor),
@ -277,13 +298,13 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
}
}
fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> ControlFlow<(), ()> {
use crate::mir::ProjectionElem::*;
match self {
Field(_, ty) => ty.visit_with(visitor),
Index(v) => v.visit_with(visitor),
_ => false,
_ => ControlFlow::CONTINUE,
}
}
}
@ -292,8 +313,8 @@ impl<'tcx> TypeFoldable<'tcx> for Field {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<(), ()> {
ControlFlow::CONTINUE
}
}
@ -301,8 +322,8 @@ impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<(), ()> {
ControlFlow::CONTINUE
}
}
@ -310,8 +331,8 @@ impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
self.clone()
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<(), ()> {
ControlFlow::CONTINUE
}
}
@ -323,7 +344,7 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
literal: self.literal.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.literal.visit_with(visitor)
}
}

View File

@ -37,6 +37,7 @@ use rustc_hir::def_id::DefId;
use rustc_data_structures::fx::FxHashSet;
use std::collections::BTreeMap;
use std::fmt;
use std::ops::ControlFlow;
/// This trait is implemented for every type that can be folded.
/// Basically, every type that has a corresponding method in `TypeFolder`.
@ -48,8 +49,8 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
self.super_fold_with(folder)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool;
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()>;
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.super_visit_with(visitor)
}
@ -59,6 +60,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
/// 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 })
== ControlFlow::Break(())
}
/// Returns `true` if this `self` has any regions that escape `binder` (and
@ -72,7 +74,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
}
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.visit_with(&mut HasTypeFlagsVisitor { flags })
self.visit_with(&mut HasTypeFlagsVisitor { flags }) == ControlFlow::Break(())
}
fn has_projections(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_PROJECTION)
@ -143,11 +145,14 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
}
/// A visitor that does not recurse into types, works like `fn walk_shallow` in `Ty`.
fn visit_tys_shallow(&self, visit: impl FnMut(Ty<'tcx>) -> bool) -> bool {
fn visit_tys_shallow(
&self,
visit: impl FnMut(Ty<'tcx>) -> ControlFlow<(), ()>,
) -> ControlFlow<(), ()> {
pub struct Visitor<F>(F);
impl<'tcx, F: FnMut(Ty<'tcx>) -> bool> TypeVisitor<'tcx> for Visitor<F> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
impl<'tcx, F: FnMut(Ty<'tcx>) -> ControlFlow<(), ()>> TypeVisitor<'tcx> for Visitor<F> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
self.0(ty)
}
}
@ -160,8 +165,8 @@ impl TypeFoldable<'tcx> for hir::Constness {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
false
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<(), ()> {
ControlFlow::CONTINUE
}
}
@ -194,23 +199,23 @@ pub trait TypeFolder<'tcx>: Sized {
}
pub trait TypeVisitor<'tcx>: Sized {
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> ControlFlow<(), ()> {
t.super_visit_with(self)
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
t.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<(), ()> {
r.super_visit_with(self)
}
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<(), ()> {
c.super_visit_with(self)
}
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> bool {
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<(), ()> {
p.super_visit_with(self)
}
}
@ -302,8 +307,6 @@ impl<'tcx> TyCtxt<'tcx> {
value: &impl TypeFoldable<'tcx>,
callback: impl FnMut(ty::Region<'tcx>) -> bool,
) -> bool {
return value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback });
struct RegionVisitor<F> {
/// The index of a binder *just outside* the things we have
/// traversed. If we encounter a bound region bound by this
@ -330,31 +333,43 @@ impl<'tcx> TyCtxt<'tcx> {
where
F: FnMut(ty::Region<'tcx>) -> bool,
{
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &Binder<T>,
) -> ControlFlow<(), ()> {
self.outer_index.shift_in(1);
let result = t.as_ref().skip_binder().visit_with(self);
self.outer_index.shift_out(1);
result
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<(), ()> {
match *r {
ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => {
false // ignore bound regions, keep visiting
ControlFlow::CONTINUE
}
_ => {
if (self.callback)(r) {
ControlFlow::BREAK
} else {
ControlFlow::CONTINUE
}
}
_ => (self.callback)(r),
}
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> {
// We're only interested in types involving regions
if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
ty.super_visit_with(self)
} else {
false // keep visiting
ControlFlow::CONTINUE
}
}
}
value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback })
== ControlFlow::BREAK
}
}
@ -670,7 +685,7 @@ impl<'tcx> TyCtxt<'tcx> {
{
let mut collector = LateBoundRegionsCollector::new(just_constraint);
let result = value.as_ref().skip_binder().visit_with(&mut collector);
assert!(!result); // should never have stopped early
assert!(result == ControlFlow::Continue(())); // should never have stopped early
collector.regions
}
@ -836,43 +851,55 @@ struct HasEscapingVarsVisitor {
}
impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> ControlFlow<(), ()> {
self.outer_index.shift_in(1);
let result = t.super_visit_with(self);
self.outer_index.shift_out(1);
result
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
// If the outer-exclusive-binder is *strictly greater* than
// `outer_index`, that means that `t` 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.
t.outer_exclusive_binder > self.outer_index
if t.outer_exclusive_binder > self.outer_index {
ControlFlow::BREAK
} else {
ControlFlow::CONTINUE
}
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<(), ()> {
// If the region is bound by `outer_index` or anything outside
// of outer index, then it escapes the binders we have
// visited.
r.bound_at_or_above_binder(self.outer_index)
if r.bound_at_or_above_binder(self.outer_index) {
ControlFlow::BREAK
} else {
ControlFlow::CONTINUE
}
}
fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> bool {
fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> ControlFlow<(), ()> {
// we don't have a `visit_infer_const` callback, so we have to
// hook in here to catch this case (annoying...), but
// otherwise we do want to remember to visit the rest of the
// const, as it has types/regions embedded in a lot of other
// places.
match ct.val {
ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => true,
ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => ControlFlow::BREAK,
_ => ct.super_visit_with(self),
}
}
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool {
predicate.inner.outer_exclusive_binder > self.outer_index
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<(), ()> {
if predicate.inner.outer_exclusive_binder > self.outer_index {
ControlFlow::BREAK
} else {
ControlFlow::CONTINUE
}
}
}
@ -882,34 +909,38 @@ struct HasTypeFlagsVisitor {
}
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
fn visit_ty(&mut self, t: Ty<'_>) -> bool {
fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<(), ()> {
debug!(
"HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}",
t,
t.flags(),
self.flags
);
t.flags().intersects(self.flags)
if t.flags().intersects(self.flags) { ControlFlow::BREAK } else { ControlFlow::CONTINUE }
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<(), ()> {
let flags = r.type_flags();
debug!("HasTypeFlagsVisitor: r={:?} r.flags={:?} self.flags={:?}", r, flags, self.flags);
flags.intersects(self.flags)
if flags.intersects(self.flags) { ControlFlow::BREAK } else { ControlFlow::CONTINUE }
}
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<(), ()> {
let flags = FlagComputation::for_const(c);
debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
flags.intersects(self.flags)
if flags.intersects(self.flags) { ControlFlow::BREAK } else { ControlFlow::CONTINUE }
}
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> bool {
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<(), ()> {
debug!(
"HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
predicate, predicate.inner.flags, self.flags
);
predicate.inner.flags.intersects(self.flags)
if predicate.inner.flags.intersects(self.flags) {
ControlFlow::BREAK
} else {
ControlFlow::CONTINUE
}
}
}
@ -940,45 +971,45 @@ impl LateBoundRegionsCollector {
}
impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> ControlFlow<(), ()> {
self.current_index.shift_in(1);
let result = t.super_visit_with(self);
self.current_index.shift_out(1);
result
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<(), ()> {
// if we are only looking for "constrained" region, we have to
// ignore the inputs to a projection, as they may not appear
// in the normalized form
if self.just_constrained {
if let ty::Projection(..) | ty::Opaque(..) = t.kind() {
return false;
return ControlFlow::CONTINUE;
}
}
t.super_visit_with(self)
}
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<(), ()> {
// if we are only looking for "constrained" region, we have to
// ignore the inputs of an unevaluated const, as they may not appear
// in the normalized form
if self.just_constrained {
if let ty::ConstKind::Unevaluated(..) = c.val {
return false;
return ControlFlow::CONTINUE;
}
}
c.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<(), ()> {
if let ty::ReLateBound(debruijn, br) = *r {
if debruijn == self.current_index {
self.regions.insert(br);
}
}
false
ControlFlow::CONTINUE
}
}

View File

@ -46,7 +46,7 @@ use std::cell::RefCell;
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops::Range;
use std::ops::{ControlFlow, Range};
use std::ptr;
use std::str;
@ -1776,8 +1776,9 @@ impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
ParamEnv::new(self.caller_bounds().fold_with(folder), self.reveal().fold_with(folder))
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.caller_bounds().visit_with(visitor) || self.reveal().visit_with(visitor)
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.caller_bounds().visit_with(visitor)?;
self.reveal().visit_with(visitor)
}
}

View File

@ -22,7 +22,7 @@ use std::cell::Cell;
use std::char;
use std::collections::BTreeMap;
use std::fmt::{self, Write as _};
use std::ops::{Deref, DerefMut};
use std::ops::{ControlFlow, Deref, DerefMut};
// `pretty` is a separate module only for organization.
use super::*;
@ -1803,7 +1803,7 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
{
struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet<Symbol>);
impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<(), ()> {
if let ty::ReLateBound(_, ty::BrNamed(_, name)) = *r {
self.0.insert(name);
}

View File

@ -14,6 +14,7 @@ use rustc_index::vec::{Idx, IndexVec};
use smallvec::SmallVec;
use std::fmt;
use std::ops::ControlFlow;
use std::rc::Rc;
use std::sync::Arc;
@ -727,8 +728,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
false
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<(), ()> {
ControlFlow::CONTINUE
}
}
@ -737,8 +738,9 @@ impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for
(self.0.fold_with(folder), self.1.fold_with(folder))
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.0.visit_with(visitor) || self.1.visit_with(visitor)
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.0.visit_with(visitor)?;
self.1.visit_with(visitor)
}
}
@ -749,8 +751,10 @@ impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>>
(self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder))
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.0.visit_with(visitor) || self.1.visit_with(visitor) || self.2.visit_with(visitor)
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.0.visit_with(visitor)?;
self.1.visit_with(visitor)?;
self.2.visit_with(visitor)
}
}
@ -773,7 +777,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
Rc::new((**self).fold_with(folder))
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
(**self).visit_with(visitor)
}
}
@ -783,7 +787,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> {
Arc::new((**self).fold_with(folder))
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
(**self).visit_with(visitor)
}
}
@ -794,7 +798,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
box content
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
(**self).visit_with(visitor)
}
}
@ -804,8 +808,8 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
self.iter().map(|t| t.fold_with(folder)).collect()
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|t| t.visit_with(visitor))
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
@ -814,8 +818,8 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> {
self.iter().map(|t| t.fold_with(folder)).collect::<Vec<_>>().into_boxed_slice()
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|t| t.visit_with(visitor))
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
@ -828,11 +832,11 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
folder.fold_binder(self)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.as_ref().skip_binder().visit_with(visitor)
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
visitor.visit_binder(self)
}
}
@ -842,8 +846,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>>
fold_list(*self, folder, |tcx, v| tcx.intern_existential_predicates(v))
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|p| p.visit_with(visitor))
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.iter().try_for_each(|p| p.visit_with(visitor))
}
}
@ -852,8 +856,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
fold_list(*self, folder, |tcx, v| tcx.intern_type_list(v))
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|t| t.visit_with(visitor))
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
@ -862,8 +866,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> {
fold_list(*self, folder, |tcx, v| tcx.intern_projs(v))
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|t| t.visit_with(visitor))
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
@ -888,20 +892,24 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
use crate::ty::InstanceDef::*;
self.substs.visit_with(visitor)
|| match self.def {
Item(def) => def.visit_with(visitor),
VtableShim(did) | ReifyShim(did) | Intrinsic(did) | Virtual(did, _) => {
did.visit_with(visitor)
}
FnPtrShim(did, ty) | CloneShim(did, ty) => {
did.visit_with(visitor) || ty.visit_with(visitor)
}
DropGlue(did, ty) => did.visit_with(visitor) || ty.visit_with(visitor),
ClosureOnceShim { call_once } => call_once.visit_with(visitor),
self.substs.visit_with(visitor)?;
match self.def {
Item(def) => def.visit_with(visitor),
VtableShim(did) | ReifyShim(did) | Intrinsic(did) | Virtual(did, _) => {
did.visit_with(visitor)
}
FnPtrShim(did, ty) | CloneShim(did, ty) => {
did.visit_with(visitor)?;
ty.visit_with(visitor)
}
DropGlue(did, ty) => {
did.visit_with(visitor)?;
ty.visit_with(visitor)
}
ClosureOnceShim { call_once } => call_once.visit_with(visitor),
}
}
}
@ -910,7 +918,7 @@ impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> {
Self { instance: self.instance.fold_with(folder), promoted: self.promoted }
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.instance.visit_with(visitor)
}
}
@ -959,19 +967,26 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
folder.fold_ty(*self)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
match self.kind() {
ty::RawPtr(ref tm) => tm.visit_with(visitor),
ty::Array(typ, sz) => typ.visit_with(visitor) || sz.visit_with(visitor),
ty::Array(typ, sz) => {
typ.visit_with(visitor)?;
sz.visit_with(visitor)
}
ty::Slice(typ) => typ.visit_with(visitor),
ty::Adt(_, substs) => substs.visit_with(visitor),
ty::Dynamic(ref trait_ty, ref reg) => {
trait_ty.visit_with(visitor) || reg.visit_with(visitor)
trait_ty.visit_with(visitor)?;
reg.visit_with(visitor)
}
ty::Tuple(ts) => ts.visit_with(visitor),
ty::FnDef(_, substs) => substs.visit_with(visitor),
ty::FnPtr(ref f) => f.visit_with(visitor),
ty::Ref(r, ty, _) => r.visit_with(visitor) || ty.visit_with(visitor),
ty::Ref(r, ty, _) => {
r.visit_with(visitor)?;
ty.visit_with(visitor)
}
ty::Generator(_did, ref substs, _) => substs.visit_with(visitor),
ty::GeneratorWitness(ref types) => types.visit_with(visitor),
ty::Closure(_did, ref substs) => substs.visit_with(visitor),
@ -990,11 +1005,11 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
| ty::Placeholder(..)
| ty::Param(..)
| ty::Never
| ty::Foreign(..) => false,
| ty::Foreign(..) => ControlFlow::CONTINUE,
}
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
visitor.visit_ty(self)
}
}
@ -1008,11 +1023,11 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
folder.fold_region(*self)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
false
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<(), ()> {
ControlFlow::CONTINUE
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
visitor.visit_region(*self)
}
}
@ -1023,11 +1038,11 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
folder.tcx().reuse_or_mk_predicate(*self, new)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
ty::PredicateKind::super_visit_with(&self.inner.kind, visitor)
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
visitor.visit_predicate(*self)
}
@ -1045,8 +1060,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
fold_list(*self, folder, |tcx, v| tcx.intern_predicates(v))
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|p| p.visit_with(visitor))
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.iter().try_for_each(|p| p.visit_with(visitor))
}
}
@ -1055,8 +1070,8 @@ impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T>
self.iter().map(|x| x.fold_with(folder)).collect()
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|t| t.visit_with(visitor))
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
@ -1075,11 +1090,12 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
folder.fold_const(*self)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.ty.visit_with(visitor) || self.val.visit_with(visitor)
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.ty.visit_with(visitor)?;
self.val.visit_with(visitor)
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
visitor.visit_const(self)
}
}
@ -1099,7 +1115,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
match *self {
ty::ConstKind::Infer(ic) => ic.visit_with(visitor),
ty::ConstKind::Param(p) => p.visit_with(visitor),
@ -1107,7 +1123,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
ty::ConstKind::Value(_)
| ty::ConstKind::Bound(..)
| ty::ConstKind::Placeholder(_)
| ty::ConstKind::Error(_) => false,
| ty::ConstKind::Error(_) => ControlFlow::CONTINUE,
}
}
}
@ -1117,8 +1133,8 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
false
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<(), ()> {
ControlFlow::CONTINUE
}
}

View File

@ -17,6 +17,7 @@ use std::fmt;
use std::marker::PhantomData;
use std::mem;
use std::num::NonZeroUsize;
use std::ops::ControlFlow;
/// An entity in the Rust type system, which can be one of
/// several kinds (types, lifetimes, and consts).
@ -159,7 +160,7 @@ impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> {
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
match self.unpack() {
GenericArgKind::Lifetime(lt) => lt.visit_with(visitor),
GenericArgKind::Type(ty) => ty.visit_with(visitor),
@ -391,8 +392,8 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|t| t.visit_with(visitor))
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<(), ()> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}