@@ -280,3 +280,277 @@ pub enum LvalueContext {
280280 // Consumed as part of an operand
281281 Consume ,
282282}
283+
284+ pub trait MutVisitor < ' tcx > {
285+ // Override these, and call `self.super_xxx` to revert back to the
286+ // default behavior.
287+
288+ fn visit_mir ( & mut self , mir : & mut Mir < ' tcx > ) {
289+ self . super_mir ( mir) ;
290+ }
291+
292+ fn visit_basic_block_data ( & mut self ,
293+ block : BasicBlock ,
294+ data : & mut BasicBlockData < ' tcx > ) {
295+ self . super_basic_block_data ( block, data) ;
296+ }
297+
298+ fn visit_statement ( & mut self ,
299+ block : BasicBlock ,
300+ statement : & mut Statement < ' tcx > ) {
301+ self . super_statement ( block, statement) ;
302+ }
303+
304+ fn visit_assign ( & mut self ,
305+ block : BasicBlock ,
306+ lvalue : & mut Lvalue < ' tcx > ,
307+ rvalue : & mut Rvalue < ' tcx > ) {
308+ self . super_assign ( block, lvalue, rvalue) ;
309+ }
310+
311+ fn visit_terminator ( & mut self ,
312+ block : BasicBlock ,
313+ terminator : & mut Terminator < ' tcx > ) {
314+ self . super_terminator ( block, terminator) ;
315+ }
316+
317+ fn visit_rvalue ( & mut self , rvalue : & mut Rvalue < ' tcx > ) {
318+ self . super_rvalue ( rvalue) ;
319+ }
320+
321+ fn visit_operand ( & mut self , operand : & mut Operand < ' tcx > ) {
322+ self . super_operand ( operand) ;
323+ }
324+
325+ fn visit_lvalue ( & mut self ,
326+ lvalue : & mut Lvalue < ' tcx > ,
327+ context : LvalueContext ) {
328+ self . super_lvalue ( lvalue, context) ;
329+ }
330+
331+ fn visit_branch ( & mut self , source : BasicBlock , target : BasicBlock ) {
332+ self . super_branch ( source, target) ;
333+ }
334+
335+ fn visit_constant ( & mut self , constant : & mut Constant < ' tcx > ) {
336+ self . super_constant ( constant) ;
337+ }
338+
339+ fn visit_literal ( & mut self , literal : & mut Literal < ' tcx > ) {
340+ self . super_literal ( literal) ;
341+ }
342+
343+ fn visit_def_id ( & mut self , def_id : & mut DefId ) {
344+ self . super_def_id ( def_id) ;
345+ }
346+
347+ fn visit_span ( & mut self , span : & mut Span ) {
348+ self . super_span ( span) ;
349+ }
350+
351+ // The `super_xxx` methods comprise the default behavior and are
352+ // not meant to be overidden.
353+
354+ fn super_mir ( & mut self , mir : & mut Mir < ' tcx > ) {
355+ for block in mir. all_basic_blocks ( ) {
356+ let data = mir. basic_block_data_mut ( block) ;
357+ self . visit_basic_block_data ( block, data) ;
358+ }
359+ }
360+
361+ fn super_basic_block_data ( & mut self ,
362+ block : BasicBlock ,
363+ data : & mut BasicBlockData < ' tcx > ) {
364+ for statement in & mut data. statements {
365+ self . visit_statement ( block, statement) ;
366+ }
367+ self . visit_terminator ( block, & mut data. terminator ) ;
368+ }
369+
370+ fn super_statement ( & mut self ,
371+ block : BasicBlock ,
372+ statement : & mut Statement < ' tcx > ) {
373+ self . visit_span ( & mut statement. span ) ;
374+
375+ match statement. kind {
376+ StatementKind :: Assign ( ref mut lvalue, ref mut rvalue) => {
377+ self . visit_assign ( block, lvalue, rvalue) ;
378+ }
379+ StatementKind :: Drop ( _, ref mut lvalue) => {
380+ self . visit_lvalue ( lvalue, LvalueContext :: Drop ) ;
381+ }
382+ }
383+ }
384+
385+ fn super_assign ( & mut self ,
386+ _block : BasicBlock ,
387+ lvalue : & mut Lvalue < ' tcx > ,
388+ rvalue : & mut Rvalue < ' tcx > ) {
389+ self . visit_lvalue ( lvalue, LvalueContext :: Store ) ;
390+ self . visit_rvalue ( rvalue) ;
391+ }
392+
393+ fn super_terminator ( & mut self ,
394+ block : BasicBlock ,
395+ terminator : & mut Terminator < ' tcx > ) {
396+ match * terminator {
397+ Terminator :: Goto { target } |
398+ Terminator :: Panic { target } => {
399+ self . visit_branch ( block, target) ;
400+ }
401+
402+ Terminator :: If { ref mut cond, ref mut targets } => {
403+ self . visit_operand ( cond) ;
404+ for & target in targets. as_slice ( ) {
405+ self . visit_branch ( block, target) ;
406+ }
407+ }
408+
409+ Terminator :: Switch { ref mut discr, adt_def : _, ref targets } => {
410+ self . visit_lvalue ( discr, LvalueContext :: Inspect ) ;
411+ for & target in targets {
412+ self . visit_branch ( block, target) ;
413+ }
414+ }
415+
416+ Terminator :: SwitchInt { ref mut discr, switch_ty : _, values : _, ref targets } => {
417+ self . visit_lvalue ( discr, LvalueContext :: Inspect ) ;
418+ for & target in targets {
419+ self . visit_branch ( block, target) ;
420+ }
421+ }
422+
423+ Terminator :: Diverge |
424+ Terminator :: Return => {
425+ }
426+
427+ Terminator :: Call { ref mut data, ref mut targets } => {
428+ self . visit_lvalue ( & mut data. destination , LvalueContext :: Store ) ;
429+ self . visit_operand ( & mut data. func ) ;
430+ for arg in & mut data. args {
431+ self . visit_operand ( arg) ;
432+ }
433+ for & target in targets. as_slice ( ) {
434+ self . visit_branch ( block, target) ;
435+ }
436+ }
437+ }
438+ }
439+
440+ fn super_rvalue ( & mut self , rvalue : & mut Rvalue < ' tcx > ) {
441+ match * rvalue {
442+ Rvalue :: Use ( ref mut operand) => {
443+ self . visit_operand ( operand) ;
444+ }
445+
446+ Rvalue :: Repeat ( ref mut value, ref mut len) => {
447+ self . visit_operand ( value) ;
448+ self . visit_constant ( len) ;
449+ }
450+
451+ Rvalue :: Ref ( r, bk, ref mut path) => {
452+ self . visit_lvalue ( path, LvalueContext :: Borrow {
453+ region : r,
454+ kind : bk
455+ } ) ;
456+ }
457+
458+ Rvalue :: Len ( ref mut path) => {
459+ self . visit_lvalue ( path, LvalueContext :: Inspect ) ;
460+ }
461+
462+ Rvalue :: Cast ( _, ref mut operand, _) => {
463+ self . visit_operand ( operand) ;
464+ }
465+
466+ Rvalue :: BinaryOp ( _, ref mut lhs, ref mut rhs) => {
467+ self . visit_operand ( lhs) ;
468+ self . visit_operand ( rhs) ;
469+ }
470+
471+ Rvalue :: UnaryOp ( _, ref mut op) => {
472+ self . visit_operand ( op) ;
473+ }
474+
475+ Rvalue :: Box ( _) => {
476+ }
477+
478+ Rvalue :: Aggregate ( ref mut kind, ref mut operands) => {
479+ match * kind {
480+ AggregateKind :: Closure ( ref mut def_id, _) => {
481+ self . visit_def_id ( def_id) ;
482+ }
483+ _ => { /* nothing to do */ }
484+ }
485+
486+ for operand in & mut operands[ ..] {
487+ self . visit_operand ( operand) ;
488+ }
489+ }
490+
491+ Rvalue :: Slice { ref mut input, from_start, from_end } => {
492+ self . visit_lvalue ( input, LvalueContext :: Slice {
493+ from_start : from_start,
494+ from_end : from_end,
495+ } ) ;
496+ }
497+
498+ Rvalue :: InlineAsm ( _) => {
499+ }
500+ }
501+ }
502+
503+ fn super_operand ( & mut self , operand : & mut Operand < ' tcx > ) {
504+ match * operand {
505+ Operand :: Consume ( ref mut lvalue) => {
506+ self . visit_lvalue ( lvalue, LvalueContext :: Consume ) ;
507+ }
508+ Operand :: Constant ( ref mut constant) => {
509+ self . visit_constant ( constant) ;
510+ }
511+ }
512+ }
513+
514+ fn super_lvalue ( & mut self ,
515+ lvalue : & mut Lvalue < ' tcx > ,
516+ _context : LvalueContext ) {
517+ match * lvalue {
518+ Lvalue :: Var ( _) |
519+ Lvalue :: Temp ( _) |
520+ Lvalue :: Arg ( _) |
521+ Lvalue :: ReturnPointer => {
522+ }
523+ Lvalue :: Static ( ref mut def_id) => {
524+ self . visit_def_id ( def_id) ;
525+ }
526+ Lvalue :: Projection ( ref mut proj) => {
527+ self . visit_lvalue ( & mut proj. base , LvalueContext :: Projection ) ;
528+ }
529+ }
530+ }
531+
532+ fn super_branch ( & mut self , _source : BasicBlock , _target : BasicBlock ) {
533+ }
534+
535+ fn super_constant ( & mut self , constant : & mut Constant < ' tcx > ) {
536+ self . visit_span ( & mut constant. span ) ;
537+ self . visit_literal ( & mut constant. literal ) ;
538+ }
539+
540+ fn super_literal ( & mut self , literal : & mut Literal < ' tcx > ) {
541+ match * literal {
542+ Literal :: Item { ref mut def_id, .. } => {
543+ self . visit_def_id ( def_id) ;
544+ } ,
545+ Literal :: Value { .. } => {
546+ // Nothing to do
547+ }
548+ }
549+ }
550+
551+ fn super_def_id ( & mut self , _def_id : & mut DefId ) {
552+ }
553+
554+ fn super_span ( & mut self , _span : & mut Span ) {
555+ }
556+ }
0 commit comments