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

@ -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() {