diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs index 6931e6552ad..7aab3fe4c3a 100644 --- a/compiler/rustc_macros/src/type_foldable.rs +++ b/compiler/rustc_macros/src/type_foldable.rs @@ -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 } }, ) 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>( &self, _: &mut F) - -> bool + -> ::std::ops::ControlFlow<(), ()> { - false + ::std::ops::ControlFlow::CONTINUE } } )+ @@ -105,7 +105,7 @@ macro_rules! EnumTypeFoldableImpl { fn super_visit_with>( &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>(&self, visitor: &mut Vs) -> bool { + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&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>(&self, _: &mut V) -> bool { - false + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { - self.local.visit_with(visitor) || self.projection.visit_with(visitor) + fn super_visit_with>(&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> { folder.tcx().intern_place_elems(&v) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&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>(&self, visitor: &mut Vs) -> bool { + fn super_visit_with>(&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>(&self, _: &mut F) -> Self { *self } - fn super_visit_with>(&self, _: &mut V) -> bool { - false + fn super_visit_with>(&self, _: &mut V) -> ControlFlow<(), ()> { + ControlFlow::CONTINUE } } @@ -301,8 +322,8 @@ impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal { fn super_fold_with>(&self, _: &mut F) -> Self { *self } - fn super_visit_with>(&self, _: &mut V) -> bool { - false + fn super_visit_with>(&self, _: &mut V) -> ControlFlow<(), ()> { + ControlFlow::CONTINUE } } @@ -310,8 +331,8 @@ impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix { fn super_fold_with>(&self, _: &mut F) -> Self { self.clone() } - fn super_visit_with>(&self, _: &mut V) -> bool { - false + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool; - fn visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<(), ()>; + fn visit_with>(&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); - impl<'tcx, F: FnMut(Ty<'tcx>) -> bool> TypeVisitor<'tcx> for Visitor { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + impl<'tcx, F: FnMut(Ty<'tcx>) -> ControlFlow<(), ()>> TypeVisitor<'tcx> for Visitor { + 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>(&self, _: &mut F) -> Self { *self } - fn super_visit_with>(&self, _: &mut V) -> bool { - false + fn super_visit_with>(&self, _: &mut V) -> ControlFlow<(), ()> { + ControlFlow::CONTINUE } } @@ -194,23 +199,23 @@ pub trait TypeFolder<'tcx>: Sized { } pub trait TypeVisitor<'tcx>: Sized { - fn visit_binder>(&mut self, t: &Binder) -> bool { + fn visit_binder>(&mut self, t: &Binder) -> 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 { /// 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>(&mut self, t: &Binder) -> bool { + fn visit_binder>( + &mut self, + t: &Binder, + ) -> 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>(&mut self, t: &Binder) -> bool { + fn visit_binder>(&mut self, t: &Binder) -> 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>(&mut self, t: &Binder) -> bool { + fn visit_binder>(&mut self, t: &Binder) -> 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>(&self, visitor: &mut V) -> bool { - self.caller_bounds().visit_with(visitor) || self.reveal().visit_with(visitor) + fn super_visit_with>(&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 FmtPrinter<'_, 'tcx, F> { { struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet); 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>(&self, _visitor: &mut V) -> bool { - false + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { - self.0.visit_with(visitor) || self.1.visit_with(visitor) + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { - self.0.visit_with(visitor) || self.1.visit_with(visitor) || self.2.visit_with(visitor) + fn super_visit_with>(&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 { Rc::new((**self).fold_with(folder)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<(), ()> { (**self).visit_with(visitor) } } @@ -783,7 +787,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc { Arc::new((**self).fold_with(folder)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<(), ()> { (**self).visit_with(visitor) } } @@ -794,7 +798,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box { box content } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<(), ()> { (**self).visit_with(visitor) } } @@ -804,8 +808,8 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec { self.iter().map(|t| t.fold_with(folder)).collect() } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_visit_with>(&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::>().into_boxed_slice() } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_visit_with>(&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 { folder.fold_binder(self) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<(), ()> { self.as_ref().skip_binder().visit_with(visitor) } - fn visit_with>(&self, visitor: &mut V) -> bool { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow<(), ()> { visitor.visit_binder(self) } } @@ -842,8 +846,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> fold_list(*self, folder, |tcx, v| tcx.intern_existential_predicates(v)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|p| p.visit_with(visitor)) + fn super_visit_with>(&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> { fold_list(*self, folder, |tcx, v| tcx.intern_type_list(v)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_visit_with>(&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 { fold_list(*self, folder, |tcx, v| tcx.intern_projs(v)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { + fn visit_with>(&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>(&self, _visitor: &mut V) -> bool { - false + fn super_visit_with>(&self, _visitor: &mut V) -> ControlFlow<(), ()> { + ControlFlow::CONTINUE } - fn visit_with>(&self, visitor: &mut V) -> bool { + fn visit_with>(&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>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<(), ()> { ty::PredicateKind::super_visit_with(&self.inner.kind, visitor) } - fn visit_with>(&self, visitor: &mut V) -> bool { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow<(), ()> { visitor.visit_predicate(*self) } @@ -1045,8 +1060,8 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fold_list(*self, folder, |tcx, v| tcx.intern_predicates(v)) } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|p| p.visit_with(visitor)) + fn super_visit_with>(&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 self.iter().map(|x| x.fold_with(folder)).collect() } - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { - self.ty.visit_with(visitor) || self.val.visit_with(visitor) + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<(), ()> { + self.ty.visit_with(visitor)?; + self.val.visit_with(visitor) } - fn visit_with>(&self, visitor: &mut V) -> bool { + fn visit_with>(&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>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&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>(&self, _visitor: &mut V) -> bool { - false + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { + fn super_visit_with>(&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>(&self, visitor: &mut V) -> bool { - self.iter().any(|t| t.visit_with(visitor)) + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<(), ()> { + self.iter().try_for_each(|t| t.visit_with(visitor)) } }