@@ -178,77 +178,91 @@ pub trait ValueVisitor<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: fmt::Debug +
178178 self . value ( ) . layout ( )
179179 }
180180
181- // Replace the value by `val`, which must be the `field`th field of `self`, then call
182- // `visit_value` and then un-do everything that might have happened to the visitor state.
183- // The point of this is that some visitors keep a stack of fields that we projected below,
184- // and this lets us avoid copying that stack; instead they will pop the stack after
185- // executing `visit_value`.
186- fn visit_field (
187- & mut self ,
188- ectx : & mut EvalContext < ' a , ' mir , ' tcx , M > ,
189- val : Self :: V ,
190- field : usize ,
191- ) -> EvalResult < ' tcx > ;
192-
193- // A chance for the visitor to do special (different or more efficient) handling for some
194- // array types. Return `true` if the value was handled and we should return.
181+ // Recursie actions, ready to be overloaded.
182+ /// Visit the current value, dispatching as appropriate to more speicalized visitors.
195183 #[ inline]
196- fn handle_array ( & mut self , _ectx : & EvalContext < ' a , ' mir , ' tcx , M > )
197- -> EvalResult < ' tcx , bool >
184+ fn visit_value ( & mut self , ectx : & mut EvalContext < ' a , ' mir , ' tcx , M > )
185+ -> EvalResult < ' tcx >
198186 {
199- Ok ( false )
187+ self . walk_value ( ectx )
200188 }
201-
202- // Execute visitor on the current value. Used for recursing.
189+ /// Visit the current value as an array.
203190 #[ inline]
204- fn visit ( & mut self , ectx : & mut EvalContext < ' a , ' mir , ' tcx , M > )
191+ fn visit_array ( & mut self , ectx : & mut EvalContext < ' a , ' mir , ' tcx , M > )
205192 -> EvalResult < ' tcx >
206193 {
207- ectx . walk_value ( self )
194+ self . walk_array ( ectx )
208195 }
196+ /// Called each time we recurse down to a field of the value, to (a) let
197+ /// the visitor change its internal state (recording the new current value),
198+ /// and (b) let the visitor track the "stack" of fields that we descended below.
199+ fn visit_field (
200+ & mut self ,
201+ ectx : & mut EvalContext < ' a , ' mir , ' tcx , M > ,
202+ val : Self :: V ,
203+ field : usize ,
204+ ) -> EvalResult < ' tcx > ;
209205
210- // Actions on the leaves.
206+ // Actions on the leaves, ready to be overloaded.
207+ #[ inline]
211208 fn visit_uninhabited ( & mut self , _ectx : & mut EvalContext < ' a , ' mir , ' tcx , M > )
212209 -> EvalResult < ' tcx >
213210 { Ok ( ( ) ) }
211+ #[ inline]
214212 fn visit_scalar ( & mut self , _ectx : & mut EvalContext < ' a , ' mir , ' tcx , M > , _layout : & layout:: Scalar )
215213 -> EvalResult < ' tcx >
216214 { Ok ( ( ) ) }
215+ #[ inline]
217216 fn visit_primitive ( & mut self , _ectx : & mut EvalContext < ' a , ' mir , ' tcx , M > )
218217 -> EvalResult < ' tcx >
219218 { Ok ( ( ) ) }
220- }
221219
222- impl < ' a , ' mir , ' tcx , M : Machine < ' a , ' mir , ' tcx > > EvalContext < ' a , ' mir , ' tcx , M > {
223- pub fn walk_value < V : ValueVisitor < ' a , ' mir , ' tcx , M > > (
224- & mut self ,
225- v : & mut V ,
226- ) -> EvalResult < ' tcx > {
227- trace ! ( "walk_value: {:?}" , v) ;
220+ // Default recursors. Not meant to be overloaded.
221+ fn walk_array ( & mut self , ectx : & mut EvalContext < ' a , ' mir , ' tcx , M > )
222+ -> EvalResult < ' tcx >
223+ {
224+ // Let's get an mplace first.
225+ let mplace = if self . layout ( ) . is_zst ( ) {
226+ // it's a ZST, the memory content cannot matter
227+ MPlaceTy :: dangling ( self . layout ( ) , & ectx)
228+ } else {
229+ // non-ZST array/slice/str cannot be immediate
230+ self . value ( ) . to_mem_place ( ectx) ?
231+ } ;
232+ // Now iterate over it.
233+ for ( i, field) in ectx. mplace_array_fields ( mplace) ?. enumerate ( ) {
234+ self . visit_field ( ectx, Value :: from_mem_place ( field?) , i) ?;
235+ }
236+ Ok ( ( ) )
237+ }
238+ fn walk_value ( & mut self , ectx : & mut EvalContext < ' a , ' mir , ' tcx , M > )
239+ -> EvalResult < ' tcx >
240+ {
241+ trace ! ( "walk_value: {:?}" , self ) ;
228242
229243 // If this is a multi-variant layout, we have find the right one and proceed with that.
230244 // (No benefit from making this recursion, but it is equivalent to that.)
231- match v . layout ( ) . variants {
245+ match self . layout ( ) . variants {
232246 layout:: Variants :: NicheFilling { .. } |
233247 layout:: Variants :: Tagged { .. } => {
234- let ( inner, idx) = v . value ( ) . project_downcast ( self ) ?;
248+ let ( inner, idx) = self . value ( ) . project_downcast ( ectx ) ?;
235249 trace ! ( "variant layout: {:#?}" , inner. layout( ) ) ;
236250 // recurse with the inner type
237- return v . visit_field ( self , inner, idx) ;
251+ return self . visit_field ( ectx , inner, idx) ;
238252 }
239253 layout:: Variants :: Single { .. } => { }
240254 }
241255
242256 // Even for single variants, we might be able to get a more refined type:
243257 // If it is a trait object, switch to the actual type that was used to create it.
244- match v . layout ( ) . ty . sty {
258+ match self . layout ( ) . ty . sty {
245259 ty:: Dynamic ( ..) => {
246260 // immediate trait objects are not a thing
247- let dest = v . value ( ) . to_mem_place ( self ) ?;
248- let inner = self . unpack_dyn_trait ( dest) ?. 1 ;
261+ let dest = self . value ( ) . to_mem_place ( ectx ) ?;
262+ let inner = ectx . unpack_dyn_trait ( dest) ?. 1 ;
249263 trace ! ( "dyn object layout: {:#?}" , inner. layout) ;
250264 // recurse with the inner type
251- return v . visit_field ( self , Value :: from_mem_place ( inner) , 0 ) ;
265+ return self . visit_field ( ectx , Value :: from_mem_place ( inner) , 0 ) ;
252266 } ,
253267 _ => { } ,
254268 } ;
@@ -260,12 +274,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
260274 // FIXME: We could avoid some redundant checks here. For newtypes wrapping
261275 // scalars, we do the same check on every "level" (e.g. first we check
262276 // MyNewtype and then the scalar in there).
263- match v . layout ( ) . abi {
277+ match self . layout ( ) . abi {
264278 layout:: Abi :: Uninhabited => {
265- v . visit_uninhabited ( self ) ?;
279+ self . visit_uninhabited ( ectx ) ?;
266280 }
267281 layout:: Abi :: Scalar ( ref layout) => {
268- v . visit_scalar ( self , layout) ?;
282+ self . visit_scalar ( ectx , layout) ?;
269283 }
270284 // FIXME: Should we do something for ScalarPair? Vector?
271285 _ => { }
@@ -276,17 +290,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
276290 // so we check them separately and before aggregate handling.
277291 // It is CRITICAL that we get this check right, or we might be
278292 // validating the wrong thing!
279- let primitive = match v . layout ( ) . fields {
293+ let primitive = match self . layout ( ) . fields {
280294 // Primitives appear as Union with 0 fields -- except for Boxes and fat pointers.
281295 layout:: FieldPlacement :: Union ( 0 ) => true ,
282- _ => v . layout ( ) . ty . builtin_deref ( true ) . is_some ( ) ,
296+ _ => self . layout ( ) . ty . builtin_deref ( true ) . is_some ( ) ,
283297 } ;
284298 if primitive {
285- return v . visit_primitive ( self ) ;
299+ return self . visit_primitive ( ectx ) ;
286300 }
287301
288302 // Proceed into the fields.
289- match v . layout ( ) . fields {
303+ match self . layout ( ) . fields {
290304 layout:: FieldPlacement :: Union ( fields) => {
291305 // Empty unions are not accepted by rustc. That's great, it means we can
292306 // use that as an unambiguous signal for detecting primitives. Make sure
@@ -298,26 +312,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
298312 } ,
299313 layout:: FieldPlacement :: Arbitrary { ref offsets, .. } => {
300314 for i in 0 ..offsets. len ( ) {
301- let val = v . value ( ) . project_field ( self , i as u64 ) ?;
302- v . visit_field ( self , val, i) ?;
315+ let val = self . value ( ) . project_field ( ectx , i as u64 ) ?;
316+ self . visit_field ( ectx , val, i) ?;
303317 }
304318 } ,
305319 layout:: FieldPlacement :: Array { .. } => {
306- if !v. handle_array ( self ) ? {
307- // We still have to work!
308- // Let's get an mplace first.
309- let mplace = if v. layout ( ) . is_zst ( ) {
310- // it's a ZST, the memory content cannot matter
311- MPlaceTy :: dangling ( v. layout ( ) , & self )
312- } else {
313- // non-ZST array/slice/str cannot be immediate
314- v. value ( ) . to_mem_place ( self ) ?
315- } ;
316- // Now iterate over it.
317- for ( i, field) in self . mplace_array_fields ( mplace) ?. enumerate ( ) {
318- v. visit_field ( self , Value :: from_mem_place ( field?) , i) ?;
319- }
320- }
320+ self . visit_array ( ectx) ?;
321321 }
322322 }
323323 Ok ( ( ) )
0 commit comments