1
1
use crate :: ty:: needs_ordered_drop;
2
2
use crate :: { get_enclosing_block, path_to_local_id} ;
3
3
use core:: ops:: ControlFlow ;
4
+ use rustc_ast:: visit:: { try_visit, VisitorResult } ;
4
5
use rustc_hir as hir;
5
6
use rustc_hir:: def:: { CtorKind , DefKind , Res } ;
6
7
use rustc_hir:: intravisit:: { self , walk_block, walk_expr, Visitor } ;
@@ -50,44 +51,46 @@ impl Continue for Descend {
50
51
/// A type which can be visited.
51
52
pub trait Visitable < ' tcx > {
52
53
/// Calls the corresponding `visit_*` function on the visitor.
53
- fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) ;
54
+ fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) -> V :: Result ;
54
55
}
55
56
impl < ' tcx , T > Visitable < ' tcx > for & ' tcx [ T ]
56
57
where
57
58
& ' tcx T : Visitable < ' tcx > ,
58
59
{
59
- fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) {
60
+ fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) -> V :: Result {
60
61
for x in self {
61
- x. visit ( visitor) ;
62
+ try_visit ! ( x. visit( visitor) ) ;
62
63
}
64
+ V :: Result :: output ( )
63
65
}
64
66
}
65
67
impl < ' tcx , A , B > Visitable < ' tcx > for ( A , B )
66
68
where
67
69
A : Visitable < ' tcx > ,
68
70
B : Visitable < ' tcx > ,
69
71
{
70
- fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) {
72
+ fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) -> V :: Result {
71
73
let ( a, b) = self ;
72
- a. visit ( visitor) ;
73
- b. visit ( visitor) ;
74
+ try_visit ! ( a. visit( visitor) ) ;
75
+ b. visit ( visitor)
74
76
}
75
77
}
76
78
impl < ' tcx , T > Visitable < ' tcx > for Option < T >
77
79
where
78
80
T : Visitable < ' tcx > ,
79
81
{
80
- fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) {
82
+ fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) -> V :: Result {
81
83
if let Some ( x) = self {
82
- x. visit ( visitor) ;
84
+ try_visit ! ( x. visit( visitor) ) ;
83
85
}
86
+ V :: Result :: output ( )
84
87
}
85
88
}
86
89
macro_rules! visitable_ref {
87
90
( $t: ident, $f: ident) => {
88
91
impl <' tcx> Visitable <' tcx> for & ' tcx $t<' tcx> {
89
- fn visit<V : Visitor <' tcx>>( self , visitor: & mut V ) {
90
- visitor. $f( self ) ;
92
+ fn visit<V : Visitor <' tcx>>( self , visitor: & mut V ) -> V :: Result {
93
+ visitor. $f( self )
91
94
}
92
95
}
93
96
} ;
@@ -104,45 +107,37 @@ pub fn for_each_expr_without_closures<'tcx, B, C: Continue>(
104
107
node : impl Visitable < ' tcx > ,
105
108
f : impl FnMut ( & ' tcx Expr < ' tcx > ) -> ControlFlow < B , C > ,
106
109
) -> Option < B > {
107
- struct V < B , F > {
110
+ struct V < F > {
108
111
f : F ,
109
- res : Option < B > ,
110
112
}
111
- impl < ' tcx , B , C : Continue , F : FnMut ( & ' tcx Expr < ' tcx > ) -> ControlFlow < B , C > > Visitor < ' tcx > for V < B , F > {
112
- type Result = ControlFlow < ( ) > ;
113
+ impl < ' tcx , B , C : Continue , F : FnMut ( & ' tcx Expr < ' tcx > ) -> ControlFlow < B , C > > Visitor < ' tcx > for V < F > {
114
+ type Result = ControlFlow < B > ;
113
115
114
- fn visit_expr ( & mut self , e : & ' tcx Expr < ' tcx > ) -> ControlFlow < ( ) > {
115
- if self . res . is_some ( ) {
116
- return ControlFlow :: Break ( ( ) ) ;
117
- }
116
+ fn visit_expr ( & mut self , e : & ' tcx Expr < ' tcx > ) -> Self :: Result {
118
117
match ( self . f ) ( e) {
119
118
ControlFlow :: Continue ( c) if c. descend ( ) => walk_expr ( self , e) ,
120
- ControlFlow :: Break ( b) => {
121
- self . res = Some ( b) ;
122
- ControlFlow :: Break ( ( ) )
123
- } ,
119
+ ControlFlow :: Break ( b) => ControlFlow :: Break ( b) ,
124
120
ControlFlow :: Continue ( _) => ControlFlow :: Continue ( ( ) ) ,
125
121
}
126
122
}
127
123
128
124
// Avoid unnecessary `walk_*` calls.
129
- fn visit_ty ( & mut self , _: & ' tcx hir:: Ty < ' tcx > ) -> ControlFlow < ( ) > {
125
+ fn visit_ty ( & mut self , _: & ' tcx hir:: Ty < ' tcx > ) -> Self :: Result {
130
126
ControlFlow :: Continue ( ( ) )
131
127
}
132
- fn visit_pat ( & mut self , _: & ' tcx Pat < ' tcx > ) -> ControlFlow < ( ) > {
128
+ fn visit_pat ( & mut self , _: & ' tcx Pat < ' tcx > ) -> Self :: Result {
133
129
ControlFlow :: Continue ( ( ) )
134
130
}
135
- fn visit_qpath ( & mut self , _: & ' tcx QPath < ' tcx > , _: HirId , _: Span ) -> ControlFlow < ( ) > {
131
+ fn visit_qpath ( & mut self , _: & ' tcx QPath < ' tcx > , _: HirId , _: Span ) -> Self :: Result {
136
132
ControlFlow :: Continue ( ( ) )
137
133
}
138
134
// Avoid monomorphising all `visit_*` functions.
139
- fn visit_nested_item ( & mut self , _: ItemId ) -> ControlFlow < ( ) > {
135
+ fn visit_nested_item ( & mut self , _: ItemId ) -> Self :: Result {
140
136
ControlFlow :: Continue ( ( ) )
141
137
}
142
138
}
143
- let mut v = V { f, res : None } ;
144
- node. visit ( & mut v) ;
145
- v. res
139
+ let mut v = V { f } ;
140
+ node. visit ( & mut v) . break_value ( )
146
141
}
147
142
148
143
/// Calls the given function once for each expression contained. This will enter bodies, but not
@@ -152,44 +147,47 @@ pub fn for_each_expr<'tcx, B, C: Continue>(
152
147
node : impl Visitable < ' tcx > ,
153
148
f : impl FnMut ( & ' tcx Expr < ' tcx > ) -> ControlFlow < B , C > ,
154
149
) -> Option < B > {
155
- struct V < ' tcx , B , F > {
150
+ struct V < ' tcx , F > {
156
151
tcx : TyCtxt < ' tcx > ,
157
152
f : F ,
158
- res : Option < B > ,
159
153
}
160
- impl < ' tcx , B , C : Continue , F : FnMut ( & ' tcx Expr < ' tcx > ) -> ControlFlow < B , C > > Visitor < ' tcx > for V < ' tcx , B , F > {
154
+ impl < ' tcx , B , C : Continue , F : FnMut ( & ' tcx Expr < ' tcx > ) -> ControlFlow < B , C > > Visitor < ' tcx > for V < ' tcx , F > {
161
155
type NestedFilter = nested_filter:: OnlyBodies ;
156
+ type Result = ControlFlow < B > ;
157
+
162
158
fn nested_visit_map ( & mut self ) -> Self :: Map {
163
159
self . tcx . hir ( )
164
160
}
165
161
166
- fn visit_expr ( & mut self , e : & ' tcx Expr < ' tcx > ) {
167
- if self . res . is_some ( ) {
168
- return ;
169
- }
162
+ fn visit_expr ( & mut self , e : & ' tcx Expr < ' tcx > ) -> Self :: Result {
170
163
match ( self . f ) ( e) {
171
164
ControlFlow :: Continue ( c) if c. descend ( ) => walk_expr ( self , e) ,
172
- ControlFlow :: Break ( b) => self . res = Some ( b) ,
173
- ControlFlow :: Continue ( _) => ( ) ,
165
+ ControlFlow :: Break ( b) => ControlFlow :: Break ( b) ,
166
+ ControlFlow :: Continue ( _) => ControlFlow :: Continue ( ( ) ) ,
174
167
}
175
168
}
176
169
177
170
// Only walk closures
178
- fn visit_anon_const ( & mut self , _: & ' tcx AnonConst ) { }
171
+ fn visit_anon_const ( & mut self , _: & ' tcx AnonConst ) -> Self :: Result {
172
+ ControlFlow :: Continue ( ( ) )
173
+ }
179
174
// Avoid unnecessary `walk_*` calls.
180
- fn visit_ty ( & mut self , _: & ' tcx hir:: Ty < ' tcx > ) { }
181
- fn visit_pat ( & mut self , _: & ' tcx Pat < ' tcx > ) { }
182
- fn visit_qpath ( & mut self , _: & ' tcx QPath < ' tcx > , _: HirId , _: Span ) { }
175
+ fn visit_ty ( & mut self , _: & ' tcx hir:: Ty < ' tcx > ) -> Self :: Result {
176
+ ControlFlow :: Continue ( ( ) )
177
+ }
178
+ fn visit_pat ( & mut self , _: & ' tcx Pat < ' tcx > ) -> Self :: Result {
179
+ ControlFlow :: Continue ( ( ) )
180
+ }
181
+ fn visit_qpath ( & mut self , _: & ' tcx QPath < ' tcx > , _: HirId , _: Span ) -> Self :: Result {
182
+ ControlFlow :: Continue ( ( ) )
183
+ }
183
184
// Avoid monomorphising all `visit_*` functions.
184
- fn visit_nested_item ( & mut self , _: ItemId ) { }
185
+ fn visit_nested_item ( & mut self , _: ItemId ) -> Self :: Result {
186
+ ControlFlow :: Continue ( ( ) )
187
+ }
185
188
}
186
- let mut v = V {
187
- tcx : cx. tcx ,
188
- f,
189
- res : None ,
190
- } ;
191
- node. visit ( & mut v) ;
192
- v. res
189
+ let mut v = V { tcx : cx. tcx , f } ;
190
+ node. visit ( & mut v) . break_value ( )
193
191
}
194
192
195
193
/// returns `true` if expr contains match expr desugared from try
0 commit comments