diff --git a/Cargo.lock b/Cargo.lock index 5feb21a65b774..635146492b042 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3970,6 +3970,7 @@ version = "0.0.0" dependencies = [ "itertools 0.11.0", "rustc_ast", + "rustc_ast_ir", "rustc_attr", "rustc_data_structures", "rustc_errors", @@ -4038,6 +4039,7 @@ dependencies = [ name = "rustc_infer" version = "0.0.0" dependencies = [ + "rustc_ast_ir", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -4632,6 +4634,7 @@ dependencies = [ "bitflags 2.4.2", "itertools 0.11.0", "rustc_ast", + "rustc_ast_ir", "rustc_attr", "rustc_data_structures", "rustc_errors", @@ -4670,6 +4673,7 @@ name = "rustc_transmute" version = "0.0.0" dependencies = [ "itertools 0.11.0", + "rustc_ast_ir", "rustc_data_structures", "rustc_hir", "rustc_infer", @@ -4685,6 +4689,7 @@ name = "rustc_ty_utils" version = "0.0.0" dependencies = [ "itertools 0.11.0", + "rustc_ast_ir", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index f29022386a9d3..9efb87e53cde9 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -15,11 +15,12 @@ use crate::ast::*; -use core::ops::ControlFlow; - use rustc_span::symbol::Ident; use rustc_span::Span; +pub use rustc_ast_ir::visit::VisitorResult; +pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list}; + #[derive(Copy, Clone, Debug, PartialEq)] pub enum AssocCtxt { Trait, @@ -101,51 +102,6 @@ pub enum LifetimeCtxt { GenericArg, } -/// Similar to the `Try` trait, but also implemented for `()`. -pub trait VisitorResult { - type Residual; - fn output() -> Self; - fn from_residual(residual: Self::Residual) -> Self; - fn branch(self) -> ControlFlow; -} - -impl VisitorResult for () { - type Residual = !; - - fn output() -> Self {} - fn from_residual(_: !) -> Self {} - fn branch(self) -> ControlFlow { - ControlFlow::Continue(()) - } -} - -impl VisitorResult for ControlFlow { - type Residual = T; - - fn output() -> Self { - ControlFlow::Continue(()) - } - fn from_residual(residual: Self::Residual) -> Self { - ControlFlow::Break(residual) - } - fn branch(self) -> ControlFlow { - self - } -} - -#[macro_export] -macro_rules! try_visit { - ($e:expr) => { - match $crate::visit::VisitorResult::branch($e) { - core::ops::ControlFlow::Continue(()) => (), - #[allow(unreachable_code)] - core::ops::ControlFlow::Break(r) => { - return $crate::visit::VisitorResult::from_residual(r); - } - } - }; -} - /// Each method of the `Visitor` trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; @@ -316,24 +272,6 @@ pub trait Visitor<'ast>: Sized { } } -#[macro_export] -macro_rules! walk_list { - ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => { - for elem in $list { - $crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?)); - } - } -} - -#[macro_export] -macro_rules! visit_opt { - ($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => { - if let Some(x) = $opt { - $crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?)); - } - } -} - pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result { walk_list!(visitor, visit_item, &krate.items); walk_list!(visitor, visit_attribute, &krate.attrs); diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs index 9fe1370921345..ff7a155204716 100644 --- a/compiler/rustc_ast_ir/src/lib.rs +++ b/compiler/rustc_ast_ir/src/lib.rs @@ -1,3 +1,4 @@ +#![cfg_attr(feature = "nightly", feature(never_type))] #![cfg_attr(feature = "nightly", feature(rustc_attrs))] #![cfg_attr(feature = "nightly", allow(internal_features))] @@ -5,6 +6,8 @@ #[macro_use] extern crate rustc_macros; +pub mod visit; + /// The movability of a coroutine / closure literal: /// whether a coroutine contains self-references, causing it to be `!Unpin`. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] diff --git a/compiler/rustc_ast_ir/src/visit.rs b/compiler/rustc_ast_ir/src/visit.rs new file mode 100644 index 0000000000000..dec9f7a47d09d --- /dev/null +++ b/compiler/rustc_ast_ir/src/visit.rs @@ -0,0 +1,82 @@ +use core::ops::ControlFlow; + +/// Similar to the `Try` trait, but also implemented for `()`. +pub trait VisitorResult { + type Residual; + fn output() -> Self; + fn from_residual(residual: Self::Residual) -> Self; + fn from_branch(b: ControlFlow) -> Self; + fn branch(self) -> ControlFlow; +} + +impl VisitorResult for () { + #[cfg(feature = "nightly")] + type Residual = !; + + #[cfg(not(feature = "nightly"))] + type Residual = core::ops::Infallible; + + fn output() -> Self {} + fn from_residual(_: Self::Residual) -> Self {} + fn from_branch(_: ControlFlow) -> Self {} + fn branch(self) -> ControlFlow { + ControlFlow::Continue(()) + } +} + +impl VisitorResult for ControlFlow { + type Residual = T; + + fn output() -> Self { + ControlFlow::Continue(()) + } + fn from_residual(residual: Self::Residual) -> Self { + ControlFlow::Break(residual) + } + fn from_branch(b: Self) -> Self { + b + } + fn branch(self) -> Self { + self + } +} + +#[macro_export] +macro_rules! try_visit { + ($e:expr) => { + match $crate::visit::VisitorResult::branch($e) { + core::ops::ControlFlow::Continue(()) => (), + #[allow(unreachable_code)] + core::ops::ControlFlow::Break(r) => { + return $crate::visit::VisitorResult::from_residual(r); + } + } + }; +} + +#[macro_export] +macro_rules! visit_opt { + ($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => { + if let Some(x) = $opt { + $crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?)); + } + } +} + +#[macro_export] +macro_rules! walk_list { + ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => { + for elem in $list { + $crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?)); + } + } +} + +#[macro_export] +macro_rules! walk_visitable_list { + ($visitor: expr, $list: expr $(, $($extra_args: expr),* )?) => { + for elem in $list { + $crate::try_visit!(elem.visit_with($visitor $(, $($extra_args,)* )?)); + } + } +} diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 8921883d94e3a..5321ba8a7cbab 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -8,8 +8,7 @@ use itertools::{Either, Itertools}; use rustc_ast::ptr::P; -use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; -use rustc_ast::walk_list; +use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxIndexMap; diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 386d4a54b655b..fae0e1d380c0c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -2,7 +2,8 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::errors; use rustc_ast as ast; -use rustc_ast::{attr, walk_list, EnumDef, VariantData}; +use rustc_ast::visit::walk_list; +use rustc_ast::{attr, EnumDef, VariantData}; use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt}; use rustc_span::symbol::Ident; use rustc_span::symbol::{kw, sym}; diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 2a13671a82978..3427368421f8e 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -30,9 +30,9 @@ where } impl<'tcx> TypeVisitor> for UsedParamsNeedInstantiationVisitor<'tcx> { - type BreakTy = FoundParam; + type Result = ControlFlow; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if !ty.has_param() { return ControlFlow::Continue(()); } @@ -64,7 +64,7 @@ where } } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result { match c.kind() { ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam), _ => c.super_visit_with(self), diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index c98dc4deb7579..0b41b4f96820b 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -17,7 +17,7 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt}; use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor}; use std::mem; -use std::ops::{ControlFlow, Deref}; +use std::ops::Deref; use super::ops::{self, NonConstOp, Status}; use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop}; @@ -164,9 +164,9 @@ struct LocalReturnTyVisitor<'ck, 'mir, 'tcx> { } impl<'ck, 'mir, 'tcx> TypeVisitor> for LocalReturnTyVisitor<'ck, 'mir, 'tcx> { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { - ty::FnPtr(_) => ControlFlow::Continue(()), + ty::FnPtr(_) => {} ty::Ref(_, _, hir::Mutability::Mut) => { self.checker.check_op(ops::ty::MutRef(self.kind)); t.super_visit_with(self) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 9d6daf1f47fbe..169973200aafa 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -14,8 +14,7 @@ use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult}; -use rustc_ast::{try_visit, walk_list}; +use rustc_ast::visit::{self, try_visit, walk_list, AssocCtxt, Visitor, VisitorResult}; use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind}; use rustc_ast::{ForeignItemKind, HasAttrs, HasNodeId}; use rustc_ast::{Inline, ItemKind, MacStmtStyle, MetaItemKind, ModKind}; diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 1c38a45d3a32f..88e0238b5235e 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -65,8 +65,7 @@ //! example coroutine inference, and possibly also HIR borrowck. use crate::hir::*; -use rustc_ast::visit::VisitorResult; -use rustc_ast::{try_visit, visit_opt, walk_list}; +use rustc_ast::visit::{try_visit, visit_opt, walk_list, VisitorResult}; use rustc_ast::{Attribute, Label}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{Ident, Symbol}; diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 9421d9b5ae0bd..298bff9984444 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1474,15 +1474,14 @@ fn opaque_type_cycle_error( closures: Vec, } impl<'tcx> ty::visit::TypeVisitor> for OpaqueTypeCollector { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match *t.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { self.opaques.push(def); - ControlFlow::Continue(()) } ty::Closure(def_id, ..) | ty::Coroutine(def_id, ..) => { self.closures.push(def_id); - t.super_visit_with(self) + t.super_visit_with(self); } _ => t.super_visit_with(self), } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 29dc434ab4532..8c4c4fc774ec8 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -12,7 +12,6 @@ use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{ elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt, }; -use std::ops::ControlFlow; /// Check that an implementation does not refine an RPITIT from a trait method signature. pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( @@ -211,9 +210,7 @@ struct ImplTraitInTraitCollector<'tcx> { } impl<'tcx> TypeVisitor> for ImplTraitInTraitCollector<'tcx> { - type BreakTy = !; - - fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { if let ty::Alias(ty::Projection, proj) = *ty.kind() && self.tcx.is_impl_trait_in_trait(proj.def_id) { @@ -223,12 +220,11 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitCollector<'tcx> { .explicit_item_bounds(proj.def_id) .iter_instantiated_copied(self.tcx, proj.args) { - pred.visit_with(self)?; + pred.visit_with(self); } } - ControlFlow::Continue(()) } else { - ty.super_visit_with(self) + ty.super_visit_with(self); } } } diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 0f5fd7e99b776..2a4dd6b0e0ef3 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -6,7 +6,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html -use rustc_ast::walk_list; +use rustc_ast::visit::walk_list; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f03d0f8a88529..bec7b7bd9742d 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -809,9 +809,7 @@ impl<'tcx> GATArgsCollector<'tcx> { } impl<'tcx> TypeVisitor> for GATArgsCollector<'tcx> { - type BreakTy = !; - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { ty::Alias(ty::Projection, p) if p.def_id == self.gat => { for (idx, arg) in p.args.iter().enumerate() { @@ -1456,20 +1454,19 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id params: FxHashSet, } impl<'tcx> ty::visit::TypeVisitor> for CountParams { - type BreakTy = (); - - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + type Result = ControlFlow<()>; + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { 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>) -> Self::Result { ControlFlow::Break(()) } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result { if let ty::ConstKind::Param(param) = c.kind() { self.params.insert(param.index); } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index ae01bf845751a..ad8ec1036efee 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -6,7 +6,7 @@ //! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file //! is also responsible for assigning their semantics to implicit lifetimes in trait objects. -use rustc_ast::walk_list; +use rustc_ast::visit::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir as hir; @@ -1964,31 +1964,26 @@ fn is_late_bound_map( arg_is_constrained: Box<[bool]>, } - use std::ops::ControlFlow; use ty::Ty; impl<'tcx> TypeVisitor> for ConstrainedCollectorPostAstConv { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { ty::Param(param_ty) => { self.arg_is_constrained[param_ty.index as usize] = true; } - ty::Alias(ty::Projection | ty::Inherent, _) => return ControlFlow::Continue(()), + ty::Alias(ty::Projection | ty::Inherent, _) => return, _ => (), } t.super_visit_with(self) } - fn visit_const(&mut self, _: ty::Const<'tcx>) -> ControlFlow { - ControlFlow::Continue(()) - } + fn visit_const(&mut self, _: ty::Const<'tcx>) {} - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { debug!("r={:?}", r.kind()); if let ty::RegionKind::ReEarlyParam(region) = r.kind() { self.arg_is_constrained[region.index as usize] = true; } - - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index b8de2e46934dd..3b8bb0731fbd8 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -1,9 +1,8 @@ use rustc_data_structures::fx::FxHashSet; -use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; +use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; use rustc_type_ir::fold::TypeFoldable; -use std::ops::ControlFlow; #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct Parameter(pub u32); @@ -61,13 +60,13 @@ struct ParameterCollector { } impl<'tcx> TypeVisitor> for ParameterCollector { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match *t.kind() { // Projections are not injective in general. ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) if !self.include_nonconstraining => { - return ControlFlow::Continue(()); + return; } // All weak alias types should've been expanded beforehand. ty::Alias(ty::Weak, _) if !self.include_nonconstraining => { @@ -80,18 +79,17 @@ impl<'tcx> TypeVisitor> 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>) { if let ty::ReEarlyParam(data) = *r { self.parameters.push(Parameter::from(data)); } - ControlFlow::Continue(()) } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) { match c.kind() { ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => { // Constant expressions are not injective in general. - return c.ty().visit_with(self); + return; } ty::ConstKind::Param(data) => { self.parameters.push(Parameter::from(data)); diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 4d5dcbadc4a24..9618c6d8011ff 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -10,7 +10,6 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable}; -use std::ops::ControlFlow; /// Defines the `TermsContext` basically houses an arena where we can /// allocate terms. @@ -89,15 +88,14 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> { #[instrument(level = "trace", skip(self), ret)] - fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> ControlFlow { + fn visit_opaque(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) { if def_id != self.root_def_id && self.tcx.is_descendant_of(def_id, self.root_def_id) { let child_variances = self.tcx.variances_of(def_id); for (a, v) in args.iter().zip_eq(child_variances) { if *v != ty::Bivariant { - a.visit_with(self)?; + a.visit_with(self); } } - ControlFlow::Continue(()) } else { args.visit_with(self) } @@ -106,20 +104,19 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc impl<'tcx> ty::TypeVisitor> for OpaqueTypeLifetimeCollector<'tcx> { #[instrument(level = "trace", skip(self), ret)] - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::RegionKind::ReEarlyParam(ebr) = r.kind() { self.variances[ebr.index as usize] = ty::Invariant; } - ControlFlow::Continue(()) } #[instrument(level = "trace", skip(self), ret)] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { ty::Alias(_, ty::AliasTy { def_id, args, .. }) if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) => { - self.visit_opaque(*def_id, args) + self.visit_opaque(*def_id, args); } _ => t.super_visit_with(self), } diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 975f93756427e..0a5fa37ed04fa 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" # tidy-alphabetical-start itertools = "0.11" rustc_ast = { path = "../rustc_ast" } +rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 5bdd9412d0e51..b8078413611f5 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -396,9 +396,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty: Ty<'tcx>, } impl<'tcx> TypeVisitor> for MentionsTy<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if t == self.expected_ty { ControlFlow::Break(()) } else { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index f0631dd4b5fb8..a9a5a89a41363 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -337,8 +337,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Option> { struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId); impl<'tcx> TypeVisitor> for FindAmbiguousParameter<'_, 'tcx> { - type BreakTy = ty::GenericArg<'tcx>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { + type Result = ControlFlow>; + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if let Some(origin) = self.0.type_var_origin(ty) && let TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind && let generics = self.0.tcx.generics_of(self.1) diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 73a02a431dfc0..c1565a7d40fd5 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -8,6 +8,7 @@ doctest = false [dependencies] # tidy-alphabetical-start +rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 342f18a18dcc2..362ca3b4833ea 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -79,7 +79,7 @@ use rustc_middle::ty::{ use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; use std::borrow::Cow; -use std::ops::{ControlFlow, Deref}; +use std::ops::Deref; use std::path::PathBuf; use std::{cmp, fmt, iter}; @@ -1623,7 +1623,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } impl<'tcx> ty::visit::TypeVisitor> for OpaqueTypesVisitor<'tcx> { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, 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 33538309b042a..adde45f081afe 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 @@ -23,7 +23,6 @@ use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_span::def_id::LocalDefId; -use std::ops::ControlFlow; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the return type is a static `impl Trait`, @@ -545,13 +544,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { pub struct TraitObjectVisitor(pub FxIndexSet); impl<'tcx> TypeVisitor> for TraitObjectVisitor { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { ty::Dynamic(preds, re, _) if re.is_static() => { if let Some(def_id) = preds.principal_def_id() { self.0.insert(def_id); } - ControlFlow::Continue(()) } _ => t.super_visit_with(self), } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index ded628fe13663..b4cf727bf8f1a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -16,8 +16,6 @@ use rustc_middle::ty::print::RegionHighlightMode; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; use rustc_span::Span; -use std::ops::ControlFlow; - impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`. pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option { @@ -76,12 +74,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } impl<'tcx> ty::visit::TypeVisitor> for HighlightBuilder<'tcx> { - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if !r.has_name() && self.counter <= 3 { self.highlight.highlighting_region(r, self.counter); self.counter += 1; } - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 7a789a1b41bca..9f11b3ddb61d7 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -17,7 +17,6 @@ use rustc_middle::ty::{ TypeVisitable, TypeVisitableExt, TypeVisitor, }; use rustc_span::Span; -use std::ops::ControlFlow; mod table; @@ -415,29 +414,22 @@ impl<'tcx, OP> TypeVisitor> for ConstrainOpaqueTypeRegionVisitor<'t where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder>>( - &mut self, - t: &ty::Binder<'tcx, T>, - ) -> ControlFlow { + fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { t.super_visit_with(self); - ControlFlow::Continue(()) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { match *r { // ignore bound regions, keep visiting - ty::ReBound(_, _) => ControlFlow::Continue(()), - _ => { - (self.op)(r); - ControlFlow::Continue(()) - } + ty::ReBound(_, _) => {} + _ => (self.op)(r), } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { // We're only interested in types involving regions if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) { - return ControlFlow::Continue(()); + return; } match ty.kind() { @@ -488,8 +480,6 @@ where ty.super_visit_with(self); } } - - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index 42e3d6cad5a97..488f435994d4d 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -2,8 +2,6 @@ use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use std::ops::ControlFlow; - use crate::infer::outlives::test_type_match; use crate::infer::region_constraints::VerifyIfEq; @@ -26,29 +24,22 @@ impl<'tcx, OP> TypeVisitor> for FreeRegionsVisitor<'tcx, OP> where OP: FnMut(ty::Region<'tcx>), { - fn visit_binder>>( - &mut self, - t: &ty::Binder<'tcx, T>, - ) -> ControlFlow { + fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { t.super_visit_with(self); - ControlFlow::Continue(()) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { match *r { // ignore bound regions, keep visiting - ty::ReBound(_, _) => ControlFlow::Continue(()), - _ => { - (self.op)(r); - ControlFlow::Continue(()) - } + ty::ReBound(_, _) => {} + _ => (self.op)(r), } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { // We're only interested in types involving regions if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) { - return ControlFlow::Continue(()); + return; } // FIXME: Don't consider alias bounds on types that have escaping bound @@ -102,7 +93,7 @@ where && outlives_bounds[1..].iter().all(|other_r| other_r == r) { assert!(r.type_flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS)); - r.visit_with(self)?; + r.visit_with(self); } else { // Skip lifetime parameters that are not captures. let variances = match kind { @@ -114,17 +105,13 @@ where if variances.map(|variances| variances[idx]) != Some(ty::Variance::Bivariant) { - s.visit_with(self)?; + s.visit_with(self); } } } } - _ => { - ty.super_visit_with(self)?; - } + _ => ty.super_visit_with(self), } - - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index bf4f88530d04e..064e09b875068 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -1,11 +1,11 @@ use crate::traits; use crate::traits::project::Normalized; +use rustc_ast_ir::try_visit; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable}; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor}; use rustc_middle::ty::{self, TyCtxt}; use std::fmt; -use std::ops::ControlFlow; // Structural impls for the structs in `traits`. @@ -84,8 +84,8 @@ impl<'tcx, O: TypeFoldable>> TypeFoldable> impl<'tcx, O: TypeVisitable>> TypeVisitable> for traits::Obligation<'tcx, O> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.predicate.visit_with(visitor)?; + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.predicate.visit_with(visitor)); self.param_env.visit_with(visitor) } } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 0862204d88e2d..d78ec8c0dd348 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -17,8 +17,8 @@ use crate::context::{EarlyContext, LintContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; use rustc_ast::ptr::P; -use rustc_ast::visit::{self as ast_visit, Visitor}; -use rustc_ast::{self as ast, walk_list, HasAttrs}; +use rustc_ast::visit::{self as ast_visit, walk_list, Visitor}; +use rustc_ast::{self as ast, HasAttrs}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_feature::Features; use rustc_middle::ty::RegisteredTools; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 71f330b5bf799..5d36a8b3d0e9c 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1474,9 +1474,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { struct ProhibitOpaqueTypes; impl<'tcx> ty::visit::TypeVisitor> for ProhibitOpaqueTypes { - type BreakTy = Ty<'tcx>; + type Result = ControlFlow>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if !ty.has_opaque_types() { return ControlFlow::Continue(()); } @@ -1620,9 +1620,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } impl<'vis, 'a, 'tcx> ty::visit::TypeVisitor> for FnPtrFinder<'vis, 'a, 'tcx> { - type BreakTy = Ty<'tcx>; + type Result = ControlFlow>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if let ty::FnPtr(sig) = ty.kind() && !self.visitor.is_internal_abi(sig.abi()) { diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs index c8430380345b4..94e86e0e246fe 100644 --- a/compiler/rustc_macros/src/type_visitable.rs +++ b/compiler/rustc_macros/src/type_visitable.rs @@ -34,7 +34,14 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2: s.add_bounds(synstructure::AddBounds::Generics); let body_visit = s.each(|bind| { quote! { - ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)?; + match ::rustc_ast_ir::visit::VisitorResult::branch( + ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor) + ) { + ::core::ops::ControlFlow::Continue(()) => {}, + ::core::ops::ControlFlow::Break(r) => { + return ::rustc_ast_ir::visit::VisitorResult::from_residual(r); + }, + } } }); s.bind_with(|_| synstructure::BindStyle::Move); @@ -45,9 +52,9 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2: fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>( &self, __visitor: &mut __V - ) -> ::std::ops::ControlFlow<__V::BreakTy> { + ) -> __V::Result { match *self { #body_visit } - ::std::ops::ControlFlow::Continue(()) + <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output() } }, ) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index db27e2bd6301b..4960369a0a7a9 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -3,8 +3,7 @@ use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::query::LocalCrate; use crate::ty::TyCtxt; use rustc_ast as ast; -use rustc_ast::visit::VisitorResult; -use rustc_ast::walk_list; +use rustc_ast::visit::{walk_list, VisitorResult}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index 26ca90db018e6..0ee97a6bed037 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -85,9 +85,9 @@ macro_rules! TrivialTypeTraversalImpls { fn visit_with>>( &self, _: &mut F) - -> ::std::ops::ControlFlow + -> F::Result { - ::std::ops::ControlFlow::Continue(()) + ::output() } } )+ diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 0dc6512601121..95139b50cb89e 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -1,6 +1,6 @@ -use std::ops::ControlFlow; - +use rustc_ast_ir::try_visit; use rustc_data_structures::intern::Interned; +use rustc_span::def_id::DefId; use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints}; use crate::traits::query::NoSolution; @@ -9,7 +9,6 @@ use crate::ty::{ self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, }; -use rustc_span::def_id::DefId; use super::BuiltinImplSource; @@ -196,13 +195,9 @@ impl<'tcx> TypeFoldable> for ExternalConstraints<'tcx> { } impl<'tcx> TypeVisitable> for ExternalConstraints<'tcx> { - fn visit_with>>( - &self, - visitor: &mut V, - ) -> std::ops::ControlFlow { - self.region_constraints.visit_with(visitor)?; - self.opaque_types.visit_with(visitor)?; - ControlFlow::Continue(()) + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.region_constraints.visit_with(visitor)); + self.opaque_types.visit_with(visitor) } } @@ -235,10 +230,7 @@ impl<'tcx> TypeFoldable> for PredefinedOpaques<'tcx> { } impl<'tcx> TypeVisitable> for PredefinedOpaques<'tcx> { - fn visit_with>>( - &self, - visitor: &mut V, - ) -> std::ops::ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { self.opaque_types.visit_with(visitor) } } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 712fbf2444053..2506456f1fb11 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -482,9 +482,9 @@ pub struct IsSuggestableVisitor<'tcx> { } impl<'tcx> TypeVisitor> for IsSuggestableVisitor<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { match *t.kind() { Infer(InferTy::TyVar(_)) if self.infer_suggestable => {} @@ -536,7 +536,7 @@ impl<'tcx> TypeVisitor> for IsSuggestableVisitor<'tcx> { t.super_visit_with(self) } - fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result { match c.kind() { ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => {} diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index c87ef870a084e..8079ad121ad9e 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -6,6 +6,8 @@ use crate::ty::sty::{ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineCon use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; +use rustc_ast_ir::visit::VisitorResult; +use rustc_ast_ir::walk_visitable_list; use rustc_data_structures::intern::Interned; use rustc_errors::{DiagArgValue, IntoDiagnosticArg}; use rustc_hir::def_id::DefId; @@ -19,7 +21,7 @@ use std::cmp::Ordering; use std::marker::PhantomData; use std::mem; use std::num::NonZero; -use std::ops::{ControlFlow, Deref}; +use std::ops::Deref; use std::ptr::NonNull; /// An entity in the Rust type system, which can be one of @@ -240,7 +242,7 @@ impl<'tcx> TypeFoldable> for GenericArg<'tcx> { } impl<'tcx> TypeVisitable> for GenericArg<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { match self.unpack() { GenericArgKind::Lifetime(lt) => lt.visit_with(visitor), GenericArgKind::Type(ty) => ty.visit_with(visitor), @@ -554,8 +556,9 @@ impl<'tcx> TypeFoldable> for &'tcx ty::List> { impl<'tcx, T: TypeVisitable>> TypeVisitable> for &'tcx ty::List { #[inline] - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c6bb7032ace3a..0a38d379a5216 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -33,7 +33,7 @@ pub use generics::*; pub use intrinsic::IntrinsicDef; use rustc_ast as ast; use rustc_ast::node_id::NodeMap; -pub use rustc_ast_ir::{Movability, Mutability}; +pub use rustc_ast_ir::{try_visit, Movability, Mutability}; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; @@ -64,7 +64,6 @@ use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::mem; use std::num::NonZero; -use std::ops::ControlFlow; use std::ptr::NonNull; use std::{fmt, str}; @@ -599,7 +598,7 @@ impl<'tcx> TypeFoldable> for Term<'tcx> { } impl<'tcx> TypeVisitable> for Term<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { self.unpack().visit_with(visitor) } } @@ -1043,8 +1042,8 @@ impl<'tcx> TypeFoldable> for ParamEnv<'tcx> { } impl<'tcx> TypeVisitable> for ParamEnv<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.caller_bounds().visit_with(visitor)?; + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(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 540803d953016..c8c9afa7f4d05 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -27,7 +27,7 @@ use std::cell::Cell; use std::collections::BTreeMap; use std::fmt::{self, Write as _}; use std::iter; -use std::ops::{ControlFlow, Deref, DerefMut}; +use std::ops::{Deref, DerefMut}; // `pretty` is a separate module only for organization. use super::*; @@ -2667,9 +2667,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } impl<'tcx> ty::visit::TypeVisitor> for RegionNameCollector<'tcx> { - type BreakTy = (); - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { trace!("address: {:p}", r.0.0); // Collect all named lifetimes. These allow us to prevent duplication @@ -2678,18 +2676,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { if let Some(name) = r.get_name() { self.used_region_names.insert(name); } - - ControlFlow::Continue(()) } // We collect types in order to prevent really large types from compiling for // a really long time. See issue #83150 for why this is necessary. - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { let not_previously_inserted = self.type_collector.insert(ty); if not_previously_inserted { ty.super_visit_with(self) - } else { - ControlFlow::Continue(()) } } } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index c6805ba932357..c8fb11673cf89 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -8,13 +8,14 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; +use rustc_ast_ir::try_visit; +use rustc_ast_ir::visit::VisitorResult; use rustc_hir::def::Namespace; use rustc_span::source_map::Spanned; use rustc_target::abi::TyAndLayout; use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, WithInfcx}; use std::fmt::{self, Debug}; -use std::ops::ControlFlow; use super::print::PrettyPrinter; use super::{GenericArg, GenericArgKind, Region}; @@ -482,11 +483,8 @@ impl<'a, 'tcx> Lift<'tcx> for Term<'a> { // Traversal implementations. impl<'tcx> TypeVisitable> for ty::AdtDef<'tcx> { - fn visit_with>>( - &self, - _visitor: &mut V, - ) -> ControlFlow { - ControlFlow::Continue(()) + fn visit_with>>(&self, _visitor: &mut V) -> V::Result { + V::Result::output() } } @@ -500,7 +498,7 @@ impl<'tcx, T: TypeFoldable>> TypeFoldable> for ty::Bin } impl<'tcx, T: TypeVisitable>> TypeVisitable> for ty::Binder<'tcx, T> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_binder(self) } } @@ -517,10 +515,7 @@ impl<'tcx, T: TypeFoldable>> TypeSuperFoldable> for ty impl<'tcx, T: TypeVisitable>> TypeSuperVisitable> for ty::Binder<'tcx, T> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { self.as_ref().skip_binder().visit_with(visitor) } } @@ -553,7 +548,7 @@ impl<'tcx> TypeFoldable> for Ty<'tcx> { } impl<'tcx> TypeVisitable> for Ty<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_ty(*self) } } @@ -609,27 +604,24 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { } impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { match self.kind() { ty::RawPtr(ref tm) => tm.visit_with(visitor), ty::Array(typ, sz) => { - typ.visit_with(visitor)?; + try_visit!(typ.visit_with(visitor)); sz.visit_with(visitor) } ty::Slice(typ) => typ.visit_with(visitor), ty::Adt(_, args) => args.visit_with(visitor), ty::Dynamic(ref trait_ty, ref reg, _) => { - trait_ty.visit_with(visitor)?; + try_visit!(trait_ty.visit_with(visitor)); reg.visit_with(visitor) } ty::Tuple(ts) => ts.visit_with(visitor), ty::FnDef(_, args) => args.visit_with(visitor), ty::FnPtr(ref f) => f.visit_with(visitor), ty::Ref(r, ty, _) => { - r.visit_with(visitor)?; + try_visit!(r.visit_with(visitor)); ty.visit_with(visitor) } ty::Coroutine(_did, ref args) => args.visit_with(visitor), @@ -650,7 +642,7 @@ impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { | ty::Placeholder(..) | ty::Param(..) | ty::Never - | ty::Foreign(..) => ControlFlow::Continue(()), + | ty::Foreign(..) => V::Result::output(), } } } @@ -665,7 +657,7 @@ impl<'tcx> TypeFoldable> for ty::Region<'tcx> { } impl<'tcx> TypeVisitable> for ty::Region<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_region(*self) } } @@ -690,13 +682,13 @@ impl<'tcx> TypeFoldable> for ty::Clause<'tcx> { } impl<'tcx> TypeVisitable> for ty::Predicate<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_predicate(*self) } } impl<'tcx> TypeVisitable> for ty::Clause<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_predicate(self.as_predicate()) } } @@ -712,10 +704,7 @@ impl<'tcx> TypeSuperFoldable> for ty::Predicate<'tcx> { } impl<'tcx> TypeSuperVisitable> for ty::Predicate<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { self.kind().visit_with(visitor) } } @@ -739,7 +728,7 @@ impl<'tcx> TypeFoldable> for ty::Const<'tcx> { } impl<'tcx> TypeVisitable> for ty::Const<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_const(*self) } } @@ -771,16 +760,13 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { } impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { - self.ty().visit_with(visitor)?; + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.ty().visit_with(visitor)); match self.kind() { ConstKind::Param(p) => p.visit_with(visitor), ConstKind::Infer(i) => i.visit_with(visitor), ConstKind::Bound(d, b) => { - d.visit_with(visitor)?; + try_visit!(d.visit_with(visitor)); b.visit_with(visitor) } ConstKind::Placeholder(p) => p.visit_with(visitor), @@ -802,25 +788,19 @@ impl<'tcx> TypeFoldable> for InferConst { } impl<'tcx> TypeVisitable> for InferConst { - fn visit_with>>( - &self, - _visitor: &mut V, - ) -> ControlFlow { - ControlFlow::Continue(()) + fn visit_with>>(&self, _visitor: &mut V) -> V::Result { + V::Result::output() } } impl<'tcx> TypeSuperVisitable> for ty::UnevaluatedConst<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { + fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { self.args.visit_with(visitor) } } impl<'tcx> TypeVisitable> for TyAndLayout<'tcx, Ty<'tcx>> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { visitor.visit_ty(self.ty) } } @@ -828,10 +808,9 @@ impl<'tcx> TypeVisitable> for TyAndLayout<'tcx, Ty<'tcx>> { impl<'tcx, T: TypeVisitable> + Debug + Clone> TypeVisitable> for Spanned { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.node.visit_with(visitor)?; - self.span.visit_with(visitor)?; - ControlFlow::Continue(()) + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.node.visit_with(visitor)); + self.span.visit_with(visitor) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 17659ac23307c..4b349e7836c7c 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2113,9 +2113,9 @@ impl<'tcx> Ty<'tcx> { struct ContainsTyVisitor<'tcx>(Ty<'tcx>); impl<'tcx> TypeVisitor> for ContainsTyVisitor<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) } } } @@ -2131,9 +2131,9 @@ impl<'tcx> Ty<'tcx> { struct ContainsClosureVisitor; impl<'tcx> TypeVisitor> for ContainsClosureVisitor { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if let ty::Closure(..) = t.kind() { ControlFlow::Break(()) } else { diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 59d09c3dc7821..218567bbd59e8 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -64,19 +64,19 @@ impl<'tcx> TyCtxt<'tcx> { where F: FnMut(ty::Region<'tcx>) -> bool, { - type BreakTy = (); + type Result = ControlFlow<()>; fn visit_binder>>( &mut self, t: &Binder<'tcx, T>, - ) -> ControlFlow { + ) -> Self::Result { self.outer_index.shift_in(1); let result = t.super_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>) -> Self::Result { match *r { ty::ReBound(debruijn, _) if debruijn < self.outer_index => { ControlFlow::Continue(()) @@ -91,7 +91,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { // We're only interested in types involving regions if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) { ty.super_visit_with(self) @@ -140,8 +140,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut collector = LateBoundRegionsCollector::new(just_constrained); let value = value.skip_binder(); let value = if just_constrained { self.expand_weak_alias_tys(value) } else { value }; - let result = value.visit_with(&mut collector); - assert!(result.is_continue()); // should never have stopped early + value.visit_with(&mut collector); collector.regions } } @@ -165,19 +164,19 @@ impl<'tcx> ValidateBoundVars<'tcx> { } impl<'tcx> TypeVisitor> for ValidateBoundVars<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; fn visit_binder>>( &mut self, t: &Binder<'tcx, T>, - ) -> ControlFlow { + ) -> Self::Result { 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>) -> Self::Result { if t.outer_exclusive_binder() < self.binder_index || !self.visited.insert((self.binder_index, t)) { @@ -211,7 +210,7 @@ impl<'tcx> TypeVisitor> for ValidateBoundVars<'tcx> { t.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { match *r { ty::ReBound(index, br) if index == self.binder_index => { if self.bound_vars.len() <= br.var.as_usize() { @@ -266,23 +265,19 @@ impl LateBoundRegionsCollector { } impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { - fn visit_binder>>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow { + fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) { self.current_index.shift_in(1); - let result = t.super_visit_with(self); + 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>) { if self.just_constrained { match t.kind() { // If we are only looking for "constrained" regions, we have to ignore the // inputs to a projection as they may not appear in the normalized form. ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) => { - return ControlFlow::Continue(()); + return; } // All weak alias types should've been expanded beforehand. ty::Alias(ty::Weak, _) => bug!("unexpected weak alias type"), @@ -293,26 +288,25 @@ impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { t.super_visit_with(self) } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) { // 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.kind() { - return ControlFlow::Continue(()); + return; } } c.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::ReBound(debruijn, br) = *r { if debruijn == self.current_index { self.regions.insert(br.kind); } } - ControlFlow::Continue(()) } } @@ -332,7 +326,7 @@ impl MaxUniverse { } impl<'tcx> TypeVisitor> for MaxUniverse { - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { if let ty::Placeholder(placeholder) = t.kind() { self.max_universe = ty::UniverseIndex::from_u32( self.max_universe.as_u32().max(placeholder.universe.as_u32()), @@ -342,7 +336,7 @@ impl<'tcx> TypeVisitor> for MaxUniverse { t.super_visit_with(self) } - fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::consts::Const<'tcx>) { if let ty::ConstKind::Placeholder(placeholder) = c.kind() { self.max_universe = ty::UniverseIndex::from_u32( self.max_universe.as_u32().max(placeholder.universe.as_u32()), @@ -352,13 +346,11 @@ impl<'tcx> TypeVisitor> for MaxUniverse { c.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::RePlaceholder(placeholder) = *r { self.max_universe = ty::UniverseIndex::from_u32( self.max_universe.as_u32().max(placeholder.universe.as_u32()), ); } - - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index fb42532e247af..1070d1a1380d8 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -18,7 +18,6 @@ use rustc_middle::ty::{ GenericArgsRef, Ty, TyCtxt, UnusedGenericParams, }; use rustc_span::symbol::sym; -use std::ops::ControlFlow; use crate::errors::UnusedGenericParamsHint; @@ -291,31 +290,29 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor> for MarkUsedGenericParams<'a, 'tcx> { #[instrument(level = "debug", skip(self))] - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) { if !c.has_non_region_param() { - return ControlFlow::Continue(()); + return; } match c.kind() { ty::ConstKind::Param(param) => { debug!(?param); self.unused_parameters.mark_used(param.index); - ControlFlow::Continue(()) } ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) if matches!(self.tcx.def_kind(def), DefKind::AnonConst) => { self.visit_child_body(def, args); - ControlFlow::Continue(()) } _ => c.super_visit_with(self), } } #[instrument(level = "debug", skip(self))] - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { if !ty.has_non_region_param() { - return ControlFlow::Continue(()); + return; } match *ty.kind() { @@ -323,18 +320,16 @@ impl<'a, 'tcx> TypeVisitor> for MarkUsedGenericParams<'a, 'tcx> { debug!(?def_id); // Avoid cycle errors with coroutines. if def_id == self.def_id { - return ControlFlow::Continue(()); + return; } // Consider any generic parameters used by any closures/coroutines as used in the // parent. self.visit_child_body(def_id, args); - ControlFlow::Continue(()) } ty::Param(param) => { debug!(?param); self.unused_parameters.mark_used(param.index); - ControlFlow::Continue(()) } _ => ty.super_visit_with(self), } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 9d8a9f5fce3e4..fe3598616817b 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -11,6 +11,7 @@ extern crate tracing; mod errors; +use rustc_ast::visit::{try_visit, VisitorResult}; use rustc_ast::MacroDef; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; @@ -67,17 +68,13 @@ impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> { /// 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 = (); + type Result: VisitorResult = (); const SHALLOW: bool = false; const SKIP_ASSOC_TYS: bool = false; fn tcx(&self) -> TyCtxt<'tcx>; - fn visit_def_id( - &mut self, - def_id: DefId, - kind: &str, - descr: &dyn fmt::Display, - ) -> ControlFlow; + fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) + -> Self::Result; /// Not overridden, but used to actually visit types and traits. fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> { @@ -87,25 +84,16 @@ trait DefIdVisitor<'tcx> { dummy: Default::default(), } } - fn visit( - &mut self, - ty_fragment: impl TypeVisitable>, - ) -> ControlFlow { + fn visit(&mut self, ty_fragment: impl TypeVisitable>) -> Self::Result { 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>) -> Self::Result { 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>) -> Self::Result { self.skeleton().visit_clauses(predicates.predicates) } - fn visit_clauses( - &mut self, - clauses: &[(ty::Clause<'tcx>, Span)], - ) -> ControlFlow { + fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> Self::Result { self.skeleton().visit_clauses(clauses) } } @@ -120,36 +108,42 @@ 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>) -> V::Result { let TraitRef { def_id, args, .. } = trait_ref; - self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?; - if V::SHALLOW { ControlFlow::Continue(()) } else { args.visit_with(self) } + try_visit!(self.def_id_visitor.visit_def_id( + def_id, + "trait", + &trait_ref.print_only_trait_path() + )); + if V::SHALLOW { V::Result::output() } else { args.visit_with(self) } } - fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow { + fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> V::Result { let tcx = self.def_id_visitor.tcx(); let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx); - self.visit_trait(trait_ref)?; + try_visit!(self.visit_trait(trait_ref)); if V::SHALLOW { - ControlFlow::Continue(()) + V::Result::output() } else { - assoc_args.iter().try_for_each(|arg| arg.visit_with(self)) + V::Result::from_branch( + assoc_args.iter().try_for_each(|arg| arg.visit_with(self).branch()), + ) } } - fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> ControlFlow { + fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> V::Result { match clause.kind().skip_binder() { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { self.visit_trait(trait_ref) } ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { - term.visit_with(self)?; + try_visit!(term.visit_with(self)); self.visit_projection_ty(projection_ty) } ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self), - ty::ClauseKind::RegionOutlives(..) => ControlFlow::Continue(()), + ty::ClauseKind::RegionOutlives(..) => V::Result::output(), ty::ClauseKind::ConstArgHasType(ct, ty) => { - ct.visit_with(self)?; + try_visit!(ct.visit_with(self)); ty.visit_with(self) } ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self), @@ -157,8 +151,11 @@ where } } - fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> ControlFlow { - clauses.into_iter().try_for_each(|&(clause, _span)| self.visit_clause(clause)) + fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> V::Result { + for &(clause, _) in clauses { + try_visit!(self.visit_clause(clause)); + } + V::Result::output() } } @@ -166,13 +163,13 @@ impl<'tcx, V> TypeVisitor> for DefIdVisitorSkeleton<'_, 'tcx, V> where V: DefIdVisitor<'tcx> + ?Sized, { - type BreakTy = V::BreakTy; + type Result = V::Result; - fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow { + fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> Self::Result { self.visit_clause(p.as_clause().unwrap()) } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { let tcx = self.def_id_visitor.tcx(); // GenericArgs are not visited here because they are visited below // in `super_visit_with`. @@ -183,16 +180,16 @@ where | ty::Closure(def_id, ..) | ty::CoroutineClosure(def_id, ..) | ty::Coroutine(def_id, ..) => { - self.def_id_visitor.visit_def_id(def_id, "type", &ty)?; + try_visit!(self.def_id_visitor.visit_def_id(def_id, "type", &ty)); if V::SHALLOW { - return ControlFlow::Continue(()); + return V::Result::output(); } // Default type visitor doesn't visit signatures of fn types. // Something like `fn() -> Priv {my_func}` is considered a private type even if // `my_func` is public, so we need to visit signatures. if let ty::FnDef(..) = ty.kind() { // FIXME: this should probably use `args` from `FnDef` - tcx.fn_sig(def_id).instantiate_identity().visit_with(self)?; + try_visit!(tcx.fn_sig(def_id).instantiate_identity().visit_with(self)); } // Inherent static methods don't have self type in args. // Something like `fn() {my_method}` type of the method @@ -200,7 +197,9 @@ where // so we need to visit the self type additionally. if let Some(assoc_item) = tcx.opt_associated_item(def_id) { if let Some(impl_def_id) = assoc_item.impl_container(tcx) { - tcx.type_of(impl_def_id).instantiate_identity().visit_with(self)?; + try_visit!( + tcx.type_of(impl_def_id).instantiate_identity().visit_with(self) + ); } } } @@ -211,10 +210,10 @@ where // as visible/reachable even if `Type` is private. // Ideally, associated types should be instantiated in the same way as // free type aliases, but this isn't done yet. - return ControlFlow::Continue(()); + return V::Result::output(); } - self.def_id_visitor.visit_def_id( + try_visit!(self.def_id_visitor.visit_def_id( data.def_id, match kind { ty::Inherent | ty::Projection => "associated type", @@ -222,15 +221,17 @@ where ty::Opaque => unreachable!(), }, &LazyDefPathStr { def_id: data.def_id, tcx }, - )?; + )); // This will also visit args if necessary, so we don't need to recurse. return if V::SHALLOW { - ControlFlow::Continue(()) + V::Result::output() } else if kind == ty::Projection { self.visit_projection_ty(data) } else { - data.args.iter().try_for_each(|arg| arg.visit_with(self)) + V::Result::from_branch( + data.args.iter().try_for_each(|arg| arg.visit_with(self).branch()), + ) }; } ty::Dynamic(predicates, ..) => { @@ -245,7 +246,7 @@ where } }; let ty::ExistentialTraitRef { def_id, args: _ } = trait_ref; - self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)?; + try_visit!(self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)); } } ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => { @@ -258,7 +259,7 @@ where // through the trait list (default type visitor doesn't visit those traits). // All traits in the list are considered the "primary" part of the type // and are visited by shallow visitors. - self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder())?; + try_visit!(self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder())); } } // These types don't have their own def-ids (but may have subcomponents @@ -285,10 +286,10 @@ where } } - if V::SHALLOW { ControlFlow::Continue(()) } else { ty.super_visit_with(self) } + if V::SHALLOW { V::Result::output() } else { ty.super_visit_with(self) } } - fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result { let tcx = self.def_id_visitor.tcx(); tcx.expand_abstract_consts(c).super_visit_with(self) } @@ -316,16 +317,10 @@ impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx> fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn visit_def_id( - &mut self, - def_id: DefId, - _kind: &str, - _descr: &dyn fmt::Display, - ) -> ControlFlow { + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) { if let Some(def_id) = def_id.as_local() { self.min = VL::new_min(self, def_id); } - ControlFlow::Continue(()) } } @@ -836,12 +831,7 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> fn tcx(&self) -> TyCtxt<'tcx> { self.ev.tcx } - fn visit_def_id( - &mut self, - def_id: DefId, - _kind: &str, - _descr: &dyn fmt::Display, - ) -> ControlFlow { + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) { if let Some(def_id) = def_id.as_local() { // All effective visibilities except `reachable_through_impl_trait` are limited to // nominal visibility. If any type or trait is leaked farther than that, it will @@ -850,7 +840,6 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> .then(|| self.ev.tcx.local_visibility(def_id)); self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level); } - ControlFlow::Continue(()) } } @@ -1076,8 +1065,8 @@ impl<'tcx> TypePrivacyVisitor<'tcx> { } impl<'tcx> rustc_ty_utils::sig_types::SpannedTypeVisitor<'tcx> for TypePrivacyVisitor<'tcx> { - type BreakTy = (); - fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> ControlFlow<()> { + type Result = ControlFlow<()>; + fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> Self::Result { self.span = span; value.visit_with(&mut self.skeleton()) } @@ -1233,6 +1222,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { } impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { + type Result = ControlFlow<()>; fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -1241,7 +1231,7 @@ impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { def_id: DefId, kind: &str, descr: &dyn fmt::Display, - ) -> ControlFlow { + ) -> Self::Result { if self.check_def_id(def_id, kind, descr) { ControlFlow::Break(()) } else { @@ -1407,6 +1397,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { } impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { + type Result = ControlFlow<()>; fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -1415,7 +1406,7 @@ impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { def_id: DefId, kind: &str, descr: &dyn fmt::Display, - ) -> ControlFlow { + ) -> Self::Result { if self.check_def_id(def_id, kind, descr) { ControlFlow::Break(()) } else { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index de6e121c79bbb..2c80fbdab36d7 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -13,7 +13,7 @@ use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; use rustc_ast::ptr::P; -use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; +use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::{ diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 00ce9fbe7585b..3a58d41fcd0a4 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" bitflags = "2.4.1" itertools = "0.11.0" rustc_ast = { path = "../rustc_ast" } +rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 7c1bfebef2cd0..fd3d62d1321e2 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -18,6 +18,7 @@ #![allow(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] #![feature(associated_type_bounds)] +#![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(extract_if)] diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 98d28f10a5441..22f52c273625f 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -648,8 +648,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } impl<'tcx> TypeVisitor> for ContainsTermOrNotNameable<'_, 'tcx> { - type BreakTy = (); - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + type Result = ControlFlow<()>; + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { match *t.kind() { ty::Infer(ty::TyVar(vid)) => { if let ty::TermKind::Ty(term) = self.term.unpack() @@ -672,7 +672,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result { match c.kind() { ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { if let ty::TermKind::Const(term) = self.term.unpack() diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 52b900af85328..9e3e6a4676efb 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -1,15 +1,16 @@ -/// An infrastructure to mechanically analyse proof trees. -/// -/// It is unavoidable that this representation is somewhat -/// lossy as it should hide quite a few semantically relevant things, -/// e.g. canonicalization and the order of nested goals. -/// -/// @lcnr: However, a lot of the weirdness here is not strictly necessary -/// and could be improved in the future. This is mostly good enough for -/// coherence right now and was annoying to implement, so I am leaving it -/// as is until we start using it for something else. -use std::ops::ControlFlow; - +//! An infrastructure to mechanically analyse proof trees. +//! +//! It is unavoidable that this representation is somewhat +//! lossy as it should hide quite a few semantically relevant things, +//! e.g. canonicalization and the order of nested goals. +//! +//! @lcnr: However, a lot of the weirdness here is not strictly necessary +//! and could be improved in the future. This is mostly good enough for +//! coherence right now and was annoying to implement, so I am leaving it +//! as is until we start using it for something else. + +use rustc_ast_ir::try_visit; +use rustc_ast_ir::visit::VisitorResult; use rustc_infer::infer::InferCtxt; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{inspect, QueryResult}; @@ -53,10 +54,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { /// to also use it to compute the most relevant goal /// for fulfillment errors. Will do that once we actually /// need it. - pub fn visit_nested>( - &self, - visitor: &mut V, - ) -> ControlFlow { + pub fn visit_nested>(&self, visitor: &mut V) -> V::Result { // HACK: An arbitrary cutoff to avoid dealing with overflow and cycles. if self.goal.depth <= 10 { let infcx = self.goal.infcx; @@ -75,17 +73,18 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { for &goal in &instantiated_goals { let (_, proof_tree) = infcx.evaluate_root_goal(goal, GenerateProofTree::Yes); let proof_tree = proof_tree.unwrap(); - visitor.visit_goal(&InspectGoal::new( + try_visit!(visitor.visit_goal(&InspectGoal::new( infcx, self.goal.depth + 1, &proof_tree, - ))?; + ))); } - ControlFlow::Continue(()) - })?; + V::Result::output() + }) + } else { + V::Result::output() } - ControlFlow::Continue(()) } } @@ -202,9 +201,9 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { /// The public API to interact with proof trees. pub trait ProofTreeVisitor<'tcx> { - type BreakTy; + type Result: VisitorResult = (); - fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow; + fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> Self::Result; } #[extension(pub trait ProofTreeInferCtxtExt<'tcx>)] @@ -213,7 +212,7 @@ impl<'tcx> InferCtxt<'tcx> { &self, goal: Goal<'tcx, ty::Predicate<'tcx>>, visitor: &mut V, - ) -> ControlFlow { + ) -> V::Result { self.probe(|_| { let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes); let proof_tree = proof_tree.unwrap(); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 68111c4cc1fdc..176647a4b15f8 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -474,7 +474,7 @@ fn plug_infer_with_placeholders<'tcx>( } impl<'tcx> TypeVisitor> for PlugInferWithPlaceholder<'_, 'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { let ty = self.infcx.shallow_resolve(ty); if ty.is_ty_var() { let Ok(InferOk { value: (), obligations }) = @@ -496,13 +496,12 @@ fn plug_infer_with_placeholders<'tcx>( bug!("we always expect to be able to plug an infer var with placeholder") }; assert_eq!(obligations, &[]); - ControlFlow::Continue(()) } else { - ty.super_visit_with(self) + ty.super_visit_with(self); } } - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, ct: ty::Const<'tcx>) { let ct = self.infcx.shallow_resolve(ct); if ct.is_ct_infer() { let Ok(InferOk { value: (), obligations }) = @@ -519,13 +518,12 @@ fn plug_infer_with_placeholders<'tcx>( bug!("we always expect to be able to plug an infer var with placeholder") }; assert_eq!(obligations, &[]); - ControlFlow::Continue(()) } else { - ct.super_visit_with(self) + ct.super_visit_with(self); } } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::ReVar(vid) = *r { let r = self .infcx @@ -555,7 +553,6 @@ fn plug_infer_with_placeholders<'tcx>( assert_eq!(obligations, &[]); } } - ControlFlow::Continue(()) } } @@ -868,12 +865,12 @@ impl<'tcx, F, E> TypeVisitor> for OrphanChecker<'tcx, F> where F: FnMut(Ty<'tcx>) -> Result, E>, { - type BreakTy = OrphanCheckEarlyExit<'tcx, E>; - fn visit_region(&mut self, _r: ty::Region<'tcx>) -> ControlFlow { + type Result = ControlFlow>; + fn visit_region(&mut self, _r: ty::Region<'tcx>) -> Self::Result { ControlFlow::Continue(()) } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { // Need to lazily normalize here in with `-Znext-solver=coherence`. let ty = match (self.lazily_normalize_ty)(ty) { Ok(ty) => ty, @@ -996,7 +993,7 @@ where /// As these should be quite rare as const arguments and especially rare as impl /// parameters, allowing uncovered const parameters in impls seems more useful /// than allowing `impl Trait for i32` to compile. - fn visit_const(&mut self, _c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, _c: ty::Const<'tcx>) -> Self::Result { ControlFlow::Continue(()) } } @@ -1026,18 +1023,17 @@ struct AmbiguityCausesVisitor<'a, 'tcx> { } impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { - type BreakTy = !; - fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow { + fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) { let infcx = goal.infcx(); for cand in goal.candidates() { - cand.visit_nested(self)?; + cand.visit_nested(self); } // When searching for intercrate ambiguity causes, we only need to look // at ambiguous goals, as for others the coherence unknowable candidate // was irrelevant. match goal.result() { Ok(Certainty::Maybe(_)) => {} - Ok(Certainty::Yes) | Err(NoSolution) => return ControlFlow::Continue(()), + Ok(Certainty::Yes) | Err(NoSolution) => return, } let Goal { param_env, predicate } = goal.goal(); @@ -1054,7 +1050,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { { proj.projection_ty.trait_ref(infcx.tcx) } - _ => return ControlFlow::Continue(()), + _ => return, }; // Add ambiguity causes for reservation impls. @@ -1154,8 +1150,6 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { if let Some(ambiguity_cause) = ambiguity_cause { self.causes.insert(ambiguity_cause); } - - 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 189e1ba54bc36..7f0f9a12d6a05 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -17,7 +17,6 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::{self, TyCtxt, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_span::Span; -use std::ops::ControlFlow; use crate::traits::ObligationCtxt; @@ -170,8 +169,7 @@ fn satisfied_from_param_env<'tcx>( } impl<'a, 'tcx> TypeVisitor> for Visitor<'a, 'tcx> { - type BreakTy = (); - fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, c: ty::Const<'tcx>) { debug!("is_const_evaluatable: candidate={:?}", c); if self.infcx.probe(|_| { let ocx = ObligationCtxt::new(self.infcx); @@ -187,7 +185,7 @@ fn satisfied_from_param_env<'tcx>( } if let ty::ConstKind::Expr(e) = c.kind() { - e.visit_with(self) + e.visit_with(self); } else { // FIXME(generic_const_exprs): This doesn't recurse into `>::ASSOC`'s args. // This is currently unobservable as `>::ASSOC` creates an anon const @@ -196,7 +194,6 @@ fn satisfied_from_param_env<'tcx>( // If we start allowing directly writing `ConstKind::Expr` without an intermediate anon const // this will be incorrect. It might be worth investigating making `predicates_of` elaborate // all of the `ConstEvaluatable` bounds rather than having a visitor here. - ControlFlow::Continue(()) } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 0796cb57d979c..0515b09ae46a0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -152,9 +152,9 @@ impl ArgKind { struct HasNumericInferVisitor; impl<'tcx> ty::TypeVisitor> for HasNumericInferVisitor { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { if matches!(ty.kind(), ty::Infer(ty::FloatVar(_) | ty::IntVar(_))) { ControlFlow::Break(()) } else { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 32447aca390a4..cc8b8f72cf359 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -435,8 +435,8 @@ fn is_impossible_associated_item( trait_item_def_id: DefId, } impl<'tcx> ty::TypeVisitor> for ReferencesOnlyParentGenerics<'tcx> { - type BreakTy = (); - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + type Result = ControlFlow<()>; + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { // If this is a parameter from the trait item's own generics, then bail if let ty::Param(param) = t.kind() && let param_def_id = self.generics.type_param(param, self.tcx).def_id @@ -446,7 +446,7 @@ fn is_impossible_associated_item( } t.super_visit_with(self) } - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { if let ty::ReEarlyParam(param) = r.kind() && let param_def_id = self.generics.region_param(¶m, self.tcx).def_id && self.tcx.parent(param_def_id) == self.trait_item_def_id @@ -455,7 +455,7 @@ fn is_impossible_associated_item( } ControlFlow::Continue(()) } - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result { if let ty::ConstKind::Param(param) = ct.kind() && let param_def_id = self.generics.const_param(¶m, self.tcx).def_id && self.tcx.parent(param_def_id) == self.trait_item_def_id diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 7b715984c2b27..1816b98a636c6 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -834,9 +834,9 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable>>( } impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { match t.kind() { ty::Param(_) => { if t == self.tcx.types.self_param { @@ -887,7 +887,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable>>( } } - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result { // Constants can only influence object safety if they are generic and reference `Self`. // This is only possible for unevaluated constants, so we walk these here. self.tcx.expand_abstract_consts(ct).super_visit_with(self) diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index e5f8e33686099..c520e699bf542 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -18,8 +18,6 @@ use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableEx use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; use rustc_span::DUMMY_SP; -use std::ops::ControlFlow; - use super::NoSolution; pub use rustc_middle::traits::query::NormalizationResult; @@ -123,28 +121,23 @@ struct MaxEscapingBoundVarVisitor { } impl<'tcx> TypeVisitor> for MaxEscapingBoundVarVisitor { - fn visit_binder>>( - &mut self, - t: &ty::Binder<'tcx, T>, - ) -> ControlFlow { + fn visit_binder>>(&mut self, t: &ty::Binder<'tcx, T>) { self.outer_index.shift_in(1); - let result = t.super_visit_with(self); + t.super_visit_with(self); self.outer_index.shift_out(1); - result } #[inline] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) { if t.outer_exclusive_binder() > self.outer_index { self.escaping = self .escaping .max(t.outer_exclusive_binder().as_usize() - self.outer_index.as_usize()); } - ControlFlow::Continue(()) } #[inline] - fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + fn visit_region(&mut self, r: ty::Region<'tcx>) { match *r { ty::ReBound(debruijn, _) if debruijn > self.outer_index => { self.escaping = @@ -152,16 +145,14 @@ impl<'tcx> TypeVisitor> for MaxEscapingBoundVarVisitor { } _ => {} } - ControlFlow::Continue(()) } - fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow { + fn visit_const(&mut self, ct: ty::Const<'tcx>) { if ct.outer_exclusive_binder() > self.outer_index { self.escaping = self .escaping .max(ct.outer_exclusive_binder().as_usize() - self.outer_index.as_usize()); } - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index e6b42f15d5140..b89406ca02332 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -53,9 +53,9 @@ impl<'tcx> Search<'tcx> { } impl<'tcx> TypeVisitor> for Search<'tcx> { - type BreakTy = Ty<'tcx>; + type Result = ControlFlow>; - fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { debug!("Search visiting ty: {:?}", ty); let (adt_def, args) = match *ty.kind() { diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml index 066016231fa39..3d0ad31747ff7 100644 --- a/compiler/rustc_transmute/Cargo.toml +++ b/compiler/rustc_transmute/Cargo.toml @@ -5,13 +5,14 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -rustc_data_structures = { path = "../rustc_data_structures"} -rustc_hir = { path = "../rustc_hir", optional = true} -rustc_infer = { path = "../rustc_infer", optional = true} -rustc_macros = { path = "../rustc_macros", optional = true} -rustc_middle = { path = "../rustc_middle", optional = true} -rustc_span = { path = "../rustc_span", optional = true} -rustc_target = { path = "../rustc_target", optional = true} +rustc_ast_ir = { path = "../rustc_ast_ir", optional = true } +rustc_data_structures = { path = "../rustc_data_structures" } +rustc_hir = { path = "../rustc_hir", optional = true } +rustc_infer = { path = "../rustc_infer", optional = true } +rustc_macros = { path = "../rustc_macros", optional = true } +rustc_middle = { path = "../rustc_middle", optional = true } +rustc_span = { path = "../rustc_span", optional = true } +rustc_target = { path = "../rustc_target", optional = true } tracing = "0.1" # tidy-alphabetical-end @@ -23,6 +24,7 @@ rustc = [ "rustc_middle", "rustc_span", "rustc_target", + "rustc_ast_ir", ] [dev-dependencies] diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index f8eb82da8f688..2a30bd5d53907 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start itertools = "0.11" +rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 282595169737d..aaf968cbb7587 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -8,7 +8,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_span::Span; use rustc_trait_selection::traits::check_args_compatible; -use std::ops::ControlFlow; use crate::errors::{DuplicateArg, NotParam}; @@ -194,16 +193,15 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'tcx> { #[instrument(skip(self), ret, level = "trace")] - fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> ControlFlow { + fn visit(&mut self, span: Span, value: impl TypeVisitable>) { self.visit_spanned(span, value); - ControlFlow::Continue(()) } } impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { #[instrument(skip(self), ret, level = "trace")] - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - t.super_visit_with(self)?; + fn visit_ty(&mut self, t: Ty<'tcx>) { + t.super_visit_with(self); match t.kind() { ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => { self.visit_opaque_ty(alias_ty); @@ -212,7 +210,7 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { self.tcx .type_of(alias_ty.def_id) .instantiate(self.tcx, alias_ty.args) - .visit_with(self)?; + .visit_with(self); } ty::Alias(ty::Projection, alias_ty) => { // This avoids having to do normalization of `Self::AssocTy` by only @@ -244,11 +242,11 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { ); if check_args_compatible(self.tcx, assoc, impl_args) { - return self - .tcx + self.tcx .type_of(assoc.def_id) .instantiate(self.tcx, impl_args) .visit_with(self); + return; } else { self.tcx.dcx().span_delayed_bug( self.tcx.def_span(assoc.def_id), @@ -261,10 +259,10 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { } ty::Adt(def, _) if def.did().is_local() => { if let CollectionMode::ImplTraitInAssocTypes = self.mode { - return ControlFlow::Continue(()); + return; } if !self.seen.insert(def.did().expect_local()) { - return ControlFlow::Continue(()); + return; } for variant in def.variants().iter() { for field in variant.fields.iter() { @@ -283,7 +281,6 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { } _ => trace!(kind=?t.kind()), } - ControlFlow::Continue(()) } } diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 38cc558380cd8..5527d853e3048 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -1,27 +1,23 @@ //! This module contains helpers for walking all types of //! a signature, while preserving spans as much as possible -use std::ops::ControlFlow; - +use rustc_ast_ir::try_visit; +use rustc_ast_ir::visit::VisitorResult; use rustc_hir::{def::DefKind, def_id::LocalDefId}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; use rustc_type_ir::visit::TypeVisitable; pub trait SpannedTypeVisitor<'tcx> { - type BreakTy = !; - fn visit( - &mut self, - span: Span, - value: impl TypeVisitable>, - ) -> ControlFlow; + type Result: VisitorResult = (); + fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> Self::Result; } pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( tcx: TyCtxt<'tcx>, item: LocalDefId, visitor: &mut V, -) -> ControlFlow { +) -> V::Result { let kind = tcx.def_kind(item); trace!(?kind); match kind { @@ -30,12 +26,12 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( let ty_sig = tcx.fn_sig(item).instantiate_identity(); let hir_sig = tcx.hir_node_by_def_id(item).fn_decl().unwrap(); // Walk over the inputs and outputs manually in order to get good spans for them. - visitor.visit(hir_sig.output.span(), ty_sig.output()); + try_visit!(visitor.visit(hir_sig.output.span(), ty_sig.output())); for (hir, ty) in hir_sig.inputs.iter().zip(ty_sig.inputs().iter()) { - visitor.visit(hir.span, ty.map_bound(|x| *x))?; + try_visit!(visitor.visit(hir.span, ty.map_bound(|x| *x))); } for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + try_visit!(visitor.visit(span, pred)); } } // Walk over the type behind the alias @@ -44,32 +40,32 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { if let Some(ty) = tcx.hir_node_by_def_id(item).ty() { // Associated types in traits don't necessarily have a type that we can visit - visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())?; + try_visit!(visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())); } for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + try_visit!(visitor.visit(span, pred)); } } DefKind::OpaqueTy => { for (pred, span) in tcx.explicit_item_bounds(item).instantiate_identity_iter_copied() { - visitor.visit(span, pred)?; + try_visit!(visitor.visit(span, pred)); } } // Look at field types DefKind::Struct | DefKind::Union | DefKind::Enum => { let span = tcx.def_ident_span(item).unwrap(); let ty = tcx.type_of(item).instantiate_identity(); - visitor.visit(span, ty); + try_visit!(visitor.visit(span, ty)); let ty::Adt(def, args) = ty.kind() else { span_bug!(span, "invalid type for {kind:?}: {:#?}", ty.kind()) }; for field in def.all_fields() { let span = tcx.def_ident_span(field.did).unwrap(); let ty = field.ty(tcx, args); - visitor.visit(span, ty); + try_visit!(visitor.visit(span, ty)); } for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + try_visit!(visitor.visit(span, pred)); } } // These are not part of a public API, they can only appear as hidden types, and there @@ -80,20 +76,20 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( if of_trait { let span = tcx.hir_node_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().path.span; let args = &tcx.impl_trait_ref(item).unwrap().instantiate_identity().args[1..]; - visitor.visit(span, args)?; + try_visit!(visitor.visit(span, args)); } let span = match tcx.hir_node_by_def_id(item).ty() { Some(ty) => ty.span, _ => tcx.def_span(item), }; - visitor.visit(span, tcx.type_of(item).instantiate_identity()); + try_visit!(visitor.visit(span, tcx.type_of(item).instantiate_identity())); for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + try_visit!(visitor.visit(span, pred)); } } DefKind::TraitAlias | DefKind::Trait => { for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + try_visit!(visitor.visit(span, pred)); } } | DefKind::Variant @@ -116,5 +112,5 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( | DefKind::Mod | DefKind::Use => {} } - ControlFlow::Continue(()) + V::Result::output() } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index b725eda33ce89..48d9a5e27b7eb 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -174,17 +174,13 @@ struct ImplTraitInTraitFinder<'a, 'tcx> { } impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { - fn visit_binder>>( - &mut self, - binder: &ty::Binder<'tcx, T>, - ) -> std::ops::ControlFlow { + fn visit_binder>>(&mut self, binder: &ty::Binder<'tcx, T>) { self.depth.shift_in(1); - let binder = binder.super_visit_with(self); + binder.super_visit_with(self); self.depth.shift_out(1); - binder } - fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow { + fn visit_ty(&mut self, ty: Ty<'tcx>) { if let ty::Alias(ty::Projection, unshifted_alias_ty) = *ty.kind() && let Some( ty::ImplTraitInTraitData::Trait { fn_def_id, .. } diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 5bc2bfe28939c..ad18ef249842f 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -1,6 +1,7 @@ +use rustc_ast_ir::try_visit; +use rustc_ast_ir::visit::VisitorResult; use std::fmt; use std::hash::Hash; -use std::ops::ControlFlow; use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; @@ -107,9 +108,9 @@ impl> TypeVisitable for Canonical where I::CanonicalVars: TypeVisitable, { - fn visit_with>(&self, folder: &mut F) -> ControlFlow { - self.value.visit_with(folder)?; - self.max_universe.visit_with(folder)?; + fn visit_with>(&self, folder: &mut F) -> F::Result { + try_visit!(self.value.visit_with(folder)); + try_visit!(self.max_universe.visit_with(folder)); self.variables.visit_with(folder) } } @@ -137,7 +138,7 @@ impl TypeVisitable for CanonicalVarInfo where I::Ty: TypeVisitable, { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { self.kind.visit_with(visitor) } } @@ -251,13 +252,13 @@ impl TypeVisitable for CanonicalVarKind where I::Ty: TypeVisitable, { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { match self { CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) | CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) - | CanonicalVarKind::Effect => ControlFlow::Continue(()), + | CanonicalVarKind::Effect => V::Result::output(), CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => { ty.visit_with(visitor) } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 01bf79bce1c64..2ded1b956e519 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -21,13 +21,15 @@ use std::hash::Hash; #[cfg(not(feature = "nightly"))] use std::sync::Arc as Lrc; +#[macro_use] +pub mod visit; + #[cfg(feature = "nightly")] pub mod codec; pub mod fold; pub mod new; pub mod ty_info; pub mod ty_kind; -pub mod visit; #[macro_use] mod macros; diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index 231546287d027..7dcc8851a43f2 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -25,9 +25,9 @@ macro_rules! TrivialTypeTraversalImpls { fn visit_with>( &self, _: &mut F) - -> ::std::ops::ControlFlow + -> F::Result { - ::std::ops::ControlFlow::Continue(()) + ::output() } } )+ diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 8c4d0fda6af64..a0759f7df7fdd 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -1,5 +1,6 @@ +use rustc_ast_ir::try_visit; +use rustc_ast_ir::visit::VisitorResult; use std::fmt; -use std::ops::ControlFlow; use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; @@ -91,14 +92,14 @@ where I::TypeOutlivesPredicate: TypeVisitable, I::RegionOutlivesPredicate: TypeVisitable, { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { match self { ClauseKind::Trait(p) => p.visit_with(visitor), ClauseKind::RegionOutlives(p) => p.visit_with(visitor), ClauseKind::TypeOutlives(p) => p.visit_with(visitor), ClauseKind::Projection(p) => p.visit_with(visitor), ClauseKind::ConstArgHasType(c, t) => { - c.visit_with(visitor)?; + try_visit!(c.visit_with(visitor)); t.visit_with(visitor) } ClauseKind::WellFormed(p) => p.visit_with(visitor), @@ -205,21 +206,21 @@ where I::NormalizesTo: TypeVisitable, ClauseKind: TypeVisitable, { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { match self { PredicateKind::Clause(p) => p.visit_with(visitor), PredicateKind::ObjectSafe(d) => d.visit_with(visitor), PredicateKind::Subtype(s) => s.visit_with(visitor), PredicateKind::Coerce(s) => s.visit_with(visitor), PredicateKind::ConstEquate(a, b) => { - a.visit_with(visitor)?; + try_visit!(a.visit_with(visitor)); b.visit_with(visitor) } - PredicateKind::Ambiguous => ControlFlow::Continue(()), + PredicateKind::Ambiguous => V::Result::output(), PredicateKind::NormalizesTo(p) => p.visit_with(visitor), PredicateKind::AliasRelate(a, b, d) => { - a.visit_with(visitor)?; - b.visit_with(visitor)?; + try_visit!(a.visit_with(visitor)); + try_visit!(b.visit_with(visitor)); d.visit_with(visitor) } } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 00f49a07f9d81..de8f56618d000 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -1,3 +1,4 @@ +use rustc_ast_ir::try_visit; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] @@ -831,8 +832,8 @@ impl TypeVisitable for TypeAndMut where I::Ty: TypeVisitable, { - fn visit_with>(&self, visitor: &mut V) -> std::ops::ControlFlow { - self.ty.visit_with(visitor)?; + fn visit_with>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.ty.visit_with(visitor)); self.mutbl.visit_with(visitor) } } diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 638fb9f7fa9db..839e75dba4cbf 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -41,6 +41,8 @@ //! - u.visit_with(visitor) //! ``` +use rustc_ast_ir::visit::VisitorResult; +use rustc_ast_ir::{try_visit, walk_visitable_list}; use rustc_index::{Idx, IndexVec}; use std::fmt; use std::ops::ControlFlow; @@ -63,7 +65,7 @@ pub trait TypeVisitable: fmt::Debug + Clone { /// that calls a visitor method specifically for that type (such as /// `V::visit_ty`). This is where control transfers from `TypeVisitable` to /// `TypeVisitor`. - fn visit_with>(&self, visitor: &mut V) -> ControlFlow; + fn visit_with>(&self, visitor: &mut V) -> V::Result; } // This trait is implemented for types of interest. @@ -74,7 +76,7 @@ pub trait TypeSuperVisitable: TypeVisitable { /// that method. For example, in `MyVisitor::visit_ty(ty)`, it is valid to /// call `ty.super_visit_with(self)`, but any other visiting should be done /// with `xyz.visit_with(self)`. - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow; + fn super_visit_with>(&self, visitor: &mut V) -> V::Result; } /// This trait is implemented for every visiting traversal. There is a visit @@ -82,33 +84,30 @@ pub trait TypeSuperVisitable: TypeVisitable { /// that recurses into the type's fields in a non-custom fashion. pub trait TypeVisitor: Sized { #[cfg(feature = "nightly")] - type BreakTy = !; + type Result: VisitorResult = (); #[cfg(not(feature = "nightly"))] - type BreakTy; + type Result: VisitorResult; - fn visit_binder>( - &mut self, - t: &I::Binder, - ) -> ControlFlow { + fn visit_binder>(&mut self, t: &I::Binder) -> Self::Result { t.super_visit_with(self) } - fn visit_ty(&mut self, t: I::Ty) -> ControlFlow { + fn visit_ty(&mut self, t: I::Ty) -> Self::Result { t.super_visit_with(self) } // The default region visitor is a no-op because `Region` is non-recursive // and has no `super_visit_with` method to call. - fn visit_region(&mut self, _r: I::Region) -> ControlFlow { - ControlFlow::Continue(()) + fn visit_region(&mut self, _r: I::Region) -> Self::Result { + Self::Result::output() } - fn visit_const(&mut self, c: I::Const) -> ControlFlow { + fn visit_const(&mut self, c: I::Const) -> Self::Result { c.super_visit_with(self) } - fn visit_predicate(&mut self, p: I::Predicate) -> ControlFlow { + fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result { p.super_visit_with(self) } } @@ -117,8 +116,8 @@ pub trait TypeVisitor: Sized { // Traversal implementations. impl, U: TypeVisitable> TypeVisitable for (T, U) { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.0.visit_with(visitor)?; + fn visit_with>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.0.visit_with(visitor)); self.1.visit_with(visitor) } } @@ -126,24 +125,24 @@ impl, U: TypeVisitable> TypeVisitable for impl, B: TypeVisitable, C: TypeVisitable> TypeVisitable for (A, B, C) { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.0.visit_with(visitor)?; - self.1.visit_with(visitor)?; + fn visit_with>(&self, visitor: &mut V) -> V::Result { + try_visit!(self.0.visit_with(visitor)); + try_visit!(self.1.visit_with(visitor)); self.2.visit_with(visitor) } } impl> TypeVisitable for Option { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { match self { Some(v) => v.visit_with(visitor), - None => ControlFlow::Continue(()), + None => V::Result::output(), } } } impl, E: TypeVisitable> TypeVisitable for Result { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { match self { Ok(v) => v.visit_with(visitor), Err(e) => e.visit_with(visitor), @@ -152,20 +151,21 @@ impl, E: TypeVisitable> TypeVisitable for } impl> TypeVisitable for Lrc { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { (**self).visit_with(visitor) } } impl> TypeVisitable for Box { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + fn visit_with>(&self, visitor: &mut V) -> V::Result { (**self).visit_with(visitor) } } impl> TypeVisitable for Vec { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) + fn visit_with>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() } } @@ -173,20 +173,23 @@ impl> TypeVisitable for Vec { // case, because we can't return a new slice. But note that there are a couple // of trivial impls of `TypeFoldable` for specific slice types elsewhere. impl> TypeVisitable for &[T] { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) + fn visit_with>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() } } impl> TypeVisitable for Box<[T]> { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) + fn visit_with>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() } } impl, Ix: Idx> TypeVisitable for IndexVec { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) + fn visit_with>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() } } @@ -366,12 +369,9 @@ impl std::fmt::Debug for HasTypeFlagsVisitor { // is important for anonymization of binders in `TyCtxt::erase_regions`. We // specifically detect this case in `visit_binder`. impl TypeVisitor for HasTypeFlagsVisitor { - type BreakTy = FoundFlags; + type Result = ControlFlow; - fn visit_binder>( - &mut self, - t: &I::Binder, - ) -> ControlFlow { + fn visit_binder>(&mut self, t: &I::Binder) -> Self::Result { // If we're looking for the HAS_BINDER_VARS flag, check if the // binder has vars. This won't be present in the binder's bound // value, so we need to check here too. @@ -383,7 +383,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { } #[inline] - fn visit_ty(&mut self, t: I::Ty) -> ControlFlow { + fn visit_ty(&mut self, t: I::Ty) -> Self::Result { // Note: no `super_visit_with` call. let flags = t.flags(); if flags.intersects(self.flags) { @@ -394,7 +394,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { } #[inline] - fn visit_region(&mut self, r: I::Region) -> ControlFlow { + fn visit_region(&mut self, r: I::Region) -> Self::Result { // Note: no `super_visit_with` call, as usual for `Region`. let flags = r.flags(); if flags.intersects(self.flags) { @@ -405,7 +405,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { } #[inline] - fn visit_const(&mut self, c: I::Const) -> ControlFlow { + fn visit_const(&mut self, c: I::Const) -> Self::Result { // Note: no `super_visit_with` call. if c.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) @@ -415,7 +415,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { } #[inline] - fn visit_predicate(&mut self, predicate: I::Predicate) -> ControlFlow { + fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result { // Note: no `super_visit_with` call. if predicate.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) @@ -459,12 +459,9 @@ struct HasEscapingVarsVisitor { } impl TypeVisitor for HasEscapingVarsVisitor { - type BreakTy = FoundEscapingVars; + type Result = ControlFlow; - fn visit_binder>( - &mut self, - t: &I::Binder, - ) -> ControlFlow { + fn visit_binder>(&mut self, t: &I::Binder) -> Self::Result { self.outer_index.shift_in(1); let result = t.super_visit_with(self); self.outer_index.shift_out(1); @@ -472,7 +469,7 @@ impl TypeVisitor for HasEscapingVarsVisitor { } #[inline] - fn visit_ty(&mut self, t: I::Ty) -> ControlFlow { + fn visit_ty(&mut self, t: I::Ty) -> Self::Result { // 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 @@ -486,7 +483,7 @@ impl TypeVisitor for HasEscapingVarsVisitor { } #[inline] - fn visit_region(&mut self, r: I::Region) -> ControlFlow { + fn visit_region(&mut self, r: I::Region) -> Self::Result { // If the region is bound by `outer_index` or anything outside // of outer index, then it escapes the binders we have // visited. @@ -497,7 +494,7 @@ impl TypeVisitor for HasEscapingVarsVisitor { } } - fn visit_const(&mut self, ct: I::Const) -> ControlFlow { + fn visit_const(&mut self, ct: I::Const) -> Self::Result { // If the outer-exclusive-binder is *strictly greater* than // `outer_index`, that means that `ct` contains some content // bound at `outer_index` or above (because @@ -511,7 +508,7 @@ impl TypeVisitor for HasEscapingVarsVisitor { } #[inline] - fn visit_predicate(&mut self, predicate: I::Predicate) -> ControlFlow { + fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result { if predicate.outer_exclusive_binder() > self.outer_index { ControlFlow::Break(FoundEscapingVars) } else { @@ -523,9 +520,9 @@ impl TypeVisitor for HasEscapingVarsVisitor { struct HasErrorVisitor; impl TypeVisitor for HasErrorVisitor { - type BreakTy = I::ErrorGuaranteed; + type Result = ControlFlow; - fn visit_ty(&mut self, t: ::Ty) -> ControlFlow { + fn visit_ty(&mut self, t: ::Ty) -> Self::Result { if let ty::Error(guar) = t.kind() { ControlFlow::Break(guar) } else { @@ -533,7 +530,7 @@ impl TypeVisitor for HasErrorVisitor { } } - fn visit_const(&mut self, c: ::Const) -> ControlFlow { + fn visit_const(&mut self, c: ::Const) -> Self::Result { if let ty::ConstKind::Error(guar) = c.kind() { ControlFlow::Break(guar) } else { @@ -541,7 +538,7 @@ impl TypeVisitor for HasErrorVisitor { } } - fn visit_region(&mut self, r: ::Region) -> ControlFlow { + fn visit_region(&mut self, r: ::Region) -> Self::Result { if let ty::ReError(guar) = r.kind() { ControlFlow::Break(guar) } else { diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs index 514015af0455c..b8baad18cc8db 100644 --- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs @@ -22,9 +22,9 @@ fn get_enum_ty(enum_ty: Ty<'_>) -> Option> { } impl<'tcx> TypeVisitor> for ContainsTyVisitor { - type BreakTy = Ty<'tcx>; + type Result = ControlFlow>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { self.level += 1; if self.level == 1 { t.super_visit_with(self) diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index f9cc5f191253a..06229ac938f9a 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -141,9 +141,9 @@ impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, struct ContainsRegion; impl TypeVisitor> for ContainsRegion { - type BreakTy = (); + type Result = ControlFlow<()>; - fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow { + fn visit_region(&mut self, _: ty::Region<'_>) -> Self::Result { ControlFlow::Break(()) } } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 6762c88300503..6e011a28bb7bc 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -916,8 +916,8 @@ pub fn for_each_top_level_late_bound_region( f: F, } impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow> TypeVisitor> for V { - type BreakTy = B; - fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow { + type Result = ControlFlow; + fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result { if let RegionKind::ReBound(idx, bound) = r.kind() && idx.as_u32() == self.index { @@ -926,7 +926,7 @@ pub fn for_each_top_level_late_bound_region( ControlFlow::Continue(()) } } - fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) -> ControlFlow { + fn visit_binder>>(&mut self, t: &Binder<'tcx, T>) -> Self::Result { self.index += 1; let res = t.super_visit_with(self); self.index -= 1;