Skip to content

Commit cf873b8

Browse files
committed
Allow hir visitors to directly return booleans
1 parent d2e6cf7 commit cf873b8

File tree

19 files changed

+136
-250
lines changed

19 files changed

+136
-250
lines changed

compiler/rustc_ast_ir/src/visit.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use core::ops::ControlFlow;
22

3-
/// Similar to the `Try` trait, but also implemented for `()`.
3+
/// Similar to the `Try` trait, but also implemented for `()` and `bool`.
44
pub trait VisitorResult {
55
type Residual;
66
fn output() -> Self;
@@ -24,6 +24,24 @@ impl VisitorResult for () {
2424
}
2525
}
2626

27+
/// `false` continues visiting, `true` exits early.
28+
impl VisitorResult for bool {
29+
type Residual = ();
30+
31+
fn output() -> Self {
32+
false
33+
}
34+
fn from_residual((): ()) -> Self {
35+
true
36+
}
37+
fn from_branch(cf: ControlFlow<()>) -> Self {
38+
cf.is_break()
39+
}
40+
fn branch(self) -> ControlFlow<()> {
41+
if self { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
42+
}
43+
}
44+
2745
impl<T> VisitorResult for ControlFlow<T> {
2846
type Residual = T;
2947

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 22 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -784,20 +784,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
784784
/// binding declaration within every scope we inspect.
785785
struct Finder {
786786
hir_id: hir::HirId,
787-
found: bool,
788787
}
789788
impl<'hir> Visitor<'hir> for Finder {
790-
fn visit_pat(&mut self, pat: &'hir hir::Pat<'hir>) {
791-
if pat.hir_id == self.hir_id {
792-
self.found = true;
793-
}
794-
hir::intravisit::walk_pat(self, pat);
789+
type Result = bool;
790+
fn visit_pat(&mut self, pat: &'hir hir::Pat<'hir>) -> bool {
791+
(pat.hir_id == self.hir_id) || hir::intravisit::walk_pat(self, pat)
795792
}
796-
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
797-
if ex.hir_id == self.hir_id {
798-
self.found = true;
799-
}
800-
hir::intravisit::walk_expr(self, ex);
793+
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) -> bool {
794+
(ex.hir_id == self.hir_id) || hir::intravisit::walk_expr(self, ex)
801795
}
802796
}
803797
// The immediate HIR parent of the moved expression. We'll look for it to be a call.
@@ -822,9 +816,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
822816
_ => continue,
823817
};
824818
if let Some(&hir_id) = local_hir_id {
825-
let mut finder = Finder { hir_id, found: false };
826-
finder.visit_expr(e);
827-
if finder.found {
819+
if (Finder { hir_id }).visit_expr(e) {
828820
// The current scope includes the declaration of the binding we're accessing, we
829821
// can't look up any further for loops.
830822
break;
@@ -839,9 +831,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
839831
hir::Node::Expr(hir::Expr {
840832
kind: hir::ExprKind::If(cond, ..), ..
841833
}) => {
842-
let mut finder = Finder { hir_id: expr.hir_id, found: false };
843-
finder.visit_expr(cond);
844-
if finder.found {
834+
if (Finder { hir_id: expr.hir_id }).visit_expr(cond) {
845835
// The expression where the move error happened is in a `while let`
846836
// condition Don't suggest clone as it will likely end in an
847837
// infinite loop.
@@ -1837,17 +1827,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
18371827

18381828
pub struct Holds<'tcx> {
18391829
ty: Ty<'tcx>,
1840-
holds: bool,
18411830
}
18421831

18431832
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Holds<'tcx> {
1844-
type Result = std::ops::ControlFlow<()>;
1833+
type Result = bool;
18451834

1846-
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
1847-
if t == self.ty {
1848-
self.holds = true;
1849-
}
1850-
t.super_visit_with(self)
1835+
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
1836+
(t == self.ty) || t.super_visit_with(self)
18511837
}
18521838
}
18531839

@@ -1863,9 +1849,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
18631849
&& rcvr_ty == ty
18641850
&& let ty::Ref(_, inner, _) = rcvr_ty.kind()
18651851
&& let inner = inner.peel_refs()
1866-
&& let mut v = (Holds { ty: inner, holds: false })
1867-
&& let _ = v.visit_ty(local_ty)
1868-
&& v.holds
1852+
&& (Holds { ty: inner }).visit_ty(local_ty)
18691853
&& let None = self.infcx.type_implements_trait_shallow(clone, inner, self.param_env)
18701854
{
18711855
err.span_label(
@@ -4325,15 +4309,14 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
43254309
}
43264310

43274311
/// Detect whether one of the provided spans is a statement nested within the top-most visited expr
4328-
struct ReferencedStatementsVisitor<'a>(&'a [Span], bool);
4312+
struct ReferencedStatementsVisitor<'a>(&'a [Span]);
43294313

4330-
impl<'a, 'v> Visitor<'v> for ReferencedStatementsVisitor<'a> {
4331-
fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) {
4314+
impl<'v> Visitor<'v> for ReferencedStatementsVisitor<'_> {
4315+
type Result = bool;
4316+
fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) -> bool {
43324317
match s.kind {
4333-
hir::StmtKind::Semi(expr) if self.0.contains(&expr.span) => {
4334-
self.1 = true;
4335-
}
4336-
_ => {}
4318+
hir::StmtKind::Semi(expr) => self.0.contains(&expr.span),
4319+
_ => false,
43374320
}
43384321
}
43394322
}
@@ -4375,9 +4358,7 @@ impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> {
43754358
hir::ExprKind::If(cond, body, None) => {
43764359
// `if` expressions with no `else` that initialize the binding might be missing an
43774360
// `else` arm.
4378-
let mut v = ReferencedStatementsVisitor(self.spans, false);
4379-
v.visit_expr(body);
4380-
if v.1 {
4361+
if ReferencedStatementsVisitor(self.spans).visit_expr(body) {
43814362
self.errors.push((
43824363
cond.span,
43834364
format!(
@@ -4394,11 +4375,9 @@ impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> {
43944375
hir::ExprKind::If(cond, body, Some(other)) => {
43954376
// `if` expressions where the binding is only initialized in one of the two arms
43964377
// might be missing a binding initialization.
4397-
let mut a = ReferencedStatementsVisitor(self.spans, false);
4398-
a.visit_expr(body);
4399-
let mut b = ReferencedStatementsVisitor(self.spans, false);
4400-
b.visit_expr(other);
4401-
match (a.1, b.1) {
4378+
let a = ReferencedStatementsVisitor(self.spans).visit_expr(body);
4379+
let b = ReferencedStatementsVisitor(self.spans).visit_expr(other);
4380+
match (a, b) {
44024381
(true, true) | (false, false) => {}
44034382
(true, false) => {
44044383
if other.span.is_desugaring(DesugaringKind::WhileLoop) {
@@ -4437,11 +4416,7 @@ impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> {
44374416
// arms might be missing an initialization.
44384417
let results: Vec<bool> = arms
44394418
.iter()
4440-
.map(|arm| {
4441-
let mut v = ReferencedStatementsVisitor(self.spans, false);
4442-
v.visit_arm(arm);
4443-
v.1
4444-
})
4419+
.map(|arm| ReferencedStatementsVisitor(self.spans).visit_arm(arm))
44454420
.collect();
44464421
if results.iter().any(|x| *x) && !results.iter().all(|x| *x) {
44474422
for (arm, seen) in arms.iter().zip(results) {

compiler/rustc_builtin_macros/src/cfg_eval.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
22

3-
use core::ops::ControlFlow;
43
use rustc_ast as ast;
54
use rustc_ast::mut_visit::MutVisitor;
65
use rustc_ast::ptr::P;
@@ -91,20 +90,13 @@ fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool {
9190
struct CfgFinder;
9291

9392
impl<'ast> visit::Visitor<'ast> for CfgFinder {
94-
type Result = ControlFlow<()>;
95-
fn visit_attribute(&mut self, attr: &'ast Attribute) -> ControlFlow<()> {
96-
if attr
97-
.ident()
98-
.is_some_and(|ident| ident.name == sym::cfg || ident.name == sym::cfg_attr)
99-
{
100-
ControlFlow::Break(())
101-
} else {
102-
ControlFlow::Continue(())
103-
}
93+
type Result = bool;
94+
fn visit_attribute(&mut self, attr: &'ast Attribute) -> bool {
95+
attr.ident().is_some_and(|ident| ident.name == sym::cfg || ident.name == sym::cfg_attr)
10496
}
10597
}
10698

107-
let res = match annotatable {
99+
match annotatable {
108100
Annotatable::Item(item) => CfgFinder.visit_item(item),
109101
Annotatable::TraitItem(item) => CfgFinder.visit_assoc_item(item, visit::AssocCtxt::Trait),
110102
Annotatable::ImplItem(item) => CfgFinder.visit_assoc_item(item, visit::AssocCtxt::Impl),
@@ -119,8 +111,7 @@ fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool {
119111
Annotatable::FieldDef(field) => CfgFinder.visit_field_def(field),
120112
Annotatable::Variant(variant) => CfgFinder.visit_variant(variant),
121113
Annotatable::Crate(krate) => CfgFinder.visit_crate(krate),
122-
};
123-
res.is_break()
114+
}
124115
}
125116

126117
impl CfgEval<'_> {

compiler/rustc_builtin_macros/src/deriving/default.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::deriving::generic::ty::*;
22
use crate::deriving::generic::*;
33
use crate::errors;
4-
use core::ops::ControlFlow;
54
use rustc_ast as ast;
65
use rustc_ast::visit::visit_opt;
76
use rustc_ast::{attr, EnumDef, VariantData};
@@ -235,16 +234,12 @@ fn has_a_default_variant(item: &Annotatable) -> bool {
235234
struct HasDefaultAttrOnVariant;
236235

237236
impl<'ast> rustc_ast::visit::Visitor<'ast> for HasDefaultAttrOnVariant {
238-
type Result = ControlFlow<()>;
239-
fn visit_variant(&mut self, v: &'ast rustc_ast::Variant) -> ControlFlow<()> {
240-
if v.attrs.iter().any(|attr| attr.has_name(kw::Default)) {
241-
ControlFlow::Break(())
242-
} else {
243-
// no need to subrecurse.
244-
ControlFlow::Continue(())
245-
}
237+
type Result = bool;
238+
fn visit_variant(&mut self, v: &'ast rustc_ast::Variant) -> bool {
239+
v.attrs.iter().any(|attr| attr.has_name(kw::Default))
240+
// no need to walk the variant, we are only looking for top level variants
246241
}
247242
}
248243

249-
item.visit_with(&mut HasDefaultAttrOnVariant).is_break()
244+
item.visit_with(&mut HasDefaultAttrOnVariant)
250245
}

compiler/rustc_hir_analysis/src/collect/generics_of.rs

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::ops::ControlFlow;
2+
13
use crate::middle::resolve_bound_vars as rbv;
24
use hir::{
35
intravisit::{self, Visitor},
@@ -87,14 +89,9 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
8789
let mut in_param_ty = false;
8890
for (_parent, node) in tcx.hir().parent_iter(hir_id) {
8991
if let Some(generics) = node.generics() {
90-
let mut visitor = AnonConstInParamTyDetector {
91-
in_param_ty: false,
92-
found_anon_const_in_param_ty: false,
93-
ct: hir_id,
94-
};
92+
let mut visitor = AnonConstInParamTyDetector { in_param_ty: false, ct: hir_id };
9593

96-
visitor.visit_generics(generics);
97-
in_param_ty = visitor.found_anon_const_in_param_ty;
94+
in_param_ty = visitor.visit_generics(generics);
9895
break;
9996
}
10097
}
@@ -460,50 +457,45 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
460457
struct LateBoundRegionsDetector<'tcx> {
461458
tcx: TyCtxt<'tcx>,
462459
outer_index: ty::DebruijnIndex,
463-
has_late_bound_regions: Option<Span>,
464460
}
465461

466462
impl<'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'tcx> {
467-
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
468-
if self.has_late_bound_regions.is_some() {
469-
return;
470-
}
463+
type Result = ControlFlow<Span>;
464+
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) -> ControlFlow<Span> {
471465
match ty.kind {
472466
hir::TyKind::BareFn(..) => {
473467
self.outer_index.shift_in(1);
474-
intravisit::walk_ty(self, ty);
468+
let res = intravisit::walk_ty(self, ty);
475469
self.outer_index.shift_out(1);
470+
res
476471
}
477472
_ => intravisit::walk_ty(self, ty),
478473
}
479474
}
480475

481-
fn visit_poly_trait_ref(&mut self, tr: &'tcx hir::PolyTraitRef<'tcx>) {
482-
if self.has_late_bound_regions.is_some() {
483-
return;
484-
}
476+
fn visit_poly_trait_ref(&mut self, tr: &'tcx hir::PolyTraitRef<'tcx>) -> ControlFlow<Span> {
485477
self.outer_index.shift_in(1);
486-
intravisit::walk_poly_trait_ref(self, tr);
478+
let res = intravisit::walk_poly_trait_ref(self, tr);
487479
self.outer_index.shift_out(1);
480+
res
488481
}
489482

490-
fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) {
491-
if self.has_late_bound_regions.is_some() {
492-
return;
493-
}
494-
483+
fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) -> ControlFlow<Span> {
495484
match self.tcx.named_bound_var(lt.hir_id) {
496-
Some(rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(..)) => {}
485+
Some(rbv::ResolvedArg::StaticLifetime | rbv::ResolvedArg::EarlyBound(..)) => {
486+
ControlFlow::Continue(())
487+
}
497488
Some(rbv::ResolvedArg::LateBound(debruijn, _, _))
498-
if debruijn < self.outer_index => {}
489+
if debruijn < self.outer_index =>
490+
{
491+
ControlFlow::Continue(())
492+
}
499493
Some(
500494
rbv::ResolvedArg::LateBound(..)
501495
| rbv::ResolvedArg::Free(..)
502496
| rbv::ResolvedArg::Error(_),
503497
)
504-
| None => {
505-
self.has_late_bound_regions = Some(lt.ident.span);
506-
}
498+
| None => ControlFlow::Break(lt.ident.span),
507499
}
508500
}
509501
}
@@ -513,20 +505,15 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
513505
generics: &'tcx hir::Generics<'tcx>,
514506
decl: &'tcx hir::FnDecl<'tcx>,
515507
) -> Option<Span> {
516-
let mut visitor = LateBoundRegionsDetector {
517-
tcx,
518-
outer_index: ty::INNERMOST,
519-
has_late_bound_regions: None,
520-
};
508+
let mut visitor = LateBoundRegionsDetector { tcx, outer_index: ty::INNERMOST };
521509
for param in generics.params {
522510
if let GenericParamKind::Lifetime { .. } = param.kind {
523511
if tcx.is_late_bound(param.hir_id) {
524512
return Some(param.span);
525513
}
526514
}
527515
}
528-
visitor.visit_fn_decl(decl);
529-
visitor.has_late_bound_regions
516+
visitor.visit_fn_decl(decl).break_value()
530517
}
531518

532519
let decl = node.fn_decl()?;
@@ -536,26 +523,26 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
536523

537524
struct AnonConstInParamTyDetector {
538525
in_param_ty: bool,
539-
found_anon_const_in_param_ty: bool,
540526
ct: HirId,
541527
}
542528

543529
impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
544-
fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
530+
type Result = bool;
531+
532+
fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) -> bool {
545533
if let GenericParamKind::Const { ty, default: _, is_host_effect: _, synthetic: _ } = p.kind
546534
{
547535
let prev = self.in_param_ty;
548536
self.in_param_ty = true;
549-
self.visit_ty(ty);
537+
let res = self.visit_ty(ty);
550538
self.in_param_ty = prev;
539+
res
540+
} else {
541+
false
551542
}
552543
}
553544

554-
fn visit_anon_const(&mut self, c: &'v hir::AnonConst) {
555-
if self.in_param_ty && self.ct == c.hir_id {
556-
self.found_anon_const_in_param_ty = true;
557-
} else {
558-
intravisit::walk_anon_const(self, c)
559-
}
545+
fn visit_anon_const(&mut self, c: &'v hir::AnonConst) -> bool {
546+
(self.in_param_ty && self.ct == c.hir_id) || intravisit::walk_anon_const(self, c)
560547
}
561548
}

0 commit comments

Comments
 (0)