diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 524efd04cfce9..b0d9daf3927c1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1498,7 +1498,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { if let Some((kind, def_id)) = TyCategory::from_ty(t) { let span = self.tcx.def_span(def_id); // Avoid cluttering the output when the "found" and error span overlap: diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index df3dbfca01d7a..7b0deb45f8684 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -474,7 +474,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { struct TraitObjectVisitor(Vec); impl TypeVisitor<'_> for TraitObjectVisitor { - fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<()> { + fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow { match t.kind() { ty::Dynamic(preds, RegionKind::ReStatic) => { if let Some(def_id) = preds.principal_def_id() { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index acded5351f80a..225582a2db6a5 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1,5 +1,3 @@ -//! See the Book for more information. - pub use self::freshen::TypeFreshener; pub use self::LateBoundRegionConversionTime::*; pub use self::RegionVariableOrigin::*; @@ -1334,9 +1332,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { where T: TypeFoldable<'tcx>, { - let mut r = resolve::UnresolvedTypeFinder::new(self); - value.visit_with(&mut r); - r.first_unresolved + value.visit_with(&mut resolve::UnresolvedTypeFinder::new(self)).break_value() } pub fn probe_const_var( diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 9b2ffc7a920b0..0b2847658f71e 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -741,7 +741,10 @@ struct ScopeInstantiator<'me, 'tcx> { } impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> { - fn visit_binder>(&mut self, t: &ty::Binder) -> ControlFlow<()> { + fn visit_binder>( + &mut self, + t: &ty::Binder, + ) -> ControlFlow { self.target_index.shift_in(1); t.super_visit_with(self); self.target_index.shift_out(1); @@ -749,7 +752,7 @@ impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> { ControlFlow::CONTINUE } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { let ScopeInstantiator { bound_region_scope, next_region, .. } = self; match r { diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index fe4ba5aa4e820..822fa77aa0ed0 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -111,19 +111,17 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> { /// involve some hashing and so forth). pub struct UnresolvedTypeFinder<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, - - /// Used to find the type parameter name and location for error reporting. - pub first_unresolved: Option<(Ty<'tcx>, Option)>, } impl<'a, 'tcx> UnresolvedTypeFinder<'a, 'tcx> { pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self { - UnresolvedTypeFinder { infcx, first_unresolved: None } + UnresolvedTypeFinder { infcx } } } impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> { + type BreakTy = (Ty<'tcx>, Option); + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { let t = self.infcx.shallow_resolve(t); if t.has_infer_types() { if let ty::Infer(infer_ty) = *t.kind() { @@ -144,8 +142,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> { } else { None }; - self.first_unresolved = Some((t, ty_var_span)); - ControlFlow::BREAK + ControlFlow::Break((t, ty_var_span)) } else { // Otherwise, visit its contents. t.super_visit_with(self) diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index 1a1c2637a6fa6..d6500f62e7851 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -69,7 +69,7 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx } } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.predicate.visit_with(visitor) } } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 467a3a425906f..aaedd53c0f611 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1131,16 +1131,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { struct ProhibitOpaqueTypes<'a, 'tcx> { cx: &'a LateContext<'tcx>, - ty: Option>, }; impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> { + type BreakTy = Ty<'tcx>; + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { match ty.kind() { - ty::Opaque(..) => { - self.ty = Some(ty); - ControlFlow::BREAK - } + ty::Opaque(..) => ControlFlow::Break(ty), // Consider opaque types within projections FFI-safe if they do not normalize // to more opaque types. ty::Projection(..) => { @@ -1159,9 +1157,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } } - let mut visitor = ProhibitOpaqueTypes { cx: self.cx, ty: None }; - ty.visit_with(&mut visitor); - if let Some(ty) = visitor.ty { + if let Some(ty) = ty.visit_with(&mut ProhibitOpaqueTypes { cx: self.cx }).break_value() { self.emit_ffi_unsafe_type_lint(ty, sp, "opaque types have no C equivalent", None); true } else { diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs index 8fa6e6a710108..18d7affa75dea 100644 --- a/compiler/rustc_macros/src/type_foldable.rs +++ b/compiler/rustc_macros/src/type_foldable.rs @@ -35,7 +35,7 @@ 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 - ) -> ::std::ops::ControlFlow<()> { + ) -> ::std::ops::ControlFlow<__F::BreakTy> { 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 4a1d5459d1eec..cdc5940d9baed 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -51,6 +51,7 @@ #![feature(half_open_range_patterns)] #![feature(exclusive_range_pattern)] #![feature(control_flow_enum)] +#![feature(associated_type_defaults)] #![recursion_limit = "512"] #[macro_use] diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index 921086366bea2..057f2615a44c6 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -62,7 +62,7 @@ macro_rules! CloneTypeFoldableImpls { fn super_visit_with>( &self, _: &mut F) - -> ::std::ops::ControlFlow<()> + -> ::std::ops::ControlFlow { ::std::ops::ControlFlow::CONTINUE } @@ -105,7 +105,7 @@ macro_rules! EnumTypeFoldableImpl { fn super_visit_with>( &self, visitor: &mut V, - ) -> ::std::ops::ControlFlow<()> { + ) -> ::std::ops::ControlFlow { EnumTypeFoldableImpl!(@VisitVariants(self, visitor) input($($variants)*) output()) } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 5fe7b0f647dcd..15783cfd00c5c 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2477,7 +2477,10 @@ impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection { UserTypeProjection { base, projs } } - fn super_visit_with>(&self, visitor: &mut Vs) -> ControlFlow<()> { + 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 0801188b27881..0e6bf0fd02971 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -87,7 +87,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { Terminator { source_info: self.source_info, kind } } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { use crate::mir::TerminatorKind::*; match self.kind { @@ -144,7 +144,7 @@ impl<'tcx> TypeFoldable<'tcx> for GeneratorKind { *self } - fn super_visit_with>(&self, _: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE } } @@ -154,7 +154,7 @@ 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) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.local.visit_with(visitor)?; self.projection.visit_with(visitor) } @@ -166,7 +166,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { folder.tcx().intern_place_elems(&v) } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } } @@ -216,7 +216,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { } } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { use crate::mir::Rvalue::*; match *self { Use(ref op) => op.visit_with(visitor), @@ -271,7 +271,7 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { } } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + 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), @@ -295,7 +295,10 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> { } } - fn super_visit_with>(&self, visitor: &mut Vs) -> ControlFlow<()> { + fn super_visit_with>( + &self, + visitor: &mut Vs, + ) -> ControlFlow { use crate::mir::ProjectionElem::*; match self { @@ -310,7 +313,7 @@ impl<'tcx> TypeFoldable<'tcx> for Field { fn super_fold_with>(&self, _: &mut F) -> Self { *self } - fn super_visit_with>(&self, _: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE } } @@ -319,7 +322,7 @@ impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal { fn super_fold_with>(&self, _: &mut F) -> Self { *self } - fn super_visit_with>(&self, _: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE } } @@ -328,7 +331,7 @@ 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) -> ControlFlow<()> { + fn super_visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE } } @@ -341,7 +344,7 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { literal: self.literal.fold_with(folder), } } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + 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 70a8157c04ac7..b1bfcf4491ad8 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -49,8 +49,8 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { self.super_fold_with(folder) } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()>; - fn visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow; + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.super_visit_with(visitor) } @@ -73,7 +73,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { } fn has_type_flags(&self, flags: TypeFlags) -> bool { - self.visit_with(&mut HasTypeFlagsVisitor { flags }).is_break() + self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags) } fn has_projections(&self) -> bool { self.has_type_flags(TypeFlags::HAS_PROJECTION) @@ -142,26 +142,13 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn still_further_specializable(&self) -> bool { self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE) } - - /// 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>) -> ControlFlow<()>) -> ControlFlow<()> { - pub struct Visitor(F); - - impl<'tcx, F: FnMut(Ty<'tcx>) -> ControlFlow<()>> TypeVisitor<'tcx> for Visitor { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> { - self.0(ty) - } - } - - self.visit_with(&mut Visitor(visit)) - } } impl TypeFoldable<'tcx> for hir::Constness { fn super_fold_with>(&self, _: &mut F) -> Self { *self } - fn super_visit_with>(&self, _: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE } } @@ -195,23 +182,25 @@ pub trait TypeFolder<'tcx>: Sized { } pub trait TypeVisitor<'tcx>: Sized { - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow<()> { + type BreakTy = !; + + fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { t.super_visit_with(self) } - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { t.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> { + 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>) -> ControlFlow<()> { + 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>) -> ControlFlow<()> { + fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow { p.super_visit_with(self) } } @@ -329,14 +318,19 @@ impl<'tcx> TyCtxt<'tcx> { where F: FnMut(ty::Region<'tcx>) -> bool, { - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow<()> { + type BreakTy = (); + + 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>) -> ControlFlow<()> { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => { ControlFlow::CONTINUE @@ -351,7 +345,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> { + 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) @@ -813,6 +807,9 @@ where value.fold_with(&mut Shifter::new(tcx, amount)) } +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +struct FoundEscapingVars; + /// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a /// bound region or a bound type. /// @@ -844,93 +841,114 @@ struct HasEscapingVarsVisitor { } impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow<()> { + type BreakTy = FoundEscapingVars; + + 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>) -> ControlFlow<()> { + 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. if t.outer_exclusive_binder > self.outer_index { - ControlFlow::BREAK + ControlFlow::Break(FoundEscapingVars) } else { ControlFlow::CONTINUE } } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> { + 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. if r.bound_at_or_above_binder(self.outer_index) { - ControlFlow::BREAK + ControlFlow::Break(FoundEscapingVars) } else { ControlFlow::CONTINUE } } - fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> ControlFlow<()> { + 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 => ControlFlow::BREAK, + ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => { + ControlFlow::Break(FoundEscapingVars) + } _ => ct.super_visit_with(self), } } - fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<()> { + fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow { if predicate.inner.outer_exclusive_binder > self.outer_index { - ControlFlow::BREAK + ControlFlow::Break(FoundEscapingVars) } else { ControlFlow::CONTINUE } } } +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +struct FoundFlags; + // FIXME: Optimize for checking for infer flags struct HasTypeFlagsVisitor { flags: ty::TypeFlags, } impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { - fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<()> { + type BreakTy = FoundFlags; + + fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow { debug!( "HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}", t, t.flags(), self.flags ); - if t.flags().intersects(self.flags) { ControlFlow::BREAK } else { ControlFlow::CONTINUE } + if t.flags().intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::CONTINUE + } } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> { + 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); - if flags.intersects(self.flags) { ControlFlow::BREAK } else { ControlFlow::CONTINUE } + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::CONTINUE + } } - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> { + 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); - if flags.intersects(self.flags) { ControlFlow::BREAK } else { ControlFlow::CONTINUE } + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::CONTINUE + } } - fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<()> { + fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow { debug!( "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}", predicate, predicate.inner.flags, self.flags ); if predicate.inner.flags.intersects(self.flags) { - ControlFlow::BREAK + ControlFlow::Break(FoundFlags) } else { ControlFlow::CONTINUE } @@ -964,14 +982,14 @@ impl LateBoundRegionsCollector { } impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow<()> { + 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>) -> ControlFlow<()> { + 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 @@ -984,7 +1002,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { t.super_visit_with(self) } - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> { + 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 @@ -997,7 +1015,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { c.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> { + 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); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 5e8a4a56db32c..47bb4c8797781 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1792,7 +1792,7 @@ 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) -> ControlFlow<()> { + 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 1e4fd0921ee0f..d4fad188e215d 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1796,7 +1796,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>) -> ControlFlow<()> { + 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 89fd803fe5140..d42a1b772a039 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -729,7 +729,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef { *self } - fn super_visit_with>(&self, _visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, _visitor: &mut V) -> ControlFlow { ControlFlow::CONTINUE } } @@ -739,7 +739,7 @@ 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) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.0.visit_with(visitor)?; self.1.visit_with(visitor) } @@ -752,7 +752,7 @@ 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) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.0.visit_with(visitor)?; self.1.visit_with(visitor)?; self.2.visit_with(visitor) @@ -778,7 +778,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc { Rc::new((**self).fold_with(folder)) } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { (**self).visit_with(visitor) } } @@ -788,7 +788,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc { Arc::new((**self).fold_with(folder)) } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { (**self).visit_with(visitor) } } @@ -799,7 +799,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box { box content } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { (**self).visit_with(visitor) } } @@ -809,7 +809,7 @@ 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) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } } @@ -819,7 +819,7 @@ 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) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } } @@ -833,11 +833,11 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { folder.fold_binder(self) } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.as_ref().skip_binder().visit_with(visitor) } - fn visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { visitor.visit_binder(self) } } @@ -847,7 +847,7 @@ 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) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|p| p.visit_with(visitor)) } } @@ -857,7 +857,7 @@ 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) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } } @@ -867,7 +867,7 @@ 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) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } } @@ -893,7 +893,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { } } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { use crate::ty::InstanceDef::*; self.substs.visit_with(visitor)?; match self.def { @@ -919,7 +919,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) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.instance.visit_with(visitor) } } @@ -968,7 +968,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { folder.fold_ty(*self) } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { match self.kind() { ty::RawPtr(ref tm) => tm.visit_with(visitor), ty::Array(typ, sz) => { @@ -1010,7 +1010,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { } } - fn visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { visitor.visit_ty(self) } } @@ -1024,11 +1024,11 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> { folder.fold_region(*self) } - fn super_visit_with>(&self, _visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, _visitor: &mut V) -> ControlFlow { ControlFlow::CONTINUE } - fn visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { visitor.visit_region(*self) } } @@ -1039,11 +1039,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) -> ControlFlow<()> { + 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) -> ControlFlow<()> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { visitor.visit_predicate(*self) } @@ -1061,7 +1061,7 @@ 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) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|p| p.visit_with(visitor)) } } @@ -1071,7 +1071,7 @@ 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) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } } @@ -1091,12 +1091,12 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { folder.fold_const(*self) } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + 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) -> ControlFlow<()> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { visitor.visit_const(self) } } @@ -1116,7 +1116,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { } } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + 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), @@ -1134,7 +1134,7 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> { *self } - fn super_visit_with>(&self, _visitor: &mut V) -> ControlFlow<()> { + 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 07f775cf8b1e5..343322cfe5830 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -160,7 +160,7 @@ impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> { } } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + 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), @@ -392,7 +392,7 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { } } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow<()> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } } diff --git a/compiler/rustc_mir/src/interpret/util.rs b/compiler/rustc_mir/src/interpret/util.rs index fce5553c99314..e49b1c9f64d44 100644 --- a/compiler/rustc_mir/src/interpret/util.rs +++ b/compiler/rustc_mir/src/interpret/util.rs @@ -18,7 +18,9 @@ where }; impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> { - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> { + type BreakTy = (); + + fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { if !c.needs_subst() { return ControlFlow::CONTINUE; } @@ -29,7 +31,7 @@ where } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { if !ty.needs_subst() { return ControlFlow::CONTINUE; } diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs index c2ebc954a22c0..0ce1c5a04893b 100644 --- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs +++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs @@ -250,7 +250,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { } impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { - fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<()> { + fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow { debug!("visit_const: c={:?}", c); if !c.has_param_types_or_consts() { return ControlFlow::CONTINUE; @@ -283,7 +283,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { debug!("visit_ty: ty={:?}", ty); if !ty.has_param_types_or_consts() { return ControlFlow::CONTINUE; @@ -318,7 +318,9 @@ struct HasUsedGenericParams<'a> { } impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> { - fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<()> { + type BreakTy = (); + + fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow { debug!("visit_const: c={:?}", c); if !c.has_param_types_or_consts() { return ControlFlow::CONTINUE; @@ -336,7 +338,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> { } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { debug!("visit_ty: ty={:?}", ty); if !ty.has_param_types_or_consts() { return ControlFlow::CONTINUE; diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index 8bee8417c51fa..cd60602b088f2 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -640,7 +640,7 @@ pub fn write_allocations<'tcx>( } struct CollectAllocIds(BTreeSet); impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds { - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> { + fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { if let ty::ConstKind::Value(val) = c.val { self.0.extend(alloc_ids_from_const(val)); } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 75d75433f1bf1..4a0d356d3377b 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -4,6 +4,7 @@ #![feature(or_patterns)] #![feature(control_flow_enum)] #![feature(try_blocks)] +#![feature(associated_type_defaults)] #![recursion_limit = "256"] use rustc_attr as attr; @@ -44,6 +45,8 @@ use std::{cmp, fmt, mem}; /// manually. Second, it doesn't visit some type components like signatures of fn types, or traits /// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`. trait DefIdVisitor<'tcx> { + type BreakTy = (); + fn tcx(&self) -> TyCtxt<'tcx>; fn shallow(&self) -> bool { false @@ -56,7 +59,7 @@ trait DefIdVisitor<'tcx> { def_id: DefId, kind: &str, descr: &dyn fmt::Display, - ) -> ControlFlow<()>; + ) -> ControlFlow; /// Not overridden, but used to actually visit types and traits. fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> { @@ -66,13 +69,16 @@ trait DefIdVisitor<'tcx> { dummy: Default::default(), } } - fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> ControlFlow<()> { + fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> ControlFlow { ty_fragment.visit_with(&mut self.skeleton()) } - fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<()> { + fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow { self.skeleton().visit_trait(trait_ref) } - fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> ControlFlow<()> { + fn visit_predicates( + &mut self, + predicates: ty::GenericPredicates<'tcx>, + ) -> ControlFlow { self.skeleton().visit_predicates(predicates) } } @@ -87,13 +93,13 @@ impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V> where V: DefIdVisitor<'tcx> + ?Sized, { - fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<()> { + fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow { let TraitRef { def_id, substs } = trait_ref; self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?; if self.def_id_visitor.shallow() { ControlFlow::CONTINUE } else { substs.visit_with(self) } } - fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<()> { + fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow { match predicate.skip_binders() { ty::PredicateAtom::Trait(ty::TraitPredicate { trait_ref }, _) => { self.visit_trait(trait_ref) @@ -119,7 +125,10 @@ where } } - fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> ControlFlow<()> { + fn visit_predicates( + &mut self, + predicates: ty::GenericPredicates<'tcx>, + ) -> ControlFlow { let ty::GenericPredicates { parent: _, predicates } = predicates; predicates.iter().try_for_each(|&(predicate, _span)| self.visit_predicate(predicate)) } @@ -129,7 +138,9 @@ impl<'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'tcx, V> where V: DefIdVisitor<'tcx> + ?Sized, { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> { + type BreakTy = V::BreakTy; + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { let tcx = self.def_id_visitor.tcx(); // InternalSubsts are not visited here because they are visited below in `super_visit_with`. match *ty.kind() { @@ -283,7 +294,7 @@ impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'tcx> for FindMin<'a, 'tcx, VL> def_id: DefId, _kind: &str, _descr: &dyn fmt::Display, - ) -> ControlFlow<()> { + ) -> ControlFlow { self.min = VL::new_min(self, def_id); ControlFlow::CONTINUE } @@ -902,7 +913,7 @@ impl DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { def_id: DefId, _kind: &str, _descr: &dyn fmt::Display, - ) -> ControlFlow<()> { + ) -> ControlFlow { if let Some(def_id) = def_id.as_local() { if let (ty::Visibility::Public, _) | (_, Some(AccessLevel::ReachableFromImplTrait)) = (self.tcx().visibility(def_id.to_def_id()), self.access_level) @@ -1299,7 +1310,7 @@ impl DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { def_id: DefId, kind: &str, descr: &dyn fmt::Display, - ) -> ControlFlow<()> { + ) -> ControlFlow { if self.check_def_id(def_id, kind, descr) { ControlFlow::BREAK } else { @@ -1799,7 +1810,7 @@ impl DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { def_id: DefId, kind: &str, descr: &dyn fmt::Display, - ) -> ControlFlow<()> { + ) -> ControlFlow { if self.check_def_id(def_id, kind, descr) { ControlFlow::BREAK } else { diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 37538e7aac495..49effe8060bca 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -692,12 +692,15 @@ impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder>(&mut self, t: &ty::Binder) -> ControlFlow<()> { + fn visit_binder>( + &mut self, + t: &ty::Binder, + ) -> ControlFlow { t.as_ref().skip_binder().visit_with(self); ControlFlow::CONTINUE } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { match *r { // ignore bound regions, keep visiting ty::ReLateBound(_, _) => ControlFlow::CONTINUE, @@ -708,7 +711,7 @@ where } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { // We're only interested in types involving regions if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) { return ControlFlow::CONTINUE; diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index e1721a5a88a76..fdb2361ba0360 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -78,7 +78,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( Concrete, } let mut failure_kind = FailureKind::Concrete; - walk_abstract_const(tcx, ct, |node| match node { + walk_abstract_const::(tcx, ct, |node| match node { Node::Leaf(leaf) => { let leaf = leaf.subst(tcx, ct.substs); if leaf.has_infer_types_or_consts() { @@ -574,19 +574,19 @@ pub(super) fn try_unify_abstract_consts<'tcx>( // on `ErrorReported`. } -pub fn walk_abstract_const<'tcx, F>( +pub fn walk_abstract_const<'tcx, R, F>( tcx: TyCtxt<'tcx>, ct: AbstractConst<'tcx>, mut f: F, -) -> ControlFlow<()> +) -> ControlFlow where - F: FnMut(Node<'tcx>) -> ControlFlow<()>, + F: FnMut(Node<'tcx>) -> ControlFlow, { - fn recurse<'tcx>( + fn recurse<'tcx, R>( tcx: TyCtxt<'tcx>, ct: AbstractConst<'tcx>, - f: &mut dyn FnMut(Node<'tcx>) -> ControlFlow<()>, - ) -> ControlFlow<()> { + f: &mut dyn FnMut(Node<'tcx>) -> ControlFlow, + ) -> ControlFlow { let root = ct.root(); f(root)?; match root { diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 32e0991733bd9..97253da051c41 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -771,7 +771,9 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( } impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> { + type BreakTy = (); + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { match t.kind() { ty::Param(_) => { if t == self.tcx.types.self_param { @@ -812,7 +814,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( } } - fn visit_const(&mut self, ct: &ty::Const<'tcx>) -> ControlFlow<()> { + fn visit_const(&mut self, ct: &ty::Const<'tcx>) -> ControlFlow { // First check if the type of this constant references `Self`. self.visit_ty(ct.ty)?; @@ -844,7 +846,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>( } } - fn visit_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ControlFlow<()> { + fn visit_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ControlFlow { if let ty::PredicateAtom::ConstEvaluatable(def, substs) = pred.skip_binders() { // FIXME(const_evaluatable_checked): We should probably deduplicate the logic for // `AbstractConst`s here, it might make sense to change `ConstEvaluatable` to diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index ce0d3ef8a6a58..3d20a8d5cf336 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -55,9 +55,7 @@ pub fn search_for_structural_match_violation<'tcx>( ) -> Option> { // FIXME: we should instead pass in an `infcx` from the outside. tcx.infer_ctxt().enter(|infcx| { - let mut search = Search { infcx, span, found: None, seen: FxHashSet::default() }; - ty.visit_with(&mut search); - search.found + ty.visit_with(&mut Search { infcx, span, seen: FxHashSet::default() }).break_value() }) } @@ -116,9 +114,6 @@ struct Search<'a, 'tcx> { infcx: InferCtxt<'a, 'tcx>, - /// Records first ADT that does not implement a structural-match trait. - found: Option>, - /// Tracks ADTs previously encountered during search, so that /// we will not recur on them again. seen: FxHashSet, @@ -135,38 +130,33 @@ impl Search<'a, 'tcx> { } impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> { + type BreakTy = NonStructuralMatchTy<'tcx>; + + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { debug!("Search visiting ty: {:?}", ty); let (adt_def, substs) = match *ty.kind() { ty::Adt(adt_def, substs) => (adt_def, substs), ty::Param(_) => { - self.found = Some(NonStructuralMatchTy::Param); - return ControlFlow::BREAK; + return ControlFlow::Break(NonStructuralMatchTy::Param); } ty::Dynamic(..) => { - self.found = Some(NonStructuralMatchTy::Dynamic); - return ControlFlow::BREAK; + return ControlFlow::Break(NonStructuralMatchTy::Dynamic); } ty::Foreign(_) => { - self.found = Some(NonStructuralMatchTy::Foreign); - return ControlFlow::BREAK; + return ControlFlow::Break(NonStructuralMatchTy::Foreign); } ty::Opaque(..) => { - self.found = Some(NonStructuralMatchTy::Opaque); - return ControlFlow::BREAK; + return ControlFlow::Break(NonStructuralMatchTy::Opaque); } ty::Projection(..) => { - self.found = Some(NonStructuralMatchTy::Projection); - return ControlFlow::BREAK; + return ControlFlow::Break(NonStructuralMatchTy::Projection); } ty::Generator(..) | ty::GeneratorWitness(..) => { - self.found = Some(NonStructuralMatchTy::Generator); - return ControlFlow::BREAK; + return ControlFlow::Break(NonStructuralMatchTy::Generator); } ty::Closure(..) => { - self.found = Some(NonStructuralMatchTy::Closure); - return ControlFlow::BREAK; + return ControlFlow::Break(NonStructuralMatchTy::Closure); } ty::RawPtr(..) => { // structural-match ignores substructure of @@ -206,8 +196,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => { // First check all contained types and then tell the caller to continue searching. - ty.super_visit_with(self); - return ControlFlow::CONTINUE; + return ty.super_visit_with(self); } ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => { bug!("unexpected type during structural-match checking: {:?}", ty); @@ -227,8 +216,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { if !self.type_marked_structural(ty) { debug!("Search found ty: {:?}", ty); - self.found = Some(NonStructuralMatchTy::Adt(&adt_def)); - return ControlFlow::BREAK; + return ControlFlow::Break(NonStructuralMatchTy::Adt(&adt_def)); } // structural-match does not care about the @@ -244,20 +232,11 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> { // even though we skip super_visit_with, we must recur on // fields of ADT. let tcx = self.tcx(); - for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) { + adt_def.all_fields().map(|field| field.ty(tcx, substs)).try_for_each(|field_ty| { let ty = self.tcx().normalize_erasing_regions(ty::ParamEnv::empty(), field_ty); debug!("structural-match ADT: field_ty={:?}, ty={:?}", field_ty, ty); - - if ty.visit_with(self).is_break() { - // found an ADT without structural-match; halt visiting! - assert!(self.found.is_some()); - return ControlFlow::BREAK; - } - } - - // Even though we do not want to recur on substs, we do - // want our caller to continue its own search. - ControlFlow::CONTINUE + ty.visit_with(self) + }) } } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index c4e2c7f839d70..4c616ccc08676 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -859,14 +859,14 @@ impl<'tcx> BoundVarsCollector<'tcx> { } impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { - fn visit_binder>(&mut self, t: &Binder) -> ControlFlow<()> { + fn visit_binder>(&mut self, t: &Binder) -> ControlFlow { self.binder_index.shift_in(1); let result = t.super_visit_with(self); self.binder_index.shift_out(1); result } - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { match *t.kind() { ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { match self.parameters.entry(bound_ty.var.as_u32()) { @@ -886,7 +886,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { t.super_visit_with(self) } - fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<()> { + fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow { match r { ty::ReLateBound(index, br) if *index == self.binder_index => match br { ty::BoundRegion::BrNamed(def_id, _name) => { @@ -1076,7 +1076,7 @@ impl PlaceholdersCollector { } impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { match t.kind() { ty::Placeholder(p) if p.universe == self.universe_index => { self.next_ty_placeholder = self.next_ty_placeholder.max(p.name.as_usize() + 1); @@ -1088,7 +1088,7 @@ impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector { t.super_visit_with(self) } - fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<()> { + fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow { match r { ty::RePlaceholder(p) if p.universe == self.universe_index => { if let ty::BoundRegion::BrAnon(anon) = p.name { diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 70d94ef869d05..9755e499e29c9 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -446,24 +446,24 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( struct ProhibitOpaqueVisitor<'tcx> { opaque_identity_ty: Ty<'tcx>, generics: &'tcx ty::Generics, - ty: Option>, }; impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> { + type BreakTy = Option>; + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t); if t != self.opaque_identity_ty && t.super_visit_with(self).is_break() { - self.ty = Some(t); - return ControlFlow::BREAK; + return ControlFlow::Break(Some(t)); } ControlFlow::CONTINUE } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { debug!("check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}", r); if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r { if *index < self.generics.parent_count as u32 { - return ControlFlow::BREAK; + return ControlFlow::Break(None); } else { return ControlFlow::CONTINUE; } @@ -472,7 +472,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( r.super_visit_with(self) } - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> { + fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { if let ty::ConstKind::Unevaluated(..) = c.val { // FIXME(#72219) We currenctly don't detect lifetimes within substs // which would violate this check. Even though the particular substitution is not used @@ -494,18 +494,17 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( InternalSubsts::identity_for_item(tcx, def_id.to_def_id()), ), generics: tcx.generics_of(def_id), - ty: None, }; let prohibit_opaque = tcx .explicit_item_bounds(def_id) .iter() - .any(|(predicate, _)| predicate.visit_with(&mut visitor).is_break()); + .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor)); debug!( "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor={:?}", prohibit_opaque, visitor ); - if prohibit_opaque { + if let Some(ty) = prohibit_opaque.break_value() { let is_async = match item.kind { ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => match origin { hir::OpaqueTyOrigin::AsyncFn => true, @@ -525,7 +524,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) { if snippet == "Self" { - if let Some(ty) = visitor.ty { + if let Some(ty) = ty { err.span_suggestion( span, "consider spelling out the type instead", @@ -1455,7 +1454,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) { { struct VisitTypes(Vec); impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { match *t.kind() { ty::Opaque(def, _) => { self.0.push(def); diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index 247b525672603..8e69df734e6f8 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -983,7 +983,7 @@ fn suggest_constraining_param( struct TypeParamVisitor<'tcx>(Vec>); impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<()> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { if let ty::Param(_) = ty.kind() { self.0.push(ty); } diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 1e27357ce4414..7d58f2cf34c0d 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -800,18 +800,20 @@ fn check_where_clauses<'tcx, 'fcx>( params: FxHashSet, } impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> { + type BreakTy = (); + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { if let ty::Param(param) = t.kind() { self.params.insert(param.index); } t.super_visit_with(self) } - fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<()> { + fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow { ControlFlow::BREAK } - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> { + fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { if let ty::ConstKind::Param(param) = c.val { self.params.insert(param.index); } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index b431de9036944..7779794b9db7d 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2062,7 +2062,7 @@ fn const_evaluatable_predicates_of<'tcx>( } impl<'a, 'tcx> TypeVisitor<'tcx> for TyAliasVisitor<'a, 'tcx> { - fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> ControlFlow<()> { + fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> ControlFlow { if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val { self.preds.insert(( ty::PredicateAtom::ConstEvaluatable(def, substs).to_predicate(self.tcx), diff --git a/compiler/rustc_typeck/src/constrained_generic_params.rs b/compiler/rustc_typeck/src/constrained_generic_params.rs index bae5bde70026f..e389fd4d9f00f 100644 --- a/compiler/rustc_typeck/src/constrained_generic_params.rs +++ b/compiler/rustc_typeck/src/constrained_generic_params.rs @@ -57,7 +57,7 @@ struct ParameterCollector { } impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<()> { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { match *t.kind() { ty::Projection(..) | ty::Opaque(..) if !self.include_nonconstraining => { // projections are not injective @@ -72,14 +72,14 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { t.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<()> { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { if let ty::ReEarlyBound(data) = *r { self.parameters.push(Parameter::from(data)); } ControlFlow::CONTINUE } - fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<()> { + fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow { match c.val { ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => { // Constant expressions are not injective diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index b4a9804fb25a5..602facbe062ac 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -563,7 +563,9 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> { struct ContainsRegion; impl TypeVisitor<'_> for ContainsRegion { - fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<()> { + type BreakTy = (); + + fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow { ControlFlow::BREAK } }