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

View File

@ -30,9 +30,9 @@ where
}
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() {
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() {
ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
_ => 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 std::mem;
use std::ops::{ControlFlow, Deref};
use std::ops::Deref;
use super::ops::{self, NonConstOp, Status};
use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
@ -164,9 +164,9 @@ struct LocalReturnTyVisitor<'ck, 'mir, 'tcx> {
}
impl<'ck, 'mir, 'tcx> TypeVisitor<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() {
ty::FnPtr(_) => ControlFlow::Continue(()),
ty::FnPtr(_) => {}
ty::Ref(_, _, hir::Mutability::Mut) => {
self.checker.check_op(ops::ty::MutRef(self.kind));
t.super_visit_with(self)

View File

@ -1474,15 +1474,14 @@ fn opaque_type_cycle_error(
closures: Vec<DefId>,
}
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() {
ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
self.opaques.push(def);
ControlFlow::Continue(())
}
ty::Closure(def_id, ..) | ty::Coroutine(def_id, ..) => {
self.closures.push(def_id);
t.super_visit_with(self)
t.super_visit_with(self);
}
_ => t.super_visit_with(self),
}

View File

@ -12,7 +12,6 @@ use rustc_trait_selection::regions::InferCtxtRegionExt;
use rustc_trait_selection::traits::{
elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt,
};
use std::ops::ControlFlow;
/// Check that an implementation does not refine an RPITIT from a trait method signature.
pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
@ -211,9 +210,7 @@ struct ImplTraitInTraitCollector<'tcx> {
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'tcx> {
type BreakTy = !;
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, proj) = *ty.kind()
&& 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)
.iter_instantiated_copied(self.tcx, proj.args)
{
pred.visit_with(self)?;
pred.visit_with(self);
}
}
ControlFlow::Continue(())
} else {
ty.super_visit_with(self)
ty.super_visit_with(self);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -396,9 +396,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty: Ty<'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 {
ControlFlow::Break(())
} else {

View File

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

View File

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

View File

@ -79,7 +79,7 @@ use rustc_middle::ty::{
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
use std::borrow::Cow;
use std::ops::{ControlFlow, Deref};
use std::ops::Deref;
use std::path::PathBuf;
use std::{cmp, fmt, iter};
@ -1623,7 +1623,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
impl<'tcx> ty::visit::TypeVisitor<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) {
let span = self.tcx.def_span(def_id);
// 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::def_id::LocalDefId;
use std::ops::ControlFlow;
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Print the error message for lifetime errors when the return type is a static `impl Trait`,
@ -545,13 +544,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
pub struct TraitObjectVisitor(pub FxIndexSet<DefId>);
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() {
ty::Dynamic(preds, re, _) if re.is_static() => {
if let Some(def_id) = preds.principal_def_id() {
self.0.insert(def_id);
}
ControlFlow::Continue(())
}
_ => t.super_visit_with(self),
}

View File

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

View File

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

View File

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

View File

@ -1,11 +1,11 @@
use crate::traits;
use crate::traits::project::Normalized;
use rustc_ast_ir::try_visit;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable};
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor};
use rustc_middle::ty::{self, TyCtxt};
use std::fmt;
use std::ops::ControlFlow;
// Structural impls for the structs in `traits`.
@ -84,8 +84,8 @@ impl<'tcx, O: TypeFoldable<TyCtxt<'tcx>>> TypeFoldable<TyCtxt<'tcx>>
impl<'tcx, O: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>>
for traits::Obligation<'tcx, O>
{
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.predicate.visit_with(visitor)?;
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
try_visit!(self.predicate.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 {
struct 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() {
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> {
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()
&& !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);
let body_visit = s.each(|bind| {
quote! {
::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)?;
match ::rustc_ast_ir::visit::VisitorResult::branch(
::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)
) {
::core::ops::ControlFlow::Continue(()) => {},
::core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
},
}
}
});
s.bind_with(|_| synstructure::BindStyle::Move);
@ -45,9 +52,9 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(
&self,
__visitor: &mut __V
) -> ::std::ops::ControlFlow<__V::BreakTy> {
) -> __V::Result {
match *self { #body_visit }
::std::ops::ControlFlow::Continue(())
<__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
}
},
)

View File

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

View File

@ -482,9 +482,9 @@ pub struct 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() {
Infer(InferTy::TyVar(_)) if self.infer_suggestable => {}
@ -536,7 +536,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> {
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() {
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::{self, Lift, List, ParamConst, Ty, TyCtxt};
use rustc_ast_ir::visit::VisitorResult;
use rustc_ast_ir::walk_visitable_list;
use rustc_data_structures::intern::Interned;
use rustc_errors::{DiagArgValue, IntoDiagnosticArg};
use rustc_hir::def_id::DefId;
@ -19,7 +21,7 @@ use std::cmp::Ordering;
use std::marker::PhantomData;
use std::mem;
use std::num::NonZero;
use std::ops::{ControlFlow, Deref};
use std::ops::Deref;
use std::ptr::NonNull;
/// An entity in the Rust type system, which can be one of
@ -240,7 +242,7 @@ impl<'tcx> TypeFoldable<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() {
GenericArgKind::Lifetime(lt) => lt.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> {
#[inline]
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
walk_visitable_list!(visitor, self.iter());
V::Result::output()
}
}

View File

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

View File

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

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

View File

@ -2113,9 +2113,9 @@ impl<'tcx> Ty<'tcx> {
struct ContainsTyVisitor<'tcx>(Ty<'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) }
}
}
@ -2131,9 +2131,9 @@ impl<'tcx> Ty<'tcx> {
struct 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() {
ControlFlow::Break(())
} else {

View File

@ -64,19 +64,19 @@ impl<'tcx> TyCtxt<'tcx> {
where
F: FnMut(ty::Region<'tcx>) -> bool,
{
type BreakTy = ();
type Result = ControlFlow<()>;
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
) -> Self::Result {
self.outer_index.shift_in(1);
let result = t.super_visit_with(self);
self.outer_index.shift_out(1);
result
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
match *r {
ty::ReBound(debruijn, _) if debruijn < self.outer_index => {
ControlFlow::Continue(())
@ -91,7 +91,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
// We're only interested in types involving regions
if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
ty.super_visit_with(self)
@ -140,8 +140,7 @@ impl<'tcx> TyCtxt<'tcx> {
let mut collector = LateBoundRegionsCollector::new(just_constrained);
let value = value.skip_binder();
let value = if just_constrained { self.expand_weak_alias_tys(value) } else { value };
let result = value.visit_with(&mut collector);
assert!(result.is_continue()); // should never have stopped early
value.visit_with(&mut collector);
collector.regions
}
}
@ -165,19 +164,19 @@ impl<'tcx> ValidateBoundVars<'tcx> {
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
type BreakTy = ();
type Result = ControlFlow<()>;
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
) -> Self::Result {
self.binder_index.shift_in(1);
let result = t.super_visit_with(self);
self.binder_index.shift_out(1);
result
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
if t.outer_exclusive_binder() < self.binder_index
|| !self.visited.insert((self.binder_index, t))
{
@ -211,7 +210,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
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 {
ty::ReBound(index, br) if index == self.binder_index => {
if self.bound_vars.len() <= br.var.as_usize() {
@ -266,23 +265,19 @@ impl LateBoundRegionsCollector {
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
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.current_index.shift_in(1);
let result = t.super_visit_with(self);
t.super_visit_with(self);
self.current_index.shift_out(1);
result
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_ty(&mut self, t: Ty<'tcx>) {
if self.just_constrained {
match t.kind() {
// If we are only looking for "constrained" regions, we have to ignore the
// inputs to a projection as they may not appear in the normalized form.
ty::Alias(ty::Projection | ty::Inherent | ty::Opaque, _) => {
return ControlFlow::Continue(());
return;
}
// All weak alias types should've been expanded beforehand.
ty::Alias(ty::Weak, _) => bug!("unexpected weak alias type"),
@ -293,26 +288,25 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
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
// ignore the inputs of an unevaluated const, as they may not appear
// in the normalized form
if self.just_constrained {
if let ty::ConstKind::Unevaluated(..) = c.kind() {
return ControlFlow::Continue(());
return;
}
}
c.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_region(&mut self, r: ty::Region<'tcx>) {
if let ty::ReBound(debruijn, br) = *r {
if debruijn == self.current_index {
self.regions.insert(br.kind);
}
}
ControlFlow::Continue(())
}
}
@ -332,7 +326,7 @@ impl MaxUniverse {
}
impl<'tcx> TypeVisitor<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() {
self.max_universe = ty::UniverseIndex::from_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)
}
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() {
self.max_universe = ty::UniverseIndex::from_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)
}
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 {
self.max_universe = ty::UniverseIndex::from_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,
};
use rustc_span::symbol::sym;
use std::ops::ControlFlow;
use crate::errors::UnusedGenericParamsHint;
@ -291,31 +290,29 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
#[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() {
return ControlFlow::Continue(());
return;
}
match c.kind() {
ty::ConstKind::Param(param) => {
debug!(?param);
self.unused_parameters.mark_used(param.index);
ControlFlow::Continue(())
}
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args })
if matches!(self.tcx.def_kind(def), DefKind::AnonConst) =>
{
self.visit_child_body(def, args);
ControlFlow::Continue(())
}
_ => c.super_visit_with(self),
}
}
#[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_ty(&mut self, ty: Ty<'tcx>) {
if !ty.has_non_region_param() {
return ControlFlow::Continue(());
return;
}
match *ty.kind() {
@ -323,18 +320,16 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
debug!(?def_id);
// Avoid cycle errors with coroutines.
if def_id == self.def_id {
return ControlFlow::Continue(());
return;
}
// Consider any generic parameters used by any closures/coroutines as used in the
// parent.
self.visit_child_body(def_id, args);
ControlFlow::Continue(())
}
ty::Param(param) => {
debug!(?param);
self.unused_parameters.mark_used(param.index);
ControlFlow::Continue(())
}
_ => ty.super_visit_with(self),
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -152,9 +152,9 @@ impl ArgKind {
struct 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(_))) {
ControlFlow::Break(())
} else {

View File

@ -435,8 +435,8 @@ fn is_impossible_associated_item(
trait_item_def_id: DefId,
}
impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for ReferencesOnlyParentGenerics<'tcx> {
type BreakTy = ();
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
type Result = ControlFlow<()>;
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
// If this is a parameter from the trait item's own generics, then bail
if let ty::Param(param) = t.kind()
&& let param_def_id = self.generics.type_param(param, self.tcx).def_id
@ -446,7 +446,7 @@ fn is_impossible_associated_item(
}
t.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
if let ty::ReEarlyParam(param) = r.kind()
&& let param_def_id = self.generics.region_param(&param, self.tcx).def_id
&& self.tcx.parent(param_def_id) == self.trait_item_def_id
@ -455,7 +455,7 @@ fn is_impossible_associated_item(
}
ControlFlow::Continue(())
}
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
if let ty::ConstKind::Param(param) = ct.kind()
&& let param_def_id = self.generics.const_param(&param, self.tcx).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> {
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() {
ty::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`.
// This is only possible for unevaluated constants, so we walk these here.
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_span::DUMMY_SP;
use std::ops::ControlFlow;
use super::NoSolution;
pub use rustc_middle::traits::query::NormalizationResult;
@ -123,28 +121,23 @@ struct MaxEscapingBoundVarVisitor {
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &ty::Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
self.outer_index.shift_in(1);
let result = t.super_visit_with(self);
t.super_visit_with(self);
self.outer_index.shift_out(1);
result
}
#[inline]
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_ty(&mut self, t: Ty<'tcx>) {
if t.outer_exclusive_binder() > self.outer_index {
self.escaping = self
.escaping
.max(t.outer_exclusive_binder().as_usize() - self.outer_index.as_usize());
}
ControlFlow::Continue(())
}
#[inline]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit_region(&mut self, r: ty::Region<'tcx>) {
match *r {
ty::ReBound(debruijn, _) if debruijn > self.outer_index => {
self.escaping =
@ -152,16 +145,14 @@ impl<'tcx> TypeVisitor<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 {
self.escaping = self
.escaping
.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> {
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);
let (adt_def, args) = match *ty.kind() {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -25,9 +25,9 @@ macro_rules! TrivialTypeTraversalImpls {
fn visit_with<F: $crate::visit::TypeVisitor<I>>(
&self,
_: &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::ops::ControlFlow;
use crate::fold::{FallibleTypeFolder, TypeFoldable};
use crate::visit::{TypeVisitable, TypeVisitor};
@ -91,14 +92,14 @@ where
I::TypeOutlivesPredicate: 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 {
ClauseKind::Trait(p) => p.visit_with(visitor),
ClauseKind::RegionOutlives(p) => p.visit_with(visitor),
ClauseKind::TypeOutlives(p) => p.visit_with(visitor),
ClauseKind::Projection(p) => p.visit_with(visitor),
ClauseKind::ConstArgHasType(c, t) => {
c.visit_with(visitor)?;
try_visit!(c.visit_with(visitor));
t.visit_with(visitor)
}
ClauseKind::WellFormed(p) => p.visit_with(visitor),
@ -205,21 +206,21 @@ where
I::NormalizesTo: TypeVisitable<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 {
PredicateKind::Clause(p) => p.visit_with(visitor),
PredicateKind::ObjectSafe(d) => d.visit_with(visitor),
PredicateKind::Subtype(s) => s.visit_with(visitor),
PredicateKind::Coerce(s) => s.visit_with(visitor),
PredicateKind::ConstEquate(a, b) => {
a.visit_with(visitor)?;
try_visit!(a.visit_with(visitor));
b.visit_with(visitor)
}
PredicateKind::Ambiguous => ControlFlow::Continue(()),
PredicateKind::Ambiguous => V::Result::output(),
PredicateKind::NormalizesTo(p) => p.visit_with(visitor),
PredicateKind::AliasRelate(a, b, d) => {
a.visit_with(visitor)?;
b.visit_with(visitor)?;
try_visit!(a.visit_with(visitor));
try_visit!(b.visit_with(visitor));
d.visit_with(visitor)
}
}

View File

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

View File

@ -41,6 +41,8 @@
//! - u.visit_with(visitor)
//! ```
use rustc_ast_ir::visit::VisitorResult;
use rustc_ast_ir::{try_visit, walk_visitable_list};
use rustc_index::{Idx, IndexVec};
use std::fmt;
use std::ops::ControlFlow;
@ -63,7 +65,7 @@ pub trait TypeVisitable<I: Interner>: fmt::Debug + Clone {
/// that calls a visitor method specifically for that type (such as
/// `V::visit_ty`). This is where control transfers from `TypeVisitable` to
/// `TypeVisitor`.
fn visit_with<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.
@ -74,7 +76,7 @@ pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
/// that method. For example, in `MyVisitor::visit_ty(ty)`, it is valid to
/// call `ty.super_visit_with(self)`, but any other visiting should be done
/// with `xyz.visit_with(self)`.
fn super_visit_with<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
@ -82,33 +84,30 @@ pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
/// that recurses into the type's fields in a non-custom fashion.
pub trait TypeVisitor<I: Interner>: Sized {
#[cfg(feature = "nightly")]
type BreakTy = !;
type Result: VisitorResult = ();
#[cfg(not(feature = "nightly"))]
type BreakTy;
type Result: VisitorResult;
fn visit_binder<T: TypeVisitable<I>>(
&mut self,
t: &I::Binder<T>,
) -> ControlFlow<Self::BreakTy> {
fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> Self::Result {
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)
}
// The default region visitor is a no-op because `Region` is non-recursive
// and has no `super_visit_with` method to call.
fn visit_region(&mut self, _r: I::Region) -> ControlFlow<Self::BreakTy> {
ControlFlow::Continue(())
fn visit_region(&mut self, _r: I::Region) -> Self::Result {
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)
}
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)
}
}
@ -117,8 +116,8 @@ pub trait TypeVisitor<I: Interner>: Sized {
// Traversal implementations.
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> {
self.0.visit_with(visitor)?;
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
try_visit!(self.0.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>
for (A, B, C)
{
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.0.visit_with(visitor)?;
self.1.visit_with(visitor)?;
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
try_visit!(self.0.visit_with(visitor));
try_visit!(self.1.visit_with(visitor));
self.2.visit_with(visitor)
}
}
impl<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 {
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> {
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 {
Ok(v) => v.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> {
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)
}
}
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)
}
}
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
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
// of trivial impls of `TypeFoldable` for specific slice types elsewhere.
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for &[T] {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
walk_visitable_list!(visitor, self.iter());
V::Result::output()
}
}
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<[T]> {
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
walk_visitable_list!(visitor, self.iter());
V::Result::output()
}
}
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> {
self.iter().try_for_each(|t| t.visit_with(visitor))
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
walk_visitable_list!(visitor, self.iter());
V::Result::output()
}
}
@ -366,12 +369,9 @@ impl std::fmt::Debug for HasTypeFlagsVisitor {
// is important for anonymization of binders in `TyCtxt::erase_regions`. We
// specifically detect this case in `visit_binder`.
impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
type BreakTy = FoundFlags;
type Result = ControlFlow<FoundFlags>;
fn visit_binder<T: TypeVisitable<I>>(
&mut self,
t: &I::Binder<T>,
) -> ControlFlow<Self::BreakTy> {
fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> Self::Result {
// If we're looking for the HAS_BINDER_VARS flag, check if the
// binder has vars. This won't be present in the binder's bound
// value, so we need to check here too.
@ -383,7 +383,7 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
}
#[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.
let flags = t.flags();
if flags.intersects(self.flags) {
@ -394,7 +394,7 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
}
#[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`.
let flags = r.flags();
if flags.intersects(self.flags) {
@ -405,7 +405,7 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
}
#[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.
if c.flags().intersects(self.flags) {
ControlFlow::Break(FoundFlags)
@ -415,7 +415,7 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
}
#[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.
if predicate.flags().intersects(self.flags) {
ControlFlow::Break(FoundFlags)
@ -459,12 +459,9 @@ struct HasEscapingVarsVisitor {
}
impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
type BreakTy = FoundEscapingVars;
type Result = ControlFlow<FoundEscapingVars>;
fn visit_binder<T: TypeVisitable<I>>(
&mut self,
t: &I::Binder<T>,
) -> ControlFlow<Self::BreakTy> {
fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> Self::Result {
self.outer_index.shift_in(1);
let result = t.super_visit_with(self);
self.outer_index.shift_out(1);
@ -472,7 +469,7 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
}
#[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
// `outer_index`, that means that `t` contains some content
// bound at `outer_index` or above (because
@ -486,7 +483,7 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
}
#[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
// of outer index, then it escapes the binders we have
// 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
// `outer_index`, that means that `ct` contains some content
// bound at `outer_index` or above (because
@ -511,7 +508,7 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
}
#[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 {
ControlFlow::Break(FoundEscapingVars)
} else {
@ -523,9 +520,9 @@ impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
struct 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() {
ControlFlow::Break(guar)
} 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() {
ControlFlow::Break(guar)
} 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() {
ControlFlow::Break(guar)
} else {

View File

@ -22,9 +22,9 @@ fn get_enum_ty(enum_ty: Ty<'_>) -> Option<Ty<'_>> {
}
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;
if self.level == 1 {
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;
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(())
}
}

View File

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