11use crate :: ty:: needs_ordered_drop;
22use crate :: { get_enclosing_block, path_to_local_id} ;
33use core:: ops:: ControlFlow ;
4+ use rustc_ast:: visit:: { try_visit, VisitorResult } ;
45use rustc_hir as hir;
56use rustc_hir:: def:: { CtorKind , DefKind , Res } ;
67use rustc_hir:: intravisit:: { self , walk_block, walk_expr, Visitor } ;
@@ -50,44 +51,46 @@ impl Continue for Descend {
5051/// A type which can be visited.
5152pub trait Visitable < ' tcx > {
5253 /// 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 ;
5455}
5556impl < ' tcx , T > Visitable < ' tcx > for & ' tcx [ T ]
5657where
5758 & ' tcx T : Visitable < ' tcx > ,
5859{
59- fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) {
60+ fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) -> V :: Result {
6061 for x in self {
61- x. visit ( visitor) ;
62+ try_visit ! ( x. visit( visitor) ) ;
6263 }
64+ V :: Result :: output ( )
6365 }
6466}
6567impl < ' tcx , A , B > Visitable < ' tcx > for ( A , B )
6668where
6769 A : Visitable < ' tcx > ,
6870 B : Visitable < ' tcx > ,
6971{
70- fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) {
72+ fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) -> V :: Result {
7173 let ( a, b) = self ;
72- a. visit ( visitor) ;
73- b. visit ( visitor) ;
74+ try_visit ! ( a. visit( visitor) ) ;
75+ b. visit ( visitor)
7476 }
7577}
7678impl < ' tcx , T > Visitable < ' tcx > for Option < T >
7779where
7880 T : Visitable < ' tcx > ,
7981{
80- fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) {
82+ fn visit < V : Visitor < ' tcx > > ( self , visitor : & mut V ) -> V :: Result {
8183 if let Some ( x) = self {
82- x. visit ( visitor) ;
84+ try_visit ! ( x. visit( visitor) ) ;
8385 }
86+ V :: Result :: output ( )
8487 }
8588}
8689macro_rules! visitable_ref {
8790 ( $t: ident, $f: ident) => {
8891 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 )
9194 }
9295 }
9396 } ;
@@ -104,45 +107,37 @@ pub fn for_each_expr_without_closures<'tcx, B, C: Continue>(
104107 node : impl Visitable < ' tcx > ,
105108 f : impl FnMut ( & ' tcx Expr < ' tcx > ) -> ControlFlow < B , C > ,
106109) -> Option < B > {
107- struct V < B , F > {
110+ struct V < F > {
108111 f : F ,
109- res : Option < B > ,
110112 }
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 > ;
113115
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 {
118117 match ( self . f ) ( e) {
119118 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) ,
124120 ControlFlow :: Continue ( _) => ControlFlow :: Continue ( ( ) ) ,
125121 }
126122 }
127123
128124 // 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 {
130126 ControlFlow :: Continue ( ( ) )
131127 }
132- fn visit_pat ( & mut self , _: & ' tcx Pat < ' tcx > ) -> ControlFlow < ( ) > {
128+ fn visit_pat ( & mut self , _: & ' tcx Pat < ' tcx > ) -> Self :: Result {
133129 ControlFlow :: Continue ( ( ) )
134130 }
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 {
136132 ControlFlow :: Continue ( ( ) )
137133 }
138134 // Avoid monomorphising all `visit_*` functions.
139- fn visit_nested_item ( & mut self , _: ItemId ) -> ControlFlow < ( ) > {
135+ fn visit_nested_item ( & mut self , _: ItemId ) -> Self :: Result {
140136 ControlFlow :: Continue ( ( ) )
141137 }
142138 }
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 ( )
146141}
147142
148143/// 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>(
152147 node : impl Visitable < ' tcx > ,
153148 f : impl FnMut ( & ' tcx Expr < ' tcx > ) -> ControlFlow < B , C > ,
154149) -> Option < B > {
155- struct V < ' tcx , B , F > {
150+ struct V < ' tcx , F > {
156151 tcx : TyCtxt < ' tcx > ,
157152 f : F ,
158- res : Option < B > ,
159153 }
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 > {
161155 type NestedFilter = nested_filter:: OnlyBodies ;
156+ type Result = ControlFlow < B > ;
157+
162158 fn nested_visit_map ( & mut self ) -> Self :: Map {
163159 self . tcx . hir ( )
164160 }
165161
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 {
170163 match ( self . f ) ( e) {
171164 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 ( ( ) ) ,
174167 }
175168 }
176169
177170 // 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+ }
179174 // 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+ }
183184 // 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+ }
185188 }
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 ( )
193191}
194192
195193/// returns `true` if expr contains match expr desugared from try
0 commit comments