Convert TypeVisitor and DefIdVisitor to use VisitorResult

This commit is contained in:
Jason Newcomb 2024-02-24 17:22:28 -05:00
parent 5abfb3775d
commit be9b125d41
53 changed files with 345 additions and 448 deletions

View File

@ -3970,6 +3970,7 @@ version = "0.0.0"
dependencies = [ dependencies = [
"itertools 0.11.0", "itertools 0.11.0",
"rustc_ast", "rustc_ast",
"rustc_ast_ir",
"rustc_attr", "rustc_attr",
"rustc_data_structures", "rustc_data_structures",
"rustc_errors", "rustc_errors",
@ -4038,6 +4039,7 @@ dependencies = [
name = "rustc_infer" name = "rustc_infer"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"rustc_ast_ir",
"rustc_data_structures", "rustc_data_structures",
"rustc_errors", "rustc_errors",
"rustc_fluent_macro", "rustc_fluent_macro",
@ -4632,6 +4634,7 @@ dependencies = [
"bitflags 2.4.2", "bitflags 2.4.2",
"itertools 0.11.0", "itertools 0.11.0",
"rustc_ast", "rustc_ast",
"rustc_ast_ir",
"rustc_attr", "rustc_attr",
"rustc_data_structures", "rustc_data_structures",
"rustc_errors", "rustc_errors",
@ -4670,6 +4673,7 @@ name = "rustc_transmute"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"itertools 0.11.0", "itertools 0.11.0",
"rustc_ast_ir",
"rustc_data_structures", "rustc_data_structures",
"rustc_hir", "rustc_hir",
"rustc_infer", "rustc_infer",

View File

@ -30,9 +30,9 @@ where
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor<'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor<'tcx> {
type BreakTy = FoundParam; type Result = ControlFlow<FoundParam>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
if !ty.has_param() { if !ty.has_param() {
return ControlFlow::Continue(()); return ControlFlow::Continue(());
} }
@ -64,7 +64,7 @@ where
} }
} }
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
match c.kind() { match c.kind() {
ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam), ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
_ => c.super_visit_with(self), _ => c.super_visit_with(self),

View File

@ -17,7 +17,7 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor}; use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor};
use std::mem; use std::mem;
use std::ops::{ControlFlow, Deref}; use std::ops::Deref;
use super::ops::{self, NonConstOp, Status}; use super::ops::{self, NonConstOp, Status};
use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop}; use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
@ -164,9 +164,9 @@ struct LocalReturnTyVisitor<'ck, 'mir, 'tcx> {
} }
impl<'ck, 'mir, 'tcx> TypeVisitor<TyCtxt<'tcx>> for LocalReturnTyVisitor<'ck, 'mir, 'tcx> { impl<'ck, 'mir, 'tcx> TypeVisitor<TyCtxt<'tcx>> for LocalReturnTyVisitor<'ck, 'mir, 'tcx> {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) {
match t.kind() { match t.kind() {
ty::FnPtr(_) => ControlFlow::Continue(()), ty::FnPtr(_) => {}
ty::Ref(_, _, hir::Mutability::Mut) => { ty::Ref(_, _, hir::Mutability::Mut) => {
self.checker.check_op(ops::ty::MutRef(self.kind)); self.checker.check_op(ops::ty::MutRef(self.kind));
t.super_visit_with(self) t.super_visit_with(self)

View File

@ -1474,15 +1474,14 @@ fn opaque_type_cycle_error(
closures: Vec<DefId>, closures: Vec<DefId>,
} }
impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector { impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) {
match *t.kind() { match *t.kind() {
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
self.opaques.push(def); self.opaques.push(def);
ControlFlow::Continue(())
} }
ty::Closure(def_id, ..) | ty::Coroutine(def_id, ..) => { ty::Closure(def_id, ..) | ty::Coroutine(def_id, ..) => {
self.closures.push(def_id); self.closures.push(def_id);
t.super_visit_with(self) t.super_visit_with(self);
} }
_ => t.super_visit_with(self), _ => t.super_visit_with(self),
} }

View File

@ -12,7 +12,6 @@ use rustc_trait_selection::regions::InferCtxtRegionExt;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt, 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. /// 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>( pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
@ -211,9 +210,7 @@ struct ImplTraitInTraitCollector<'tcx> {
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'tcx> {
type BreakTy = !; fn visit_ty(&mut self, ty: Ty<'tcx>) {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
if let ty::Alias(ty::Projection, proj) = *ty.kind() if let ty::Alias(ty::Projection, proj) = *ty.kind()
&& self.tcx.is_impl_trait_in_trait(proj.def_id) && self.tcx.is_impl_trait_in_trait(proj.def_id)
{ {
@ -223,12 +220,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'tcx> {
.explicit_item_bounds(proj.def_id) .explicit_item_bounds(proj.def_id)
.iter_instantiated_copied(self.tcx, proj.args) .iter_instantiated_copied(self.tcx, proj.args)
{ {
pred.visit_with(self)?; pred.visit_with(self);
} }
} }
ControlFlow::Continue(())
} else { } else {
ty.super_visit_with(self) ty.super_visit_with(self);
} }
} }
} }

View File

@ -809,9 +809,7 @@ impl<'tcx> GATArgsCollector<'tcx> {
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {
type BreakTy = !; fn visit_ty(&mut self, t: Ty<'tcx>) {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() { match t.kind() {
ty::Alias(ty::Projection, p) if p.def_id == self.gat => { ty::Alias(ty::Projection, p) if p.def_id == self.gat => {
for (idx, arg) in p.args.iter().enumerate() { 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<u32>, params: FxHashSet<u32>,
} }
impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for CountParams { impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for CountParams {
type BreakTy = (); type Result = ControlFlow<()>;
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Param(param) = t.kind() { if let ty::Param(param) = t.kind() {
self.params.insert(param.index); self.params.insert(param.index);
} }
t.super_visit_with(self) t.super_visit_with(self)
} }
fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, _: ty::Region<'tcx>) -> Self::Result {
ControlFlow::Break(()) ControlFlow::Break(())
} }
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
if let ty::ConstKind::Param(param) = c.kind() { if let ty::ConstKind::Param(param) = c.kind() {
self.params.insert(param.index); self.params.insert(param.index);
} }

View File

@ -1964,31 +1964,26 @@ fn is_late_bound_map(
arg_is_constrained: Box<[bool]>, arg_is_constrained: Box<[bool]>,
} }
use std::ops::ControlFlow;
use ty::Ty; use ty::Ty;
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostAstConv { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostAstConv {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> { fn visit_ty(&mut self, t: Ty<'tcx>) {
match t.kind() { match t.kind() {
ty::Param(param_ty) => { ty::Param(param_ty) => {
self.arg_is_constrained[param_ty.index as usize] = true; 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) t.super_visit_with(self)
} }
fn visit_const(&mut self, _: ty::Const<'tcx>) -> ControlFlow<!> { fn visit_const(&mut self, _: ty::Const<'tcx>) {}
ControlFlow::Continue(())
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<!> { fn visit_region(&mut self, r: ty::Region<'tcx>) {
debug!("r={:?}", r.kind()); debug!("r={:?}", r.kind());
if let ty::RegionKind::ReEarlyParam(region) = r.kind() { if let ty::RegionKind::ReEarlyParam(region) = r.kind() {
self.arg_is_constrained[region.index as usize] = true; self.arg_is_constrained[region.index as usize] = true;
} }
ControlFlow::Continue(())
} }
} }

View File

@ -1,9 +1,8 @@
use rustc_data_structures::fx::FxHashSet; 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_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span; use rustc_span::Span;
use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::fold::TypeFoldable;
use std::ops::ControlFlow;
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct Parameter(pub u32); pub struct Parameter(pub u32);
@ -61,13 +60,13 @@ struct ParameterCollector {
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) {
match *t.kind() { match *t.kind() {
// Projections are not injective in general. // Projections are not injective in general.
ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _)
if !self.include_nonconstraining => if !self.include_nonconstraining =>
{ {
return ControlFlow::Continue(()); return;
} }
// All weak alias types should've been expanded beforehand. // All weak alias types should've been expanded beforehand.
ty::Alias(ty::Weak, _) if !self.include_nonconstraining => { ty::Alias(ty::Weak, _) if !self.include_nonconstraining => {
@ -80,18 +79,17 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector {
t.super_visit_with(self) t.super_visit_with(self)
} }
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) {
if let ty::ReEarlyParam(data) = *r { if let ty::ReEarlyParam(data) = *r {
self.parameters.push(Parameter::from(data)); self.parameters.push(Parameter::from(data));
} }
ControlFlow::Continue(())
} }
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: ty::Const<'tcx>) {
match c.kind() { match c.kind() {
ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => { ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => {
// Constant expressions are not injective in general. // Constant expressions are not injective in general.
return c.ty().visit_with(self); return;
} }
ty::ConstKind::Param(data) => { ty::ConstKind::Param(data) => {
self.parameters.push(Parameter::from(data)); self.parameters.push(Parameter::from(data));

View File

@ -10,7 +10,6 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt}; use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt};
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
use std::ops::ControlFlow;
/// Defines the `TermsContext` basically houses an arena where we can /// Defines the `TermsContext` basically houses an arena where we can
/// allocate terms. /// allocate terms.
@ -89,15 +88,14 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> { impl<'tcx> OpaqueTypeLifetimeCollector<'tcx> {
#[instrument(level = "trace", skip(self), ret)] #[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) { 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); let child_variances = self.tcx.variances_of(def_id);
for (a, v) in args.iter().zip_eq(child_variances) { for (a, v) in args.iter().zip_eq(child_variances) {
if *v != ty::Bivariant { if *v != ty::Bivariant {
a.visit_with(self)?; a.visit_with(self);
} }
} }
ControlFlow::Continue(())
} else { } else {
args.visit_with(self) args.visit_with(self)
} }
@ -106,20 +104,19 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeLifetimeCollector<'tcx> { impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeLifetimeCollector<'tcx> {
#[instrument(level = "trace", skip(self), ret)] #[instrument(level = "trace", skip(self), ret)]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) {
if let ty::RegionKind::ReEarlyParam(ebr) = r.kind() { if let ty::RegionKind::ReEarlyParam(ebr) = r.kind() {
self.variances[ebr.index as usize] = ty::Invariant; self.variances[ebr.index as usize] = ty::Invariant;
} }
ControlFlow::Continue(())
} }
#[instrument(level = "trace", skip(self), ret)] #[instrument(level = "trace", skip(self), ret)]
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) {
match t.kind() { match t.kind() {
ty::Alias(_, ty::AliasTy { def_id, args, .. }) ty::Alias(_, ty::AliasTy { def_id, args, .. })
if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) => 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), _ => t.super_visit_with(self),
} }

View File

@ -7,6 +7,7 @@ edition = "2021"
# tidy-alphabetical-start # tidy-alphabetical-start
itertools = "0.11" itertools = "0.11"
rustc_ast = { path = "../rustc_ast" } rustc_ast = { path = "../rustc_ast" }
rustc_ast_ir = { path = "../rustc_ast_ir" }
rustc_attr = { path = "../rustc_attr" } rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" } rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" } rustc_errors = { path = "../rustc_errors" }

View File

@ -396,9 +396,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty: Ty<'tcx>, expected_ty: Ty<'tcx>,
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MentionsTy<'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MentionsTy<'tcx> {
type BreakTy = (); type Result = ControlFlow<()>;
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
if t == self.expected_ty { if t == self.expected_ty {
ControlFlow::Break(()) ControlFlow::Break(())
} else { } else {

View File

@ -337,8 +337,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Option<ty::GenericArg<'tcx>> { ) -> Option<ty::GenericArg<'tcx>> {
struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId); struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId);
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindAmbiguousParameter<'_, 'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindAmbiguousParameter<'_, 'tcx> {
type BreakTy = ty::GenericArg<'tcx>; type Result = ControlFlow<ty::GenericArg<'tcx>>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
if let Some(origin) = self.0.type_var_origin(ty) if let Some(origin) = self.0.type_var_origin(ty)
&& let TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind && let TypeVariableOriginKind::TypeParameterDefinition(_, def_id) = origin.kind
&& let generics = self.0.tcx.generics_of(self.1) && let generics = self.0.tcx.generics_of(self.1)

View File

@ -8,6 +8,7 @@ doctest = false
[dependencies] [dependencies]
# tidy-alphabetical-start # tidy-alphabetical-start
rustc_ast_ir = { path = "../rustc_ast_ir" }
rustc_data_structures = { path = "../rustc_data_structures" } rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" } rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fluent_macro = { path = "../rustc_fluent_macro" }

View File

@ -79,7 +79,7 @@ use rustc_middle::ty::{
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span}; use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi; use rustc_target::spec::abi;
use std::borrow::Cow; use std::borrow::Cow;
use std::ops::{ControlFlow, Deref}; use std::ops::Deref;
use std::path::PathBuf; use std::path::PathBuf;
use std::{cmp, fmt, iter}; use std::{cmp, fmt, iter};
@ -1623,7 +1623,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
} }
impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypesVisitor<'tcx> { impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypesVisitor<'tcx> {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) {
if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) { if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) {
let span = self.tcx.def_span(def_id); let span = self.tcx.def_span(def_id);
// Avoid cluttering the output when the "found" and error span overlap: // Avoid cluttering the output when the "found" and error span overlap:

View File

@ -23,7 +23,6 @@ use rustc_span::symbol::Ident;
use rustc_span::Span; use rustc_span::Span;
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
use std::ops::ControlFlow;
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Print the error message for lifetime errors when the return type is a static `impl Trait`, /// 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<DefId>); pub struct TraitObjectVisitor(pub FxIndexSet<DefId>);
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for TraitObjectVisitor { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for TraitObjectVisitor {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) {
match t.kind() { match t.kind() {
ty::Dynamic(preds, re, _) if re.is_static() => { ty::Dynamic(preds, re, _) if re.is_static() => {
if let Some(def_id) = preds.principal_def_id() { if let Some(def_id) = preds.principal_def_id() {
self.0.insert(def_id); self.0.insert(def_id);
} }
ControlFlow::Continue(())
} }
_ => t.super_visit_with(self), _ => t.super_visit_with(self),
} }

View File

@ -16,8 +16,6 @@ use rustc_middle::ty::print::RegionHighlightMode;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
use rustc_span::Span; use rustc_span::Span;
use std::ops::ControlFlow;
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`. /// 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<ErrorGuaranteed> { pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorGuaranteed> {
@ -76,12 +74,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
} }
impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for HighlightBuilder<'tcx> { impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for HighlightBuilder<'tcx> {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) {
if !r.has_name() && self.counter <= 3 { if !r.has_name() && self.counter <= 3 {
self.highlight.highlighting_region(r, self.counter); self.highlight.highlighting_region(r, self.counter);
self.counter += 1; self.counter += 1;
} }
ControlFlow::Continue(())
} }
} }

View File

@ -17,7 +17,6 @@ use rustc_middle::ty::{
TypeVisitable, TypeVisitableExt, TypeVisitor, TypeVisitable, TypeVisitableExt, TypeVisitor,
}; };
use rustc_span::Span; use rustc_span::Span;
use std::ops::ControlFlow;
mod table; mod table;
@ -415,29 +414,22 @@ impl<'tcx, OP> TypeVisitor<TyCtxt<'tcx>> for ConstrainOpaqueTypeRegionVisitor<'t
where where
OP: FnMut(ty::Region<'tcx>), OP: FnMut(ty::Region<'tcx>),
{ {
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
&mut self,
t: &ty::Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
t.super_visit_with(self); t.super_visit_with(self);
ControlFlow::Continue(())
} }
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) {
match *r { match *r {
// ignore bound regions, keep visiting // ignore bound regions, keep visiting
ty::ReBound(_, _) => ControlFlow::Continue(()), ty::ReBound(_, _) => {}
_ => { _ => (self.op)(r),
(self.op)(r);
ControlFlow::Continue(())
}
} }
} }
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) {
// We're only interested in types involving regions // We're only interested in types involving regions
if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) { if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
return ControlFlow::Continue(()); return;
} }
match ty.kind() { match ty.kind() {
@ -488,8 +480,6 @@ where
ty.super_visit_with(self); ty.super_visit_with(self);
} }
} }
ControlFlow::Continue(())
} }
} }

View File

@ -2,8 +2,6 @@ use rustc_middle::ty::{
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
}; };
use std::ops::ControlFlow;
use crate::infer::outlives::test_type_match; use crate::infer::outlives::test_type_match;
use crate::infer::region_constraints::VerifyIfEq; use crate::infer::region_constraints::VerifyIfEq;
@ -26,29 +24,22 @@ impl<'tcx, OP> TypeVisitor<TyCtxt<'tcx>> for FreeRegionsVisitor<'tcx, OP>
where where
OP: FnMut(ty::Region<'tcx>), OP: FnMut(ty::Region<'tcx>),
{ {
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
&mut self,
t: &ty::Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
t.super_visit_with(self); t.super_visit_with(self);
ControlFlow::Continue(())
} }
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) {
match *r { match *r {
// ignore bound regions, keep visiting // ignore bound regions, keep visiting
ty::ReBound(_, _) => ControlFlow::Continue(()), ty::ReBound(_, _) => {}
_ => { _ => (self.op)(r),
(self.op)(r);
ControlFlow::Continue(())
}
} }
} }
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) {
// We're only interested in types involving regions // We're only interested in types involving regions
if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_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 // 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) && outlives_bounds[1..].iter().all(|other_r| other_r == r)
{ {
assert!(r.type_flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS)); assert!(r.type_flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS));
r.visit_with(self)?; r.visit_with(self);
} else { } else {
// Skip lifetime parameters that are not captures. // Skip lifetime parameters that are not captures.
let variances = match kind { let variances = match kind {
@ -114,17 +105,13 @@ where
if variances.map(|variances| variances[idx]) if variances.map(|variances| variances[idx])
!= Some(ty::Variance::Bivariant) != Some(ty::Variance::Bivariant)
{ {
s.visit_with(self)?; s.visit_with(self);
} }
} }
} }
} }
_ => { _ => ty.super_visit_with(self),
ty.super_visit_with(self)?;
}
} }
ControlFlow::Continue(())
} }
} }

View File

@ -1,11 +1,11 @@
use crate::traits; use crate::traits;
use crate::traits::project::Normalized; use crate::traits::project::Normalized;
use rustc_ast_ir::try_visit;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable}; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable};
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor}; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor};
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use std::fmt; use std::fmt;
use std::ops::ControlFlow;
// Structural impls for the structs in `traits`. // Structural impls for the structs in `traits`.
@ -84,8 +84,8 @@ impl<'tcx, O: TypeFoldable<TyCtxt<'tcx>>> TypeFoldable<TyCtxt<'tcx>>
impl<'tcx, O: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> impl<'tcx, O: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>>
for traits::Obligation<'tcx, O> for traits::Obligation<'tcx, O>
{ {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
self.predicate.visit_with(visitor)?; try_visit!(self.predicate.visit_with(visitor));
self.param_env.visit_with(visitor) self.param_env.visit_with(visitor)
} }
} }

View File

@ -1474,9 +1474,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
struct ProhibitOpaqueTypes; struct ProhibitOpaqueTypes;
impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for ProhibitOpaqueTypes { impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for ProhibitOpaqueTypes {
type BreakTy = Ty<'tcx>; type Result = ControlFlow<Ty<'tcx>>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
if !ty.has_opaque_types() { if !ty.has_opaque_types() {
return ControlFlow::Continue(()); return ControlFlow::Continue(());
} }
@ -1620,9 +1620,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
} }
impl<'vis, 'a, 'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for FnPtrFinder<'vis, 'a, 'tcx> { impl<'vis, 'a, 'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for FnPtrFinder<'vis, 'a, 'tcx> {
type BreakTy = Ty<'tcx>; type Result = ControlFlow<Ty<'tcx>>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
if let ty::FnPtr(sig) = ty.kind() if let ty::FnPtr(sig) = ty.kind()
&& !self.visitor.is_internal_abi(sig.abi()) && !self.visitor.is_internal_abi(sig.abi())
{ {

View File

@ -34,7 +34,14 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
s.add_bounds(synstructure::AddBounds::Generics); s.add_bounds(synstructure::AddBounds::Generics);
let body_visit = s.each(|bind| { let body_visit = s.each(|bind| {
quote! { 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); 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>>>( fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(
&self, &self,
__visitor: &mut __V __visitor: &mut __V
) -> ::std::ops::ControlFlow<__V::BreakTy> { ) -> __V::Result {
match *self { #body_visit } match *self { #body_visit }
::std::ops::ControlFlow::Continue(()) <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
} }
}, },
) )

View File

@ -85,9 +85,9 @@ macro_rules! TrivialTypeTraversalImpls {
fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<'tcx>>>( fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<'tcx>>>(
&self, &self,
_: &mut F) _: &mut F)
-> ::std::ops::ControlFlow<F::BreakTy> -> F::Result
{ {
::std::ops::ControlFlow::Continue(()) <F::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
} }
} }
)+ )+

View File

@ -1,6 +1,6 @@
use std::ops::ControlFlow; use rustc_ast_ir::try_visit;
use rustc_data_structures::intern::Interned; use rustc_data_structures::intern::Interned;
use rustc_span::def_id::DefId;
use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints}; use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints};
use crate::traits::query::NoSolution; use crate::traits::query::NoSolution;
@ -9,7 +9,6 @@ use crate::ty::{
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable,
TypeVisitor, TypeVisitor,
}; };
use rustc_span::def_id::DefId;
use super::BuiltinImplSource; use super::BuiltinImplSource;
@ -196,13 +195,9 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
} }
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> { impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>( fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
&self, try_visit!(self.region_constraints.visit_with(visitor));
visitor: &mut V, self.opaque_types.visit_with(visitor)
) -> std::ops::ControlFlow<V::BreakTy> {
self.region_constraints.visit_with(visitor)?;
self.opaque_types.visit_with(visitor)?;
ControlFlow::Continue(())
} }
} }
@ -235,10 +230,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
} }
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> { impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for PredefinedOpaques<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>( fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
&self,
visitor: &mut V,
) -> std::ops::ControlFlow<V::BreakTy> {
self.opaque_types.visit_with(visitor) self.opaque_types.visit_with(visitor)
} }
} }

View File

@ -482,9 +482,9 @@ pub struct IsSuggestableVisitor<'tcx> {
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> {
type BreakTy = (); type Result = ControlFlow<()>;
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
match *t.kind() { match *t.kind() {
Infer(InferTy::TyVar(_)) if self.infer_suggestable => {} Infer(InferTy::TyVar(_)) if self.infer_suggestable => {}
@ -536,7 +536,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> {
t.super_visit_with(self) t.super_visit_with(self)
} }
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result {
match c.kind() { match c.kind() {
ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => {} ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => {}

View File

@ -6,6 +6,8 @@ use crate::ty::sty::{ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineCon
use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; 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_data_structures::intern::Interned;
use rustc_errors::{DiagArgValue, IntoDiagnosticArg}; use rustc_errors::{DiagArgValue, IntoDiagnosticArg};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -19,7 +21,7 @@ use std::cmp::Ordering;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
use std::num::NonZero; use std::num::NonZero;
use std::ops::{ControlFlow, Deref}; use std::ops::Deref;
use std::ptr::NonNull; use std::ptr::NonNull;
/// An entity in the Rust type system, which can be one of /// An entity in the Rust type system, which can be one of
@ -240,7 +242,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArg<'tcx> {
} }
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for GenericArg<'tcx> { impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for GenericArg<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
match self.unpack() { match self.unpack() {
GenericArgKind::Lifetime(lt) => lt.visit_with(visitor), GenericArgKind::Lifetime(lt) => lt.visit_with(visitor),
GenericArgKind::Type(ty) => ty.visit_with(visitor), GenericArgKind::Type(ty) => ty.visit_with(visitor),
@ -554,8 +556,9 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for &'tcx ty::List<T> { impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for &'tcx ty::List<T> {
#[inline] #[inline]
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
self.iter().try_for_each(|t| t.visit_with(visitor)) walk_visitable_list!(visitor, self.iter());
V::Result::output()
} }
} }

View File

@ -33,7 +33,7 @@ pub use generics::*;
pub use intrinsic::IntrinsicDef; pub use intrinsic::IntrinsicDef;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast::node_id::NodeMap; 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_attr as attr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned; use rustc_data_structures::intern::Interned;
@ -64,7 +64,6 @@ use std::hash::{Hash, Hasher};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
use std::num::NonZero; use std::num::NonZero;
use std::ops::ControlFlow;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::{fmt, str}; use std::{fmt, str};
@ -599,7 +598,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> {
} }
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> { impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
self.unpack().visit_with(visitor) self.unpack().visit_with(visitor)
} }
} }
@ -1043,8 +1042,8 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
} }
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ParamEnv<'tcx> { impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
self.caller_bounds().visit_with(visitor)?; try_visit!(self.caller_bounds().visit_with(visitor));
self.reveal().visit_with(visitor) self.reveal().visit_with(visitor)
} }
} }

View File

@ -27,7 +27,7 @@ use std::cell::Cell;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fmt::{self, Write as _}; use std::fmt::{self, Write as _};
use std::iter; use std::iter;
use std::ops::{ControlFlow, Deref, DerefMut}; use std::ops::{Deref, DerefMut};
// `pretty` is a separate module only for organization. // `pretty` is a separate module only for organization.
use super::*; use super::*;
@ -2667,9 +2667,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
} }
impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for RegionNameCollector<'tcx> { impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for RegionNameCollector<'tcx> {
type BreakTy = (); fn visit_region(&mut self, r: ty::Region<'tcx>) {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
trace!("address: {:p}", r.0.0); trace!("address: {:p}", r.0.0);
// Collect all named lifetimes. These allow us to prevent duplication // 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() { if let Some(name) = r.get_name() {
self.used_region_names.insert(name); self.used_region_names.insert(name);
} }
ControlFlow::Continue(())
} }
// We collect types in order to prevent really large types from compiling for // 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. // a really long time. See issue #83150 for why this is necessary.
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) {
let not_previously_inserted = self.type_collector.insert(ty); let not_previously_inserted = self.type_collector.insert(ty);
if not_previously_inserted { if not_previously_inserted {
ty.super_visit_with(self) ty.super_visit_with(self)
} else {
ControlFlow::Continue(())
} }
} }
} }

View File

@ -8,13 +8,14 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; 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_hir::def::Namespace;
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;
use rustc_target::abi::TyAndLayout; use rustc_target::abi::TyAndLayout;
use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, WithInfcx}; use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, WithInfcx};
use std::fmt::{self, Debug}; use std::fmt::{self, Debug};
use std::ops::ControlFlow;
use super::print::PrettyPrinter; use super::print::PrettyPrinter;
use super::{GenericArg, GenericArgKind, Region}; use super::{GenericArg, GenericArgKind, Region};
@ -482,11 +483,8 @@ impl<'a, 'tcx> Lift<'tcx> for Term<'a> {
// Traversal implementations. // Traversal implementations.
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> { impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>( fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, _visitor: &mut V) -> V::Result {
&self, V::Result::output()
_visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
ControlFlow::Continue(())
} }
} }
@ -500,7 +498,7 @@ impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> TypeFoldable<TyCtxt<'tcx>> for ty::Bin
} }
impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> { impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
visitor.visit_binder(self) visitor.visit_binder(self)
} }
} }
@ -517,10 +515,7 @@ impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> TypeSuperFoldable<TyCtxt<'tcx>> for ty
impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeSuperVisitable<TyCtxt<'tcx>> impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeSuperVisitable<TyCtxt<'tcx>>
for ty::Binder<'tcx, T> for ty::Binder<'tcx, T>
{ {
fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>( fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
&self,
visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
self.as_ref().skip_binder().visit_with(visitor) self.as_ref().skip_binder().visit_with(visitor)
} }
} }
@ -553,7 +548,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
} }
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Ty<'tcx> { impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
visitor.visit_ty(*self) visitor.visit_ty(*self)
} }
} }
@ -609,27 +604,24 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
} }
impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> { impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>( fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
&self,
visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
match self.kind() { match self.kind() {
ty::RawPtr(ref tm) => tm.visit_with(visitor), ty::RawPtr(ref tm) => tm.visit_with(visitor),
ty::Array(typ, sz) => { ty::Array(typ, sz) => {
typ.visit_with(visitor)?; try_visit!(typ.visit_with(visitor));
sz.visit_with(visitor) sz.visit_with(visitor)
} }
ty::Slice(typ) => typ.visit_with(visitor), ty::Slice(typ) => typ.visit_with(visitor),
ty::Adt(_, args) => args.visit_with(visitor), ty::Adt(_, args) => args.visit_with(visitor),
ty::Dynamic(ref trait_ty, ref reg, _) => { ty::Dynamic(ref trait_ty, ref reg, _) => {
trait_ty.visit_with(visitor)?; try_visit!(trait_ty.visit_with(visitor));
reg.visit_with(visitor) reg.visit_with(visitor)
} }
ty::Tuple(ts) => ts.visit_with(visitor), ty::Tuple(ts) => ts.visit_with(visitor),
ty::FnDef(_, args) => args.visit_with(visitor), ty::FnDef(_, args) => args.visit_with(visitor),
ty::FnPtr(ref f) => f.visit_with(visitor), ty::FnPtr(ref f) => f.visit_with(visitor),
ty::Ref(r, ty, _) => { ty::Ref(r, ty, _) => {
r.visit_with(visitor)?; try_visit!(r.visit_with(visitor));
ty.visit_with(visitor) ty.visit_with(visitor)
} }
ty::Coroutine(_did, ref args) => args.visit_with(visitor), ty::Coroutine(_did, ref args) => args.visit_with(visitor),
@ -650,7 +642,7 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
| ty::Placeholder(..) | ty::Placeholder(..)
| ty::Param(..) | ty::Param(..)
| ty::Never | ty::Never
| ty::Foreign(..) => ControlFlow::Continue(()), | ty::Foreign(..) => V::Result::output(),
} }
} }
} }
@ -665,7 +657,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Region<'tcx> {
} }
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Region<'tcx> { impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Region<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
visitor.visit_region(*self) visitor.visit_region(*self)
} }
} }
@ -690,13 +682,13 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
} }
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> { impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
visitor.visit_predicate(*self) visitor.visit_predicate(*self)
} }
} }
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Clause<'tcx> { impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
visitor.visit_predicate(self.as_predicate()) visitor.visit_predicate(self.as_predicate())
} }
} }
@ -712,10 +704,7 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
} }
impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> { impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>( fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
&self,
visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
self.kind().visit_with(visitor) self.kind().visit_with(visitor)
} }
} }
@ -739,7 +728,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
} }
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> { impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
visitor.visit_const(*self) visitor.visit_const(*self)
} }
} }
@ -771,16 +760,13 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
} }
impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> { impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>( fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
&self, try_visit!(self.ty().visit_with(visitor));
visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
self.ty().visit_with(visitor)?;
match self.kind() { match self.kind() {
ConstKind::Param(p) => p.visit_with(visitor), ConstKind::Param(p) => p.visit_with(visitor),
ConstKind::Infer(i) => i.visit_with(visitor), ConstKind::Infer(i) => i.visit_with(visitor),
ConstKind::Bound(d, b) => { ConstKind::Bound(d, b) => {
d.visit_with(visitor)?; try_visit!(d.visit_with(visitor));
b.visit_with(visitor) b.visit_with(visitor)
} }
ConstKind::Placeholder(p) => p.visit_with(visitor), ConstKind::Placeholder(p) => p.visit_with(visitor),
@ -802,25 +788,19 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for InferConst {
} }
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for InferConst { impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for InferConst {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>( fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, _visitor: &mut V) -> V::Result {
&self, V::Result::output()
_visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
ControlFlow::Continue(())
} }
} }
impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> { impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> {
fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>( fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
&self,
visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
self.args.visit_with(visitor) self.args.visit_with(visitor)
} }
} }
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> { impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
visitor.visit_ty(self.ty) visitor.visit_ty(self.ty)
} }
} }
@ -828,10 +808,9 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> {
impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>> + Debug + Clone> TypeVisitable<TyCtxt<'tcx>> impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>> + Debug + Clone> TypeVisitable<TyCtxt<'tcx>>
for Spanned<T> for Spanned<T>
{ {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
self.node.visit_with(visitor)?; try_visit!(self.node.visit_with(visitor));
self.span.visit_with(visitor)?; self.span.visit_with(visitor)
ControlFlow::Continue(())
} }
} }

View File

@ -2113,9 +2113,9 @@ impl<'tcx> Ty<'tcx> {
struct ContainsTyVisitor<'tcx>(Ty<'tcx>); struct ContainsTyVisitor<'tcx>(Ty<'tcx>);
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTyVisitor<'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTyVisitor<'tcx> {
type BreakTy = (); type Result = ControlFlow<()>;
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) } if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) }
} }
} }
@ -2131,9 +2131,9 @@ impl<'tcx> Ty<'tcx> {
struct ContainsClosureVisitor; struct ContainsClosureVisitor;
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsClosureVisitor { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsClosureVisitor {
type BreakTy = (); type Result = ControlFlow<()>;
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
if let ty::Closure(..) = t.kind() { if let ty::Closure(..) = t.kind() {
ControlFlow::Break(()) ControlFlow::Break(())
} else { } else {

View File

@ -64,19 +64,19 @@ impl<'tcx> TyCtxt<'tcx> {
where where
F: FnMut(ty::Region<'tcx>) -> bool, F: FnMut(ty::Region<'tcx>) -> bool,
{ {
type BreakTy = (); type Result = ControlFlow<()>;
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self, &mut self,
t: &Binder<'tcx, T>, t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> { ) -> Self::Result {
self.outer_index.shift_in(1); self.outer_index.shift_in(1);
let result = t.super_visit_with(self); let result = t.super_visit_with(self);
self.outer_index.shift_out(1); self.outer_index.shift_out(1);
result result
} }
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
match *r { match *r {
ty::ReBound(debruijn, _) if debruijn < self.outer_index => { ty::ReBound(debruijn, _) if debruijn < self.outer_index => {
ControlFlow::Continue(()) ControlFlow::Continue(())
@ -91,7 +91,7 @@ impl<'tcx> TyCtxt<'tcx> {
} }
} }
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
// We're only interested in types involving regions // We're only interested in types involving regions
if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) { if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
ty.super_visit_with(self) ty.super_visit_with(self)
@ -140,8 +140,7 @@ impl<'tcx> TyCtxt<'tcx> {
let mut collector = LateBoundRegionsCollector::new(just_constrained); let mut collector = LateBoundRegionsCollector::new(just_constrained);
let value = value.skip_binder(); let value = value.skip_binder();
let value = if just_constrained { self.expand_weak_alias_tys(value) } else { value }; let value = if just_constrained { self.expand_weak_alias_tys(value) } else { value };
let result = value.visit_with(&mut collector); value.visit_with(&mut collector);
assert!(result.is_continue()); // should never have stopped early
collector.regions collector.regions
} }
} }
@ -165,19 +164,19 @@ impl<'tcx> ValidateBoundVars<'tcx> {
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
type BreakTy = (); type Result = ControlFlow<()>;
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self, &mut self,
t: &Binder<'tcx, T>, t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> { ) -> Self::Result {
self.binder_index.shift_in(1); self.binder_index.shift_in(1);
let result = t.super_visit_with(self); let result = t.super_visit_with(self);
self.binder_index.shift_out(1); self.binder_index.shift_out(1);
result result
} }
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
if t.outer_exclusive_binder() < self.binder_index if t.outer_exclusive_binder() < self.binder_index
|| !self.visited.insert((self.binder_index, t)) || !self.visited.insert((self.binder_index, t))
{ {
@ -211,7 +210,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
t.super_visit_with(self) t.super_visit_with(self)
} }
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
match *r { match *r {
ty::ReBound(index, br) if index == self.binder_index => { ty::ReBound(index, br) if index == self.binder_index => {
if self.bound_vars.len() <= br.var.as_usize() { if self.bound_vars.len() <= br.var.as_usize() {
@ -266,23 +265,19 @@ impl LateBoundRegionsCollector {
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) {
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
self.current_index.shift_in(1); self.current_index.shift_in(1);
let result = t.super_visit_with(self); t.super_visit_with(self);
self.current_index.shift_out(1); self.current_index.shift_out(1);
result
} }
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) {
if self.just_constrained { if self.just_constrained {
match t.kind() { match t.kind() {
// If we are only looking for "constrained" regions, we have to ignore the // 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. // inputs to a projection as they may not appear in the normalized form.
ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) => { ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) => {
return ControlFlow::Continue(()); return;
} }
// All weak alias types should've been expanded beforehand. // All weak alias types should've been expanded beforehand.
ty::Alias(ty::Weak, _) => bug!("unexpected weak alias type"), ty::Alias(ty::Weak, _) => bug!("unexpected weak alias type"),
@ -293,26 +288,25 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
t.super_visit_with(self) t.super_visit_with(self)
} }
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: ty::Const<'tcx>) {
// if we are only looking for "constrained" region, we have to // if we are only looking for "constrained" region, we have to
// ignore the inputs of an unevaluated const, as they may not appear // ignore the inputs of an unevaluated const, as they may not appear
// in the normalized form // in the normalized form
if self.just_constrained { if self.just_constrained {
if let ty::ConstKind::Unevaluated(..) = c.kind() { if let ty::ConstKind::Unevaluated(..) = c.kind() {
return ControlFlow::Continue(()); return;
} }
} }
c.super_visit_with(self) c.super_visit_with(self)
} }
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) {
if let ty::ReBound(debruijn, br) = *r { if let ty::ReBound(debruijn, br) = *r {
if debruijn == self.current_index { if debruijn == self.current_index {
self.regions.insert(br.kind); self.regions.insert(br.kind);
} }
} }
ControlFlow::Continue(())
} }
} }
@ -332,7 +326,7 @@ impl MaxUniverse {
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) {
if let ty::Placeholder(placeholder) = t.kind() { if let ty::Placeholder(placeholder) = t.kind() {
self.max_universe = ty::UniverseIndex::from_u32( self.max_universe = ty::UniverseIndex::from_u32(
self.max_universe.as_u32().max(placeholder.universe.as_u32()), self.max_universe.as_u32().max(placeholder.universe.as_u32()),
@ -342,7 +336,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
t.super_visit_with(self) t.super_visit_with(self)
} }
fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: ty::consts::Const<'tcx>) {
if let ty::ConstKind::Placeholder(placeholder) = c.kind() { if let ty::ConstKind::Placeholder(placeholder) = c.kind() {
self.max_universe = ty::UniverseIndex::from_u32( self.max_universe = ty::UniverseIndex::from_u32(
self.max_universe.as_u32().max(placeholder.universe.as_u32()), self.max_universe.as_u32().max(placeholder.universe.as_u32()),
@ -352,13 +346,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
c.super_visit_with(self) c.super_visit_with(self)
} }
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) {
if let ty::RePlaceholder(placeholder) = *r { if let ty::RePlaceholder(placeholder) = *r {
self.max_universe = ty::UniverseIndex::from_u32( self.max_universe = ty::UniverseIndex::from_u32(
self.max_universe.as_u32().max(placeholder.universe.as_u32()), self.max_universe.as_u32().max(placeholder.universe.as_u32()),
); );
} }
ControlFlow::Continue(())
} }
} }

View File

@ -18,7 +18,6 @@ use rustc_middle::ty::{
GenericArgsRef, Ty, TyCtxt, UnusedGenericParams, GenericArgsRef, Ty, TyCtxt, UnusedGenericParams,
}; };
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use std::ops::ControlFlow;
use crate::errors::UnusedGenericParamsHint; use crate::errors::UnusedGenericParamsHint;
@ -291,31 +290,29 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: ty::Const<'tcx>) {
if !c.has_non_region_param() { if !c.has_non_region_param() {
return ControlFlow::Continue(()); return;
} }
match c.kind() { match c.kind() {
ty::ConstKind::Param(param) => { ty::ConstKind::Param(param) => {
debug!(?param); debug!(?param);
self.unused_parameters.mark_used(param.index); self.unused_parameters.mark_used(param.index);
ControlFlow::Continue(())
} }
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args })
if matches!(self.tcx.def_kind(def), DefKind::AnonConst) => if matches!(self.tcx.def_kind(def), DefKind::AnonConst) =>
{ {
self.visit_child_body(def, args); self.visit_child_body(def, args);
ControlFlow::Continue(())
} }
_ => c.super_visit_with(self), _ => c.super_visit_with(self),
} }
} }
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) {
if !ty.has_non_region_param() { if !ty.has_non_region_param() {
return ControlFlow::Continue(()); return;
} }
match *ty.kind() { match *ty.kind() {
@ -323,18 +320,16 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
debug!(?def_id); debug!(?def_id);
// Avoid cycle errors with coroutines. // Avoid cycle errors with coroutines.
if def_id == self.def_id { if def_id == self.def_id {
return ControlFlow::Continue(()); return;
} }
// Consider any generic parameters used by any closures/coroutines as used in the // Consider any generic parameters used by any closures/coroutines as used in the
// parent. // parent.
self.visit_child_body(def_id, args); self.visit_child_body(def_id, args);
ControlFlow::Continue(())
} }
ty::Param(param) => { ty::Param(param) => {
debug!(?param); debug!(?param);
self.unused_parameters.mark_used(param.index); self.unused_parameters.mark_used(param.index);
ControlFlow::Continue(())
} }
_ => ty.super_visit_with(self), _ => ty.super_visit_with(self),
} }

View File

@ -11,6 +11,7 @@ extern crate tracing;
mod errors; mod errors;
use rustc_ast::visit::{try_visit, VisitorResult};
use rustc_ast::MacroDef; use rustc_ast::MacroDef;
use rustc_attr as attr; use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet; 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 /// 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`. /// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`.
trait DefIdVisitor<'tcx> { trait DefIdVisitor<'tcx> {
type BreakTy = (); type Result: VisitorResult = ();
const SHALLOW: bool = false; const SHALLOW: bool = false;
const SKIP_ASSOC_TYS: bool = false; const SKIP_ASSOC_TYS: bool = false;
fn tcx(&self) -> TyCtxt<'tcx>; fn tcx(&self) -> TyCtxt<'tcx>;
fn visit_def_id( fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
&mut self, -> Self::Result;
def_id: DefId,
kind: &str,
descr: &dyn fmt::Display,
) -> ControlFlow<Self::BreakTy>;
/// Not overridden, but used to actually visit types and traits. /// Not overridden, but used to actually visit types and traits.
fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> { fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> {
@ -87,25 +84,16 @@ trait DefIdVisitor<'tcx> {
dummy: Default::default(), dummy: Default::default(),
} }
} }
fn visit( fn visit(&mut self, ty_fragment: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result {
&mut self,
ty_fragment: impl TypeVisitable<TyCtxt<'tcx>>,
) -> ControlFlow<Self::BreakTy> {
ty_fragment.visit_with(&mut self.skeleton()) ty_fragment.visit_with(&mut self.skeleton())
} }
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> Self::Result {
self.skeleton().visit_trait(trait_ref) self.skeleton().visit_trait(trait_ref)
} }
fn visit_predicates( fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> Self::Result {
&mut self,
predicates: ty::GenericPredicates<'tcx>,
) -> ControlFlow<Self::BreakTy> {
self.skeleton().visit_clauses(predicates.predicates) self.skeleton().visit_clauses(predicates.predicates)
} }
fn visit_clauses( fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> Self::Result {
&mut self,
clauses: &[(ty::Clause<'tcx>, Span)],
) -> ControlFlow<Self::BreakTy> {
self.skeleton().visit_clauses(clauses) self.skeleton().visit_clauses(clauses)
} }
} }
@ -120,36 +108,42 @@ impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V>
where where
V: DefIdVisitor<'tcx> + ?Sized, V: DefIdVisitor<'tcx> + ?Sized,
{ {
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> { fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> V::Result {
let TraitRef { def_id, args, .. } = trait_ref; let TraitRef { def_id, args, .. } = trait_ref;
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?; try_visit!(self.def_id_visitor.visit_def_id(
if V::SHALLOW { ControlFlow::Continue(()) } else { args.visit_with(self) } 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<V::BreakTy> { fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> V::Result {
let tcx = self.def_id_visitor.tcx(); let tcx = self.def_id_visitor.tcx();
let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(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 { if V::SHALLOW {
ControlFlow::Continue(()) V::Result::output()
} else { } 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<V::BreakTy> { fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> V::Result {
match clause.kind().skip_binder() { match clause.kind().skip_binder() {
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
self.visit_trait(trait_ref) self.visit_trait(trait_ref)
} }
ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
term.visit_with(self)?; try_visit!(term.visit_with(self));
self.visit_projection_ty(projection_ty) self.visit_projection_ty(projection_ty)
} }
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self), 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) => { ty::ClauseKind::ConstArgHasType(ct, ty) => {
ct.visit_with(self)?; try_visit!(ct.visit_with(self));
ty.visit_with(self) ty.visit_with(self)
} }
ty::ClauseKind::ConstEvaluatable(ct) => ct.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<V::BreakTy> { fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> V::Result {
clauses.into_iter().try_for_each(|&(clause, _span)| self.visit_clause(clause)) for &(clause, _) in clauses {
try_visit!(self.visit_clause(clause));
}
V::Result::output()
} }
} }
@ -166,13 +163,13 @@ impl<'tcx, V> TypeVisitor<TyCtxt<'tcx>> for DefIdVisitorSkeleton<'_, 'tcx, V>
where where
V: DefIdVisitor<'tcx> + ?Sized, V: DefIdVisitor<'tcx> + ?Sized,
{ {
type BreakTy = V::BreakTy; type Result = V::Result;
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> Self::Result {
self.visit_clause(p.as_clause().unwrap()) self.visit_clause(p.as_clause().unwrap())
} }
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
let tcx = self.def_id_visitor.tcx(); let tcx = self.def_id_visitor.tcx();
// GenericArgs are not visited here because they are visited below // GenericArgs are not visited here because they are visited below
// in `super_visit_with`. // in `super_visit_with`.
@ -183,16 +180,16 @@ where
| ty::Closure(def_id, ..) | ty::Closure(def_id, ..)
| ty::CoroutineClosure(def_id, ..) | ty::CoroutineClosure(def_id, ..)
| ty::Coroutine(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 { if V::SHALLOW {
return ControlFlow::Continue(()); return V::Result::output();
} }
// Default type visitor doesn't visit signatures of fn types. // Default type visitor doesn't visit signatures of fn types.
// Something like `fn() -> Priv {my_func}` is considered a private type even if // Something like `fn() -> Priv {my_func}` is considered a private type even if
// `my_func` is public, so we need to visit signatures. // `my_func` is public, so we need to visit signatures.
if let ty::FnDef(..) = ty.kind() { if let ty::FnDef(..) = ty.kind() {
// FIXME: this should probably use `args` from `FnDef` // 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. // Inherent static methods don't have self type in args.
// Something like `fn() {my_method}` type of the method // Something like `fn() {my_method}` type of the method
@ -200,7 +197,9 @@ where
// so we need to visit the self type additionally. // so we need to visit the self type additionally.
if let Some(assoc_item) = tcx.opt_associated_item(def_id) { if let Some(assoc_item) = tcx.opt_associated_item(def_id) {
if let Some(impl_def_id) = assoc_item.impl_container(tcx) { 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. // as visible/reachable even if `Type` is private.
// Ideally, associated types should be instantiated in the same way as // Ideally, associated types should be instantiated in the same way as
// free type aliases, but this isn't done yet. // 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, data.def_id,
match kind { match kind {
ty::Inherent | ty::Projection => "associated type", ty::Inherent | ty::Projection => "associated type",
@ -222,15 +221,17 @@ where
ty::Opaque => unreachable!(), ty::Opaque => unreachable!(),
}, },
&LazyDefPathStr { def_id: data.def_id, tcx }, &LazyDefPathStr { def_id: data.def_id, tcx },
)?; ));
// This will also visit args if necessary, so we don't need to recurse. // This will also visit args if necessary, so we don't need to recurse.
return if V::SHALLOW { return if V::SHALLOW {
ControlFlow::Continue(()) V::Result::output()
} else if kind == ty::Projection { } else if kind == ty::Projection {
self.visit_projection_ty(data) self.visit_projection_ty(data)
} else { } 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, ..) => { ty::Dynamic(predicates, ..) => {
@ -245,7 +246,7 @@ where
} }
}; };
let ty::ExistentialTraitRef { def_id, args: _ } = trait_ref; 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, .. }) => { 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). // 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 // All traits in the list are considered the "primary" part of the type
// and are visited by shallow visitors. // 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 // 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<Self::BreakTy> { fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result {
let tcx = self.def_id_visitor.tcx(); let tcx = self.def_id_visitor.tcx();
tcx.expand_abstract_consts(c).super_visit_with(self) 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> { fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx self.tcx
} }
fn visit_def_id( fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
&mut self,
def_id: DefId,
_kind: &str,
_descr: &dyn fmt::Display,
) -> ControlFlow<Self::BreakTy> {
if let Some(def_id) = def_id.as_local() { if let Some(def_id) = def_id.as_local() {
self.min = VL::new_min(self, def_id); 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> { fn tcx(&self) -> TyCtxt<'tcx> {
self.ev.tcx self.ev.tcx
} }
fn visit_def_id( fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
&mut self,
def_id: DefId,
_kind: &str,
_descr: &dyn fmt::Display,
) -> ControlFlow<Self::BreakTy> {
if let Some(def_id) = def_id.as_local() { if let Some(def_id) = def_id.as_local() {
// All effective visibilities except `reachable_through_impl_trait` are limited to // 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 // 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)); .then(|| self.ev.tcx.local_visibility(def_id));
self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level); self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level);
} }
ControlFlow::Continue(())
} }
} }
@ -1233,6 +1222,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
} }
impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
type Result = ControlFlow<()>;
fn tcx(&self) -> TyCtxt<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx self.tcx
} }
@ -1241,7 +1231,7 @@ impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
def_id: DefId, def_id: DefId,
kind: &str, kind: &str,
descr: &dyn fmt::Display, descr: &dyn fmt::Display,
) -> ControlFlow<Self::BreakTy> { ) -> Self::Result {
if self.check_def_id(def_id, kind, descr) { if self.check_def_id(def_id, kind, descr) {
ControlFlow::Break(()) ControlFlow::Break(())
} else { } else {
@ -1407,6 +1397,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
} }
impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
type Result = ControlFlow<()>;
fn tcx(&self) -> TyCtxt<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx self.tcx
} }
@ -1415,7 +1406,7 @@ impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
def_id: DefId, def_id: DefId,
kind: &str, kind: &str,
descr: &dyn fmt::Display, descr: &dyn fmt::Display,
) -> ControlFlow<Self::BreakTy> { ) -> Self::Result {
if self.check_def_id(def_id, kind, descr) { if self.check_def_id(def_id, kind, descr) {
ControlFlow::Break(()) ControlFlow::Break(())
} else { } else {

View File

@ -8,6 +8,7 @@ edition = "2021"
bitflags = "2.4.1" bitflags = "2.4.1"
itertools = "0.11.0" itertools = "0.11.0"
rustc_ast = { path = "../rustc_ast" } rustc_ast = { path = "../rustc_ast" }
rustc_ast_ir = { path = "../rustc_ast_ir" }
rustc_attr = { path = "../rustc_attr" } rustc_attr = { path = "../rustc_attr" }
rustc_data_structures = { path = "../rustc_data_structures" } rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" } rustc_errors = { path = "../rustc_errors" }

View File

@ -648,8 +648,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTermOrNotNameable<'_, 'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTermOrNotNameable<'_, 'tcx> {
type BreakTy = (); type Result = ControlFlow<()>;
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
match *t.kind() { match *t.kind() {
ty::Infer(ty::TyVar(vid)) => { ty::Infer(ty::TyVar(vid)) => {
if let ty::TermKind::Ty(term) = self.term.unpack() 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<Self::BreakTy> { fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
match c.kind() { match c.kind() {
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
if let ty::TermKind::Const(term) = self.term.unpack() if let ty::TermKind::Const(term) = self.term.unpack()

View File

@ -474,7 +474,7 @@ fn plug_infer_with_placeholders<'tcx>(
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for PlugInferWithPlaceholder<'_, 'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for PlugInferWithPlaceholder<'_, 'tcx> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) {
let ty = self.infcx.shallow_resolve(ty); let ty = self.infcx.shallow_resolve(ty);
if ty.is_ty_var() { if ty.is_ty_var() {
let Ok(InferOk { value: (), obligations }) = 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") bug!("we always expect to be able to plug an infer var with placeholder")
}; };
assert_eq!(obligations, &[]); assert_eq!(obligations, &[]);
ControlFlow::Continue(())
} else { } else {
ty.super_visit_with(self) ty.super_visit_with(self);
} }
} }
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, ct: ty::Const<'tcx>) {
let ct = self.infcx.shallow_resolve(ct); let ct = self.infcx.shallow_resolve(ct);
if ct.is_ct_infer() { if ct.is_ct_infer() {
let Ok(InferOk { value: (), obligations }) = 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") bug!("we always expect to be able to plug an infer var with placeholder")
}; };
assert_eq!(obligations, &[]); assert_eq!(obligations, &[]);
ControlFlow::Continue(())
} else { } else {
ct.super_visit_with(self) ct.super_visit_with(self);
} }
} }
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) {
if let ty::ReVar(vid) = *r { if let ty::ReVar(vid) = *r {
let r = self let r = self
.infcx .infcx
@ -555,7 +553,6 @@ fn plug_infer_with_placeholders<'tcx>(
assert_eq!(obligations, &[]); assert_eq!(obligations, &[]);
} }
} }
ControlFlow::Continue(())
} }
} }
@ -868,12 +865,12 @@ impl<'tcx, F, E> TypeVisitor<TyCtxt<'tcx>> for OrphanChecker<'tcx, F>
where where
F: FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>, F: FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
{ {
type BreakTy = OrphanCheckEarlyExit<'tcx, E>; type Result = ControlFlow<OrphanCheckEarlyExit<'tcx, E>>;
fn visit_region(&mut self, _r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, _r: ty::Region<'tcx>) -> Self::Result {
ControlFlow::Continue(()) ControlFlow::Continue(())
} }
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
// Need to lazily normalize here in with `-Znext-solver=coherence`. // Need to lazily normalize here in with `-Znext-solver=coherence`.
let ty = match (self.lazily_normalize_ty)(ty) { let ty = match (self.lazily_normalize_ty)(ty) {
Ok(ty) => ty, Ok(ty) => ty,
@ -996,7 +993,7 @@ where
/// As these should be quite rare as const arguments and especially rare as impl /// As these should be quite rare as const arguments and especially rare as impl
/// parameters, allowing uncovered const parameters in impls seems more useful /// parameters, allowing uncovered const parameters in impls seems more useful
/// than allowing `impl<T> Trait<local_fn_ptr, T> for i32` to compile. /// than allowing `impl<T> Trait<local_fn_ptr, T> for i32` to compile.
fn visit_const(&mut self, _c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, _c: ty::Const<'tcx>) -> Self::Result {
ControlFlow::Continue(()) ControlFlow::Continue(())
} }
} }

View File

@ -17,7 +17,6 @@ use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::{self, TyCtxt, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_middle::ty::{self, TyCtxt, TypeVisitable, TypeVisitableExt, TypeVisitor};
use rustc_span::Span; use rustc_span::Span;
use std::ops::ControlFlow;
use crate::traits::ObligationCtxt; use crate::traits::ObligationCtxt;
@ -170,8 +169,7 @@ fn satisfied_from_param_env<'tcx>(
} }
impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor<'a, 'tcx> { impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for Visitor<'a, 'tcx> {
type BreakTy = (); fn visit_const(&mut self, c: ty::Const<'tcx>) {
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("is_const_evaluatable: candidate={:?}", c); debug!("is_const_evaluatable: candidate={:?}", c);
if self.infcx.probe(|_| { if self.infcx.probe(|_| {
let ocx = ObligationCtxt::new(self.infcx); let ocx = ObligationCtxt::new(self.infcx);
@ -187,7 +185,7 @@ fn satisfied_from_param_env<'tcx>(
} }
if let ty::ConstKind::Expr(e) = c.kind() { if let ty::ConstKind::Expr(e) = c.kind() {
e.visit_with(self) e.visit_with(self);
} else { } else {
// FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s args. // FIXME(generic_const_exprs): This doesn't recurse into `<T as Trait<U>>::ASSOC`'s args.
// This is currently unobservable as `<T as Trait<{ U + 1 }>>::ASSOC` creates an anon const // This is currently unobservable as `<T as Trait<{ U + 1 }>>::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 // 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 // this will be incorrect. It might be worth investigating making `predicates_of` elaborate
// all of the `ConstEvaluatable` bounds rather than having a visitor here. // all of the `ConstEvaluatable` bounds rather than having a visitor here.
ControlFlow::Continue(())
} }
} }
} }

View File

@ -152,9 +152,9 @@ impl ArgKind {
struct HasNumericInferVisitor; struct HasNumericInferVisitor;
impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for HasNumericInferVisitor { impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for HasNumericInferVisitor {
type BreakTy = (); type Result = ControlFlow<()>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
if matches!(ty.kind(), ty::Infer(ty::FloatVar(_) | ty::IntVar(_))) { if matches!(ty.kind(), ty::Infer(ty::FloatVar(_) | ty::IntVar(_))) {
ControlFlow::Break(()) ControlFlow::Break(())
} else { } else {

View File

@ -435,8 +435,8 @@ fn is_impossible_associated_item(
trait_item_def_id: DefId, trait_item_def_id: DefId,
} }
impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for ReferencesOnlyParentGenerics<'tcx> { impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for ReferencesOnlyParentGenerics<'tcx> {
type BreakTy = (); type Result = ControlFlow<()>;
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { 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 this is a parameter from the trait item's own generics, then bail
if let ty::Param(param) = t.kind() if let ty::Param(param) = t.kind()
&& let param_def_id = self.generics.type_param(param, self.tcx).def_id && 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) t.super_visit_with(self)
} }
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
if let ty::ReEarlyParam(param) = r.kind() if let ty::ReEarlyParam(param) = r.kind()
&& let param_def_id = self.generics.region_param(&param, self.tcx).def_id && let param_def_id = self.generics.region_param(&param, self.tcx).def_id
&& self.tcx.parent(param_def_id) == self.trait_item_def_id && self.tcx.parent(param_def_id) == self.trait_item_def_id
@ -455,7 +455,7 @@ fn is_impossible_associated_item(
} }
ControlFlow::Continue(()) ControlFlow::Continue(())
} }
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
if let ty::ConstKind::Param(param) = ct.kind() if let ty::ConstKind::Param(param) = ct.kind()
&& let param_def_id = self.generics.const_param(&param, self.tcx).def_id && let param_def_id = self.generics.const_param(&param, self.tcx).def_id
&& self.tcx.parent(param_def_id) == self.trait_item_def_id && self.tcx.parent(param_def_id) == self.trait_item_def_id

View File

@ -834,9 +834,9 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
type BreakTy = (); type Result = ControlFlow<()>;
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
match t.kind() { match t.kind() {
ty::Param(_) => { ty::Param(_) => {
if t == self.tcx.types.self_param { if t == self.tcx.types.self_param {
@ -887,7 +887,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<TyCtxt<'tcx>>>(
} }
} }
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
// Constants can only influence object safety if they are generic and reference `Self`. // 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. // This is only possible for unevaluated constants, so we walk these here.
self.tcx.expand_abstract_consts(ct).super_visit_with(self) self.tcx.expand_abstract_consts(ct).super_visit_with(self)

View File

@ -18,8 +18,6 @@ use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableEx
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
use std::ops::ControlFlow;
use super::NoSolution; use super::NoSolution;
pub use rustc_middle::traits::query::NormalizationResult; pub use rustc_middle::traits::query::NormalizationResult;
@ -123,28 +121,23 @@ struct MaxEscapingBoundVarVisitor {
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
&mut self,
t: &ty::Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
self.outer_index.shift_in(1); self.outer_index.shift_in(1);
let result = t.super_visit_with(self); t.super_visit_with(self);
self.outer_index.shift_out(1); self.outer_index.shift_out(1);
result
} }
#[inline] #[inline]
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) {
if t.outer_exclusive_binder() > self.outer_index { if t.outer_exclusive_binder() > self.outer_index {
self.escaping = self self.escaping = self
.escaping .escaping
.max(t.outer_exclusive_binder().as_usize() - self.outer_index.as_usize()); .max(t.outer_exclusive_binder().as_usize() - self.outer_index.as_usize());
} }
ControlFlow::Continue(())
} }
#[inline] #[inline]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: ty::Region<'tcx>) {
match *r { match *r {
ty::ReBound(debruijn, _) if debruijn > self.outer_index => { ty::ReBound(debruijn, _) if debruijn > self.outer_index => {
self.escaping = self.escaping =
@ -152,16 +145,14 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {
} }
_ => {} _ => {}
} }
ControlFlow::Continue(())
} }
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, ct: ty::Const<'tcx>) {
if ct.outer_exclusive_binder() > self.outer_index { if ct.outer_exclusive_binder() > self.outer_index {
self.escaping = self self.escaping = self
.escaping .escaping
.max(ct.outer_exclusive_binder().as_usize() - self.outer_index.as_usize()); .max(ct.outer_exclusive_binder().as_usize() - self.outer_index.as_usize());
} }
ControlFlow::Continue(())
} }
} }

View File

@ -53,9 +53,9 @@ impl<'tcx> Search<'tcx> {
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
type BreakTy = Ty<'tcx>; type Result = ControlFlow<Ty<'tcx>>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
debug!("Search visiting ty: {:?}", ty); debug!("Search visiting ty: {:?}", ty);
let (adt_def, args) = match *ty.kind() { let (adt_def, args) = match *ty.kind() {

View File

@ -5,13 +5,14 @@ edition = "2021"
[dependencies] [dependencies]
# tidy-alphabetical-start # tidy-alphabetical-start
rustc_data_structures = { path = "../rustc_data_structures"} rustc_ast_ir = { path = "../rustc_ast_ir", optional = true }
rustc_hir = { path = "../rustc_hir", optional = true} rustc_data_structures = { path = "../rustc_data_structures" }
rustc_infer = { path = "../rustc_infer", optional = true} rustc_hir = { path = "../rustc_hir", optional = true }
rustc_macros = { path = "../rustc_macros", optional = true} rustc_infer = { path = "../rustc_infer", optional = true }
rustc_middle = { path = "../rustc_middle", optional = true} rustc_macros = { path = "../rustc_macros", optional = true }
rustc_span = { path = "../rustc_span", optional = true} rustc_middle = { path = "../rustc_middle", optional = true }
rustc_target = { path = "../rustc_target", optional = true} rustc_span = { path = "../rustc_span", optional = true }
rustc_target = { path = "../rustc_target", optional = true }
tracing = "0.1" tracing = "0.1"
# tidy-alphabetical-end # tidy-alphabetical-end
@ -23,6 +24,7 @@ rustc = [
"rustc_middle", "rustc_middle",
"rustc_span", "rustc_span",
"rustc_target", "rustc_target",
"rustc_ast_ir",
] ]
[dev-dependencies] [dev-dependencies]

View File

@ -202,8 +202,8 @@ impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'t
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
#[instrument(skip(self), ret, level = "trace")] #[instrument(skip(self), ret, level = "trace")]
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> { fn visit_ty(&mut self, t: Ty<'tcx>) {
t.super_visit_with(self)?; t.super_visit_with(self);
match t.kind() { match t.kind() {
ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => { ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
self.visit_opaque_ty(alias_ty); self.visit_opaque_ty(alias_ty);
@ -212,7 +212,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
self.tcx self.tcx
.type_of(alias_ty.def_id) .type_of(alias_ty.def_id)
.instantiate(self.tcx, alias_ty.args) .instantiate(self.tcx, alias_ty.args)
.visit_with(self)?; .visit_with(self);
} }
ty::Alias(ty::Projection, alias_ty) => { ty::Alias(ty::Projection, alias_ty) => {
// This avoids having to do normalization of `Self::AssocTy` by only // This avoids having to do normalization of `Self::AssocTy` by only
@ -244,11 +244,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
); );
if check_args_compatible(self.tcx, assoc, impl_args) { if check_args_compatible(self.tcx, assoc, impl_args) {
return self self.tcx
.tcx
.type_of(assoc.def_id) .type_of(assoc.def_id)
.instantiate(self.tcx, impl_args) .instantiate(self.tcx, impl_args)
.visit_with(self); .visit_with(self);
return;
} else { } else {
self.tcx.dcx().span_delayed_bug( self.tcx.dcx().span_delayed_bug(
self.tcx.def_span(assoc.def_id), self.tcx.def_span(assoc.def_id),
@ -261,10 +261,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
} }
ty::Adt(def, _) if def.did().is_local() => { ty::Adt(def, _) if def.did().is_local() => {
if let CollectionMode::ImplTraitInAssocTypes = self.mode { if let CollectionMode::ImplTraitInAssocTypes = self.mode {
return ControlFlow::Continue(()); return;
} }
if !self.seen.insert(def.did().expect_local()) { if !self.seen.insert(def.did().expect_local()) {
return ControlFlow::Continue(()); return;
} }
for variant in def.variants().iter() { for variant in def.variants().iter() {
for field in variant.fields.iter() { for field in variant.fields.iter() {
@ -283,7 +283,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
} }
_ => trace!(kind=?t.kind()), _ => trace!(kind=?t.kind()),
} }
ControlFlow::Continue(())
} }
} }

View File

@ -174,17 +174,13 @@ struct ImplTraitInTraitFinder<'a, 'tcx> {
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, binder: &ty::Binder<'tcx, T>) {
&mut self,
binder: &ty::Binder<'tcx, T>,
) -> std::ops::ControlFlow<Self::BreakTy> {
self.depth.shift_in(1); self.depth.shift_in(1);
let binder = binder.super_visit_with(self); binder.super_visit_with(self);
self.depth.shift_out(1); self.depth.shift_out(1);
binder
} }
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, ty: Ty<'tcx>) {
if let ty::Alias(ty::Projection, unshifted_alias_ty) = *ty.kind() if let ty::Alias(ty::Projection, unshifted_alias_ty) = *ty.kind()
&& let Some( && let Some(
ty::ImplTraitInTraitData::Trait { fn_def_id, .. } ty::ImplTraitInTraitData::Trait { fn_def_id, .. }

View File

@ -1,6 +1,7 @@
use rustc_ast_ir::try_visit;
use rustc_ast_ir::visit::VisitorResult;
use std::fmt; use std::fmt;
use std::hash::Hash; use std::hash::Hash;
use std::ops::ControlFlow;
use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::fold::{FallibleTypeFolder, TypeFoldable};
use crate::visit::{TypeVisitable, TypeVisitor}; use crate::visit::{TypeVisitable, TypeVisitor};
@ -107,9 +108,9 @@ impl<I: Interner, V: TypeVisitable<I>> TypeVisitable<I> for Canonical<I, V>
where where
I::CanonicalVars: TypeVisitable<I>, I::CanonicalVars: TypeVisitable<I>,
{ {
fn visit_with<F: TypeVisitor<I>>(&self, folder: &mut F) -> ControlFlow<F::BreakTy> { fn visit_with<F: TypeVisitor<I>>(&self, folder: &mut F) -> F::Result {
self.value.visit_with(folder)?; try_visit!(self.value.visit_with(folder));
self.max_universe.visit_with(folder)?; try_visit!(self.max_universe.visit_with(folder));
self.variables.visit_with(folder) self.variables.visit_with(folder)
} }
} }
@ -137,7 +138,7 @@ impl<I: Interner> TypeVisitable<I> for CanonicalVarInfo<I>
where where
I::Ty: TypeVisitable<I>, I::Ty: TypeVisitable<I>,
{ {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
self.kind.visit_with(visitor) self.kind.visit_with(visitor)
} }
} }
@ -251,13 +252,13 @@ impl<I: Interner> TypeVisitable<I> for CanonicalVarKind<I>
where where
I::Ty: TypeVisitable<I>, I::Ty: TypeVisitable<I>,
{ {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
match self { match self {
CanonicalVarKind::Ty(_) CanonicalVarKind::Ty(_)
| CanonicalVarKind::PlaceholderTy(_) | CanonicalVarKind::PlaceholderTy(_)
| CanonicalVarKind::Region(_) | CanonicalVarKind::Region(_)
| CanonicalVarKind::PlaceholderRegion(_) | CanonicalVarKind::PlaceholderRegion(_)
| CanonicalVarKind::Effect => ControlFlow::Continue(()), | CanonicalVarKind::Effect => V::Result::output(),
CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => { CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => {
ty.visit_with(visitor) ty.visit_with(visitor)
} }

View File

@ -21,13 +21,15 @@ use std::hash::Hash;
#[cfg(not(feature = "nightly"))] #[cfg(not(feature = "nightly"))]
use std::sync::Arc as Lrc; use std::sync::Arc as Lrc;
#[macro_use]
pub mod visit;
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
pub mod codec; pub mod codec;
pub mod fold; pub mod fold;
pub mod new; pub mod new;
pub mod ty_info; pub mod ty_info;
pub mod ty_kind; pub mod ty_kind;
pub mod visit;
#[macro_use] #[macro_use]
mod macros; mod macros;

View File

@ -25,9 +25,9 @@ macro_rules! TrivialTypeTraversalImpls {
fn visit_with<F: $crate::visit::TypeVisitor<I>>( fn visit_with<F: $crate::visit::TypeVisitor<I>>(
&self, &self,
_: &mut F) _: &mut F)
-> ::std::ops::ControlFlow<F::BreakTy> -> F::Result
{ {
::std::ops::ControlFlow::Continue(()) <F::Result as rustc_ast_ir::visit::VisitorResult>::output()
} }
} }
)+ )+

View File

@ -1,5 +1,6 @@
use rustc_ast_ir::try_visit;
use rustc_ast_ir::visit::VisitorResult;
use std::fmt; use std::fmt;
use std::ops::ControlFlow;
use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::fold::{FallibleTypeFolder, TypeFoldable};
use crate::visit::{TypeVisitable, TypeVisitor}; use crate::visit::{TypeVisitable, TypeVisitor};
@ -91,14 +92,14 @@ where
I::TypeOutlivesPredicate: TypeVisitable<I>, I::TypeOutlivesPredicate: TypeVisitable<I>,
I::RegionOutlivesPredicate: TypeVisitable<I>, I::RegionOutlivesPredicate: TypeVisitable<I>,
{ {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
match self { match self {
ClauseKind::Trait(p) => p.visit_with(visitor), ClauseKind::Trait(p) => p.visit_with(visitor),
ClauseKind::RegionOutlives(p) => p.visit_with(visitor), ClauseKind::RegionOutlives(p) => p.visit_with(visitor),
ClauseKind::TypeOutlives(p) => p.visit_with(visitor), ClauseKind::TypeOutlives(p) => p.visit_with(visitor),
ClauseKind::Projection(p) => p.visit_with(visitor), ClauseKind::Projection(p) => p.visit_with(visitor),
ClauseKind::ConstArgHasType(c, t) => { ClauseKind::ConstArgHasType(c, t) => {
c.visit_with(visitor)?; try_visit!(c.visit_with(visitor));
t.visit_with(visitor) t.visit_with(visitor)
} }
ClauseKind::WellFormed(p) => p.visit_with(visitor), ClauseKind::WellFormed(p) => p.visit_with(visitor),
@ -205,21 +206,21 @@ where
I::NormalizesTo: TypeVisitable<I>, I::NormalizesTo: TypeVisitable<I>,
ClauseKind<I>: TypeVisitable<I>, ClauseKind<I>: TypeVisitable<I>,
{ {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
match self { match self {
PredicateKind::Clause(p) => p.visit_with(visitor), PredicateKind::Clause(p) => p.visit_with(visitor),
PredicateKind::ObjectSafe(d) => d.visit_with(visitor), PredicateKind::ObjectSafe(d) => d.visit_with(visitor),
PredicateKind::Subtype(s) => s.visit_with(visitor), PredicateKind::Subtype(s) => s.visit_with(visitor),
PredicateKind::Coerce(s) => s.visit_with(visitor), PredicateKind::Coerce(s) => s.visit_with(visitor),
PredicateKind::ConstEquate(a, b) => { PredicateKind::ConstEquate(a, b) => {
a.visit_with(visitor)?; try_visit!(a.visit_with(visitor));
b.visit_with(visitor) b.visit_with(visitor)
} }
PredicateKind::Ambiguous => ControlFlow::Continue(()), PredicateKind::Ambiguous => V::Result::output(),
PredicateKind::NormalizesTo(p) => p.visit_with(visitor), PredicateKind::NormalizesTo(p) => p.visit_with(visitor),
PredicateKind::AliasRelate(a, b, d) => { PredicateKind::AliasRelate(a, b, d) => {
a.visit_with(visitor)?; try_visit!(a.visit_with(visitor));
b.visit_with(visitor)?; try_visit!(b.visit_with(visitor));
d.visit_with(visitor) d.visit_with(visitor)
} }
} }

View File

@ -1,3 +1,4 @@
use rustc_ast_ir::try_visit;
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
@ -831,8 +832,8 @@ impl<I: Interner> TypeVisitable<I> for TypeAndMut<I>
where where
I::Ty: TypeVisitable<I>, I::Ty: TypeVisitable<I>,
{ {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> std::ops::ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
self.ty.visit_with(visitor)?; try_visit!(self.ty.visit_with(visitor));
self.mutbl.visit_with(visitor) self.mutbl.visit_with(visitor)
} }
} }

View File

@ -41,6 +41,8 @@
//! - u.visit_with(visitor) //! - 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 rustc_index::{Idx, IndexVec};
use std::fmt; use std::fmt;
use std::ops::ControlFlow; use std::ops::ControlFlow;
@ -63,7 +65,7 @@ pub trait TypeVisitable<I: Interner>: fmt::Debug + Clone {
/// that calls a visitor method specifically for that type (such as /// that calls a visitor method specifically for that type (such as
/// `V::visit_ty`). This is where control transfers from `TypeVisitable` to /// `V::visit_ty`). This is where control transfers from `TypeVisitable` to
/// `TypeVisitor`. /// `TypeVisitor`.
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>; fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result;
} }
// This trait is implemented for types of interest. // This trait is implemented for types of interest.
@ -74,7 +76,7 @@ pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
/// that method. For example, in `MyVisitor::visit_ty(ty)`, it is valid to /// 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 /// call `ty.super_visit_with(self)`, but any other visiting should be done
/// with `xyz.visit_with(self)`. /// with `xyz.visit_with(self)`.
fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>; fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result;
} }
/// This trait is implemented for every visiting traversal. There is a visit /// This trait is implemented for every visiting traversal. There is a visit
@ -82,33 +84,30 @@ pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
/// that recurses into the type's fields in a non-custom fashion. /// that recurses into the type's fields in a non-custom fashion.
pub trait TypeVisitor<I: Interner>: Sized { pub trait TypeVisitor<I: Interner>: Sized {
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
type BreakTy = !; type Result: VisitorResult = ();
#[cfg(not(feature = "nightly"))] #[cfg(not(feature = "nightly"))]
type BreakTy; type Result: VisitorResult;
fn visit_binder<T: TypeVisitable<I>>( fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> Self::Result {
&mut self,
t: &I::Binder<T>,
) -> ControlFlow<Self::BreakTy> {
t.super_visit_with(self) t.super_visit_with(self)
} }
fn visit_ty(&mut self, t: I::Ty) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
t.super_visit_with(self) t.super_visit_with(self)
} }
// The default region visitor is a no-op because `Region` is non-recursive // The default region visitor is a no-op because `Region` is non-recursive
// and has no `super_visit_with` method to call. // and has no `super_visit_with` method to call.
fn visit_region(&mut self, _r: I::Region) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, _r: I::Region) -> Self::Result {
ControlFlow::Continue(()) Self::Result::output()
} }
fn visit_const(&mut self, c: I::Const) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: I::Const) -> Self::Result {
c.super_visit_with(self) c.super_visit_with(self)
} }
fn visit_predicate(&mut self, p: I::Predicate) -> ControlFlow<Self::BreakTy> { fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result {
p.super_visit_with(self) p.super_visit_with(self)
} }
} }
@ -117,8 +116,8 @@ pub trait TypeVisitor<I: Interner>: Sized {
// Traversal implementations. // Traversal implementations.
impl<I: Interner, T: TypeVisitable<I>, U: TypeVisitable<I>> TypeVisitable<I> for (T, U) { impl<I: Interner, T: TypeVisitable<I>, U: TypeVisitable<I>> TypeVisitable<I> for (T, U) {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
self.0.visit_with(visitor)?; try_visit!(self.0.visit_with(visitor));
self.1.visit_with(visitor) self.1.visit_with(visitor)
} }
} }
@ -126,24 +125,24 @@ impl<I: Interner, T: TypeVisitable<I>, U: TypeVisitable<I>> TypeVisitable<I> for
impl<I: Interner, A: TypeVisitable<I>, B: TypeVisitable<I>, C: TypeVisitable<I>> TypeVisitable<I> impl<I: Interner, A: TypeVisitable<I>, B: TypeVisitable<I>, C: TypeVisitable<I>> TypeVisitable<I>
for (A, B, C) for (A, B, C)
{ {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
self.0.visit_with(visitor)?; try_visit!(self.0.visit_with(visitor));
self.1.visit_with(visitor)?; try_visit!(self.1.visit_with(visitor));
self.2.visit_with(visitor) self.2.visit_with(visitor)
} }
} }
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Option<T> { impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Option<T> {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
match self { match self {
Some(v) => v.visit_with(visitor), Some(v) => v.visit_with(visitor),
None => ControlFlow::Continue(()), None => V::Result::output(),
} }
} }
} }
impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for Result<T, E> { impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for Result<T, E> {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
match self { match self {
Ok(v) => v.visit_with(visitor), Ok(v) => v.visit_with(visitor),
Err(e) => e.visit_with(visitor), Err(e) => e.visit_with(visitor),
@ -152,20 +151,21 @@ impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for
} }
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Lrc<T> { impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Lrc<T> {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
(**self).visit_with(visitor) (**self).visit_with(visitor)
} }
} }
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<T> { impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<T> {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
(**self).visit_with(visitor) (**self).visit_with(visitor)
} }
} }
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> { impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
self.iter().try_for_each(|t| t.visit_with(visitor)) walk_visitable_list!(visitor, self.iter());
V::Result::output()
} }
} }
@ -173,20 +173,23 @@ impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> {
// case, because we can't return a new slice. But note that there are a couple // 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. // of trivial impls of `TypeFoldable` for specific slice types elsewhere.
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for &[T] { impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for &[T] {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
self.iter().try_for_each(|t| t.visit_with(visitor)) walk_visitable_list!(visitor, self.iter());
V::Result::output()
} }
} }
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<[T]> { impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<[T]> {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
self.iter().try_for_each(|t| t.visit_with(visitor)) walk_visitable_list!(visitor, self.iter());
V::Result::output()
} }
} }
impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix, T> { impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix, T> {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
self.iter().try_for_each(|t| t.visit_with(visitor)) 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 // is important for anonymization of binders in `TyCtxt::erase_regions`. We
// specifically detect this case in `visit_binder`. // specifically detect this case in `visit_binder`.
impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor { impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
type BreakTy = FoundFlags; type Result = ControlFlow<FoundFlags>;
fn visit_binder<T: TypeVisitable<I>>( fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> Self::Result {
&mut self,
t: &I::Binder<T>,
) -> ControlFlow<Self::BreakTy> {
// If we're looking for the HAS_BINDER_VARS flag, check if the // 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 // binder has vars. This won't be present in the binder's bound
// value, so we need to check here too. // value, so we need to check here too.
@ -383,7 +383,7 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
} }
#[inline] #[inline]
fn visit_ty(&mut self, t: I::Ty) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
// Note: no `super_visit_with` call. // Note: no `super_visit_with` call.
let flags = t.flags(); let flags = t.flags();
if flags.intersects(self.flags) { if flags.intersects(self.flags) {
@ -394,7 +394,7 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
} }
#[inline] #[inline]
fn visit_region(&mut self, r: I::Region) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: I::Region) -> Self::Result {
// Note: no `super_visit_with` call, as usual for `Region`. // Note: no `super_visit_with` call, as usual for `Region`.
let flags = r.flags(); let flags = r.flags();
if flags.intersects(self.flags) { if flags.intersects(self.flags) {
@ -405,7 +405,7 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
} }
#[inline] #[inline]
fn visit_const(&mut self, c: I::Const) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: I::Const) -> Self::Result {
// Note: no `super_visit_with` call. // Note: no `super_visit_with` call.
if c.flags().intersects(self.flags) { if c.flags().intersects(self.flags) {
ControlFlow::Break(FoundFlags) ControlFlow::Break(FoundFlags)
@ -415,7 +415,7 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
} }
#[inline] #[inline]
fn visit_predicate(&mut self, predicate: I::Predicate) -> ControlFlow<Self::BreakTy> { fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result {
// Note: no `super_visit_with` call. // Note: no `super_visit_with` call.
if predicate.flags().intersects(self.flags) { if predicate.flags().intersects(self.flags) {
ControlFlow::Break(FoundFlags) ControlFlow::Break(FoundFlags)
@ -459,12 +459,9 @@ struct HasEscapingVarsVisitor {
} }
impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor { impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
type BreakTy = FoundEscapingVars; type Result = ControlFlow<FoundEscapingVars>;
fn visit_binder<T: TypeVisitable<I>>( fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> Self::Result {
&mut self,
t: &I::Binder<T>,
) -> ControlFlow<Self::BreakTy> {
self.outer_index.shift_in(1); self.outer_index.shift_in(1);
let result = t.super_visit_with(self); let result = t.super_visit_with(self);
self.outer_index.shift_out(1); self.outer_index.shift_out(1);
@ -472,7 +469,7 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
} }
#[inline] #[inline]
fn visit_ty(&mut self, t: I::Ty) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
// If the outer-exclusive-binder is *strictly greater* than // If the outer-exclusive-binder is *strictly greater* than
// `outer_index`, that means that `t` contains some content // `outer_index`, that means that `t` contains some content
// bound at `outer_index` or above (because // bound at `outer_index` or above (because
@ -486,7 +483,7 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
} }
#[inline] #[inline]
fn visit_region(&mut self, r: I::Region) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: I::Region) -> Self::Result {
// If the region is bound by `outer_index` or anything outside // If the region is bound by `outer_index` or anything outside
// of outer index, then it escapes the binders we have // of outer index, then it escapes the binders we have
// visited. // visited.
@ -497,7 +494,7 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
} }
} }
fn visit_const(&mut self, ct: I::Const) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, ct: I::Const) -> Self::Result {
// If the outer-exclusive-binder is *strictly greater* than // If the outer-exclusive-binder is *strictly greater* than
// `outer_index`, that means that `ct` contains some content // `outer_index`, that means that `ct` contains some content
// bound at `outer_index` or above (because // bound at `outer_index` or above (because
@ -511,7 +508,7 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
} }
#[inline] #[inline]
fn visit_predicate(&mut self, predicate: I::Predicate) -> ControlFlow<Self::BreakTy> { fn visit_predicate(&mut self, predicate: I::Predicate) -> Self::Result {
if predicate.outer_exclusive_binder() > self.outer_index { if predicate.outer_exclusive_binder() > self.outer_index {
ControlFlow::Break(FoundEscapingVars) ControlFlow::Break(FoundEscapingVars)
} else { } else {
@ -523,9 +520,9 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
struct HasErrorVisitor; struct HasErrorVisitor;
impl<I: Interner> TypeVisitor<I> for HasErrorVisitor { impl<I: Interner> TypeVisitor<I> for HasErrorVisitor {
type BreakTy = I::ErrorGuaranteed; type Result = ControlFlow<I::ErrorGuaranteed>;
fn visit_ty(&mut self, t: <I as Interner>::Ty) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: <I as Interner>::Ty) -> Self::Result {
if let ty::Error(guar) = t.kind() { if let ty::Error(guar) = t.kind() {
ControlFlow::Break(guar) ControlFlow::Break(guar)
} else { } else {
@ -533,7 +530,7 @@ impl<I: Interner> TypeVisitor<I> for HasErrorVisitor {
} }
} }
fn visit_const(&mut self, c: <I as Interner>::Const) -> ControlFlow<Self::BreakTy> { fn visit_const(&mut self, c: <I as Interner>::Const) -> Self::Result {
if let ty::ConstKind::Error(guar) = c.kind() { if let ty::ConstKind::Error(guar) = c.kind() {
ControlFlow::Break(guar) ControlFlow::Break(guar)
} else { } else {
@ -541,7 +538,7 @@ impl<I: Interner> TypeVisitor<I> for HasErrorVisitor {
} }
} }
fn visit_region(&mut self, r: <I as Interner>::Region) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: <I as Interner>::Region) -> Self::Result {
if let ty::ReError(guar) = r.kind() { if let ty::ReError(guar) = r.kind() {
ControlFlow::Break(guar) ControlFlow::Break(guar)
} else { } else {

View File

@ -22,9 +22,9 @@ fn get_enum_ty(enum_ty: Ty<'_>) -> Option<Ty<'_>> {
} }
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTyVisitor { impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTyVisitor {
type BreakTy = Ty<'tcx>; type Result = ControlFlow<Ty<'tcx>>;
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
self.level += 1; self.level += 1;
if self.level == 1 { if self.level == 1 {
t.super_visit_with(self) t.super_visit_with(self)

View File

@ -141,9 +141,9 @@ impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b,
struct ContainsRegion; struct ContainsRegion;
impl TypeVisitor<TyCtxt<'_>> for ContainsRegion { impl TypeVisitor<TyCtxt<'_>> for ContainsRegion {
type BreakTy = (); type Result = ControlFlow<()>;
fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, _: ty::Region<'_>) -> Self::Result {
ControlFlow::Break(()) ControlFlow::Break(())
} }
} }

View File

@ -916,8 +916,8 @@ pub fn for_each_top_level_late_bound_region<B>(
f: F, f: F,
} }
impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow<B>> TypeVisitor<TyCtxt<'tcx>> for V<F> { impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow<B>> TypeVisitor<TyCtxt<'tcx>> for V<F> {
type BreakTy = B; type Result = ControlFlow<B>;
fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> { fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result {
if let RegionKind::ReBound(idx, bound) = r.kind() if let RegionKind::ReBound(idx, bound) = r.kind()
&& idx.as_u32() == self.index && idx.as_u32() == self.index
{ {
@ -926,7 +926,7 @@ pub fn for_each_top_level_late_bound_region<B>(
ControlFlow::Continue(()) ControlFlow::Continue(())
} }
} }
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) -> ControlFlow<Self::BreakTy> { fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &Binder<'tcx, T>) -> Self::Result {
self.index += 1; self.index += 1;
let res = t.super_visit_with(self); let res = t.super_visit_with(self);
self.index -= 1; self.index -= 1;