Skip to content

Commit ea91556

Browse files
committed
Use ControlFlow in HIR visitors
1 parent f4b42d7 commit ea91556

File tree

12 files changed

+166
-200
lines changed

12 files changed

+166
-200
lines changed

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

+29-47
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![allow(rustc::diagnostic_outside_of_impl)]
22
#![allow(rustc::untranslatable_diagnostic)]
33

4+
use core::ops::ControlFlow;
45
use hir::ExprKind;
56
use rustc_errors::{Applicability, DiagnosticBuilder};
67
use rustc_hir as hir;
@@ -732,30 +733,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
732733
_ => local_decl.source_info.span,
733734
};
734735

735-
struct BindingFinder {
736-
span: Span,
737-
hir_id: Option<hir::HirId>,
738-
}
739-
740-
impl<'tcx> Visitor<'tcx> for BindingFinder {
741-
fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
742-
if let hir::StmtKind::Local(local) = s.kind {
743-
if local.pat.span == self.span {
744-
self.hir_id = Some(local.hir_id);
745-
}
746-
}
747-
hir::intravisit::walk_stmt(self, s);
748-
}
749-
}
750-
751736
let def_id = self.body.source.def_id();
752737
let hir_id = if let Some(local_def_id) = def_id.as_local()
753738
&& let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
754739
{
755740
let body = self.infcx.tcx.hir().body(body_id);
756-
let mut v = BindingFinder { span: pat_span, hir_id: None };
757-
v.visit_body(body);
758-
v.hir_id
741+
BindingFinder { span: pat_span }.visit_body(body).break_value()
759742
} else {
760743
None
761744
};
@@ -864,17 +847,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
864847
};
865848

866849
let hir_map = self.infcx.tcx.hir();
867-
struct Finder<'tcx> {
850+
struct Finder {
868851
span: Span,
869-
expr: Option<&'tcx Expr<'tcx>>,
870852
}
871853

872-
impl<'tcx> Visitor<'tcx> for Finder<'tcx> {
873-
fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
874-
if e.span == self.span && self.expr.is_none() {
875-
self.expr = Some(e);
854+
impl<'tcx> Visitor<'tcx> for Finder {
855+
type Result = ControlFlow<&'tcx Expr<'tcx>>;
856+
fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) -> Self::Result {
857+
if e.span == self.span {
858+
ControlFlow::Break(e)
859+
} else {
860+
hir::intravisit::walk_expr(self, e)
876861
}
877-
hir::intravisit::walk_expr(self, e);
878862
}
879863
}
880864
if let Some(body_id) = hir_map.maybe_body_owned_by(self.mir_def_id())
@@ -883,9 +867,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
883867
// `span` corresponds to the expression being iterated, find the `for`-loop desugared
884868
// expression with that span in order to identify potential fixes when encountering a
885869
// read-only iterator that should be mutable.
886-
let mut v = Finder { span, expr: None };
887-
v.visit_block(block);
888-
if let Some(expr) = v.expr
870+
if let ControlFlow::Break(expr) = (Finder { span }).visit_block(block)
889871
&& let Call(_, [expr]) = expr.kind
890872
{
891873
match expr.kind {
@@ -1184,29 +1166,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
11841166
);
11851167
}
11861168
Some((false, err_label_span, message)) => {
1187-
struct BindingFinder {
1188-
span: Span,
1189-
hir_id: Option<hir::HirId>,
1190-
}
1191-
1192-
impl<'tcx> Visitor<'tcx> for BindingFinder {
1193-
fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
1194-
if let hir::StmtKind::Local(local) = s.kind {
1195-
if local.pat.span == self.span {
1196-
self.hir_id = Some(local.hir_id);
1197-
}
1198-
}
1199-
hir::intravisit::walk_stmt(self, s);
1200-
}
1201-
}
12021169
let def_id = self.body.source.def_id();
12031170
let hir_id = if let Some(local_def_id) = def_id.as_local()
12041171
&& let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
12051172
{
12061173
let body = self.infcx.tcx.hir().body(body_id);
1207-
let mut v = BindingFinder { span: err_label_span, hir_id: None };
1208-
v.visit_body(body);
1209-
v.hir_id
1174+
BindingFinder { span: err_label_span }.visit_body(body).break_value()
12101175
} else {
12111176
None
12121177
};
@@ -1338,6 +1303,23 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
13381303
}
13391304
}
13401305

1306+
struct BindingFinder {
1307+
span: Span,
1308+
}
1309+
1310+
impl<'tcx> Visitor<'tcx> for BindingFinder {
1311+
type Result = ControlFlow<hir::HirId>;
1312+
fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) -> Self::Result {
1313+
if let hir::StmtKind::Local(local) = s.kind
1314+
&& local.pat.span == self.span
1315+
{
1316+
ControlFlow::Break(local.hir_id)
1317+
} else {
1318+
hir::intravisit::walk_stmt(self, s)
1319+
}
1320+
}
1321+
}
1322+
13411323
pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {
13421324
debug!("local_info: {:?}, ty.kind(): {:?}", local_decl.local_info, local_decl.ty.kind());
13431325

compiler/rustc_borrowck/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#![feature(assert_matches)]
77
#![feature(associated_type_bounds)]
88
#![feature(box_patterns)]
9+
#![feature(control_flow_enum)]
910
#![feature(let_chains)]
1011
#![feature(min_specialization)]
1112
#![feature(never_type)]

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::potentially_plural_count;
22
use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture};
3+
use core::ops::ControlFlow;
34
use hir::def_id::{DefId, DefIdMap, LocalDefId};
45
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
56
use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
@@ -1565,24 +1566,24 @@ fn compare_synthetic_generics<'tcx>(
15651566
let (sig, _) = impl_m.expect_fn();
15661567
let input_tys = sig.decl.inputs;
15671568

1568-
struct Visitor(Option<Span>, hir::def_id::LocalDefId);
1569+
struct Visitor(hir::def_id::LocalDefId);
15691570
impl<'v> intravisit::Visitor<'v> for Visitor {
1570-
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
1571-
intravisit::walk_ty(self, ty);
1571+
type Result = ControlFlow<Span>;
1572+
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) -> Self::Result {
15721573
if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind
15731574
&& let Res::Def(DefKind::TyParam, def_id) = path.res
1574-
&& def_id == self.1.to_def_id()
1575+
&& def_id == self.0.to_def_id()
15751576
{
1576-
self.0 = Some(ty.span);
1577+
ControlFlow::Break(ty.span)
1578+
} else {
1579+
intravisit::walk_ty(self, ty)
15771580
}
15781581
}
15791582
}
15801583

1581-
let mut visitor = Visitor(None, impl_def_id);
1582-
for ty in input_tys {
1583-
intravisit::Visitor::visit_ty(&mut visitor, ty);
1584-
}
1585-
let span = visitor.0?;
1584+
let span = input_tys.iter().find_map(|ty| {
1585+
intravisit::Visitor::visit_ty(&mut Visitor(impl_def_id), ty).break_value()
1586+
})?;
15861587

15871588
let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds;
15881589
let bounds = bounds.first()?.span().to(bounds.last()?.span());

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file
77
//! is also responsible for assigning their semantics to implicit lifetimes in trait objects.
88
9+
use core::ops::ControlFlow;
910
use rustc_ast::walk_list;
1011
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
1112
use rustc_errors::{codes::*, struct_span_code_err};
@@ -417,23 +418,18 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
417418
{
418419
if let &hir::ClosureBinder::For { span: for_sp, .. } = binder {
419420
fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> {
420-
struct V(Option<Span>);
421-
421+
struct V;
422422
impl<'v> Visitor<'v> for V {
423-
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
424-
match t.kind {
425-
_ if self.0.is_some() => (),
426-
hir::TyKind::Infer => {
427-
self.0 = Some(t.span);
428-
}
429-
_ => intravisit::walk_ty(self, t),
423+
type Result = ControlFlow<Span>;
424+
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) -> Self::Result {
425+
if matches!(t.kind, hir::TyKind::Infer) {
426+
ControlFlow::Break(t.span)
427+
} else {
428+
intravisit::walk_ty(self, t)
430429
}
431430
}
432431
}
433-
434-
let mut v = V(None);
435-
v.visit_ty(ty);
436-
v.0
432+
V.visit_ty(ty).break_value()
437433
}
438434

439435
let infer_in_rt_sp = match fn_decl.output {
@@ -1965,7 +1961,6 @@ fn is_late_bound_map(
19651961
arg_is_constrained: Box<[bool]>,
19661962
}
19671963

1968-
use std::ops::ControlFlow;
19691964
use ty::Ty;
19701965
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstrainedCollectorPostAstConv {
19711966
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {

compiler/rustc_hir_analysis/src/collect/type_of.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use core::ops::ControlFlow;
12
use rustc_errors::{Applicability, StashKey};
23
use rustc_hir as hir;
34
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -670,19 +671,16 @@ pub fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
670671
if tcx.features().lazy_type_alias {
671672
return true;
672673
}
673-
struct HasTait {
674-
has_type_alias_impl_trait: bool,
675-
}
674+
struct HasTait;
676675
impl<'tcx> Visitor<'tcx> for HasTait {
677-
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
676+
type Result = ControlFlow<()>;
677+
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) -> Self::Result {
678678
if let hir::TyKind::OpaqueDef(..) = t.kind {
679-
self.has_type_alias_impl_trait = true;
679+
ControlFlow::Break(())
680680
} else {
681-
hir::intravisit::walk_ty(self, t);
681+
hir::intravisit::walk_ty(self, t)
682682
}
683683
}
684684
}
685-
let mut has_tait = HasTait { has_type_alias_impl_trait: false };
686-
has_tait.visit_ty(tcx.hir().expect_item(def_id).expect_ty_alias().0);
687-
has_tait.has_type_alias_impl_trait
685+
HasTait.visit_ty(tcx.hir().expect_item(def_id).expect_ty_alias().0).is_break()
688686
}

compiler/rustc_hir_typeck/src/method/suggest.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use crate::errors::{self, CandidateTraitNote, NoAssociatedItem};
77
use crate::Expectation;
88
use crate::FnCtxt;
9+
use core::ops::ControlFlow;
910
use rustc_ast::ast::Mutability;
1011
use rustc_attr::parse_confusables;
1112
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@@ -2212,30 +2213,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22122213
let map = self.infcx.tcx.hir();
22132214
let body_id = self.tcx.hir().body_owned_by(self.body_id);
22142215
let body = map.body(body_id);
2215-
struct LetVisitor<'a> {
2216-
result: Option<&'a hir::Expr<'a>>,
2216+
struct LetVisitor {
22172217
ident_name: Symbol,
22182218
}
22192219

22202220
// FIXME: This really should be taking scoping, etc into account.
2221-
impl<'v> Visitor<'v> for LetVisitor<'v> {
2222-
fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
2221+
impl<'v> Visitor<'v> for LetVisitor {
2222+
type Result = ControlFlow<Option<&'v hir::Expr<'v>>>;
2223+
fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result {
22232224
if let hir::StmtKind::Local(hir::Local { pat, init, .. }) = &ex.kind
22242225
&& let Binding(_, _, ident, ..) = pat.kind
22252226
&& ident.name == self.ident_name
22262227
{
2227-
self.result = *init;
2228+
ControlFlow::Break(*init)
22282229
} else {
2229-
hir::intravisit::walk_stmt(self, ex);
2230+
hir::intravisit::walk_stmt(self, ex)
22302231
}
22312232
}
22322233
}
22332234

2234-
let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name };
2235-
visitor.visit_body(body);
2236-
22372235
if let Node::Expr(call_expr) = self.tcx.parent_hir_node(seg1.hir_id)
2238-
&& let Some(expr) = visitor.result
2236+
&& let ControlFlow::Break(Some(expr)) =
2237+
(LetVisitor { ident_name: seg1.ident.name }).visit_body(body)
22392238
&& let Some(self_ty) = self.node_ty_opt(expr.hir_id)
22402239
{
22412240
let probe = self.lookup_probe_for_diagnostic(

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+8-11
Original file line numberDiff line numberDiff line change
@@ -2128,15 +2128,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
21282128
let tykind = match self.tcx.opt_hir_node_by_def_id(trace.cause.body_id) {
21292129
Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) => {
21302130
let body = hir.body(*body_id);
2131-
struct LetVisitor<'v> {
2131+
struct LetVisitor {
21322132
span: Span,
2133-
result: Option<&'v hir::Ty<'v>>,
21342133
}
2135-
impl<'v> Visitor<'v> for LetVisitor<'v> {
2136-
fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) {
2137-
if self.result.is_some() {
2138-
return;
2139-
}
2134+
impl<'v> Visitor<'v> for LetVisitor {
2135+
type Result = ControlFlow<&'v hir::TyKind<'v>>;
2136+
fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) -> Self::Result {
21402137
// Find a local statement where the initializer has
21412138
// the same span as the error and the type is specified.
21422139
if let hir::Stmt {
@@ -2150,13 +2147,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
21502147
} = s
21512148
&& init_span == &self.span
21522149
{
2153-
self.result = Some(*array_ty);
2150+
ControlFlow::Break(&array_ty.peel_refs().kind)
2151+
} else {
2152+
ControlFlow::Continue(())
21542153
}
21552154
}
21562155
}
2157-
let mut visitor = LetVisitor { span, result: None };
2158-
visitor.visit_body(body);
2159-
visitor.result.map(|r| &r.peel_refs().kind)
2156+
LetVisitor { span }.visit_body(body).break_value()
21602157
}
21612158
Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. })) => {
21622159
Some(&ty.peel_refs().kind)

0 commit comments

Comments
 (0)