about summary refs log tree commit diff
path: root/compiler/rustc_middle/src
diff options
context:
space:
mode:
authorLeSeulArtichaut <leseulartichaut@gmail.com>2020-10-21 14:22:44 +0200
committerLeSeulArtichaut <leseulartichaut@gmail.com>2020-10-30 12:25:24 +0100
commit2c85b6fae0b2dbb1af91fd8c5fdd2c0140a43915 (patch)
treeb6eb98cc1cdcfabc2ae2cd563bdfee3db8ccdccb /compiler/rustc_middle/src
parent8df58ae03a8fda8ed126c02fbc16b530d18344df (diff)
downloadrust-2c85b6fae0b2dbb1af91fd8c5fdd2c0140a43915.tar.gz
rust-2c85b6fae0b2dbb1af91fd8c5fdd2c0140a43915.zip
TypeVisitor: use `std::ops::ControlFlow` instead of `bool`
Diffstat (limited to 'compiler/rustc_middle/src')
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/macros.rs18
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs103
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs123
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs7
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs4
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs128
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs7
9 files changed, 234 insertions, 161 deletions
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 5ccadb7e660..4b915fe020f 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -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]
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index 6ff0a94ebf3..7437443bed9 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -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)*
                 )
         )
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index a753732d364..9e1a53d9ed4 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -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.
     }
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 6aab54b9274..8eb7dc7559d 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -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,
+                match **kind {
+                    AggregateKind::Array(ty) => {
+                        ty.visit_with(visitor)?;
+                    }
+                    AggregateKind::Tuple => {}
                     AggregateKind::Adt(_, _, substs, user_ty, _) => {
-                        substs.visit_with(visitor) || user_ty.visit_with(visitor)
+                        substs.visit_with(visitor)?;
+                        user_ty.visit_with(visitor)?;
+                    }
+                    AggregateKind::Closure(_, substs) => {
+                        substs.visit_with(visitor)?;
                     }
-                    AggregateKind::Closure(_, substs) => substs.visit_with(visitor),
-                    AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor),
-                }) || fields.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)
     }
 }
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 0e5e22dcaae..4e42ee5aa1f 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -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
     }
 }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a400b85cdb7..871a2c2e710 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -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)
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 9735099a4e1..43305b8b572 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -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);
                 }
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 53521d0e9f3..0d14c37b254 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -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
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index f04144c218e..a4cb8943985 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -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))
     }
 }