]> git.lizzy.rs Git - rust.git/blob - src/librustc/mir/visit.rs
Changed usages of `mir` in librustc::mir and librustc_mir to `body`
[rust.git] / src / librustc / mir / visit.rs
1 use crate::ty::subst::SubstsRef;
2 use crate::ty::{CanonicalUserTypeAnnotation, ClosureSubsts, GeneratorSubsts, Ty};
3 use crate::mir::*;
4 use syntax_pos::Span;
5
6 // # The MIR Visitor
7 //
8 // ## Overview
9 //
10 // There are two visitors, one for immutable and one for mutable references,
11 // but both are generated by the following macro. The code is written according
12 // to the following conventions:
13 //
14 // - introduce a `visit_foo` and a `super_foo` method for every MIR type
15 // - `visit_foo`, by default, calls `super_foo`
16 // - `super_foo`, by default, destructures the `foo` and calls `visit_foo`
17 //
18 // This allows you as a user to override `visit_foo` for types are
19 // interested in, and invoke (within that method) call
20 // `self.super_foo` to get the default behavior. Just as in an OO
21 // language, you should never call `super` methods ordinarily except
22 // in that circumstance.
23 //
24 // For the most part, we do not destructure things external to the
25 // MIR, e.g., types, spans, etc, but simply visit them and stop. This
26 // avoids duplication with other visitors like `TypeFoldable`.
27 //
28 // ## Updating
29 //
30 // The code is written in a very deliberate style intended to minimize
31 // the chance of things being overlooked. You'll notice that we always
32 // use pattern matching to reference fields and we ensure that all
33 // matches are exhaustive.
34 //
35 // For example, the `super_basic_block_data` method begins like this:
36 //
37 // ```rust
38 // fn super_basic_block_data(&mut self,
39 //                           block: BasicBlock,
40 //                           data: & $($mutability)? BasicBlockData<'tcx>) {
41 //     let BasicBlockData {
42 //         statements,
43 //         terminator,
44 //         is_cleanup: _
45 //     } = *data;
46 //
47 //     for statement in statements {
48 //         self.visit_statement(block, statement);
49 //     }
50 //
51 //     ...
52 // }
53 // ```
54 //
55 // Here we used `let BasicBlockData { <fields> } = *data` deliberately,
56 // rather than writing `data.statements` in the body. This is because if one
57 // adds a new field to `BasicBlockData`, one will be forced to revise this code,
58 // and hence one will (hopefully) invoke the correct visit methods (if any).
59 //
60 // For this to work, ALL MATCHES MUST BE EXHAUSTIVE IN FIELDS AND VARIANTS.
61 // That means you never write `..` to skip over fields, nor do you write `_`
62 // to skip over variants in a `match`.
63 //
64 // The only place that `_` is acceptable is to match a field (or
65 // variant argument) that does not require visiting, as in
66 // `is_cleanup` above.
67
68 macro_rules! make_mir_visitor {
69     ($visitor_trait_name:ident, $($mutability:ident)?) => {
70         pub trait $visitor_trait_name<'tcx> {
71             // Override these, and call `self.super_xxx` to revert back to the
72             // default behavior.
73
74             fn visit_body(&mut self, body: & $($mutability)? Body<'tcx>) {
75                 self.super_body(body);
76             }
77
78             fn visit_basic_block_data(&mut self,
79                                       block: BasicBlock,
80                                       data: & $($mutability)? BasicBlockData<'tcx>) {
81                 self.super_basic_block_data(block, data);
82             }
83
84             fn visit_source_scope_data(&mut self,
85                                            scope_data: & $($mutability)? SourceScopeData) {
86                 self.super_source_scope_data(scope_data);
87             }
88
89             fn visit_statement(&mut self,
90                                statement: & $($mutability)? Statement<'tcx>,
91                                location: Location) {
92                 self.super_statement(statement, location);
93             }
94
95             fn visit_assign(&mut self,
96                             place: & $($mutability)? Place<'tcx>,
97                             rvalue: & $($mutability)? Rvalue<'tcx>,
98                             location: Location) {
99                 self.super_assign(place, rvalue, location);
100             }
101
102             fn visit_terminator(&mut self,
103                                 terminator: & $($mutability)? Terminator<'tcx>,
104                                 location: Location) {
105                 self.super_terminator(terminator, location);
106             }
107
108             fn visit_terminator_kind(&mut self,
109                                      kind: & $($mutability)? TerminatorKind<'tcx>,
110                                      location: Location) {
111                 self.super_terminator_kind(kind, location);
112             }
113
114             fn visit_assert_message(&mut self,
115                                     msg: & $($mutability)? AssertMessage<'tcx>,
116                                     location: Location) {
117                 self.super_assert_message(msg, location);
118             }
119
120             fn visit_rvalue(&mut self,
121                             rvalue: & $($mutability)? Rvalue<'tcx>,
122                             location: Location) {
123                 self.super_rvalue(rvalue, location);
124             }
125
126             fn visit_operand(&mut self,
127                              operand: & $($mutability)? Operand<'tcx>,
128                              location: Location) {
129                 self.super_operand(operand, location);
130             }
131
132             fn visit_ascribe_user_ty(&mut self,
133                                      place: & $($mutability)? Place<'tcx>,
134                                      variance: & $($mutability)? ty::Variance,
135                                      user_ty: & $($mutability)? UserTypeProjection,
136                                      location: Location) {
137                 self.super_ascribe_user_ty(place, variance, user_ty, location);
138             }
139
140             fn visit_retag(&mut self,
141                            kind: & $($mutability)? RetagKind,
142                            place: & $($mutability)? Place<'tcx>,
143                            location: Location) {
144                 self.super_retag(kind, place, location);
145             }
146
147             fn visit_place(&mut self,
148                             place: & $($mutability)? Place<'tcx>,
149                             context: PlaceContext,
150                             location: Location) {
151                 self.super_place(place, context, location);
152             }
153
154             fn visit_place_base(&mut self,
155                                 place_base: & $($mutability)? PlaceBase<'tcx>,
156                                 context: PlaceContext,
157                                 location: Location) {
158                 self.super_place_base(place_base, context, location);
159             }
160
161             fn visit_projection(&mut self,
162                                 place: & $($mutability)? Projection<'tcx>,
163                                 context: PlaceContext,
164                                 location: Location) {
165                 self.super_projection(place, context, location);
166             }
167
168             fn visit_constant(&mut self,
169                               constant: & $($mutability)? Constant<'tcx>,
170                               location: Location) {
171                 self.super_constant(constant, location);
172             }
173
174             fn visit_span(&mut self,
175                           span: & $($mutability)? Span) {
176                 self.super_span(span);
177             }
178
179             fn visit_source_info(&mut self,
180                                  source_info: & $($mutability)? SourceInfo) {
181                 self.super_source_info(source_info);
182             }
183
184             fn visit_ty(&mut self,
185                         ty: $(& $mutability)? Ty<'tcx>,
186                         _: TyContext) {
187                 self.super_ty(ty);
188             }
189
190             fn visit_user_type_projection(
191                 &mut self,
192                 ty: & $($mutability)? UserTypeProjection,
193             ) {
194                 self.super_user_type_projection(ty);
195             }
196
197             fn visit_user_type_annotation(
198                 &mut self,
199                 index: UserTypeAnnotationIndex,
200                 ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
201             ) {
202                 self.super_user_type_annotation(index, ty);
203             }
204
205             fn visit_region(&mut self,
206                             region: & $($mutability)? ty::Region<'tcx>,
207                             _: Location) {
208                 self.super_region(region);
209             }
210
211             fn visit_const(&mut self,
212                            constant: & $($mutability)? &'tcx ty::Const<'tcx>,
213                            _: Location) {
214                 self.super_const(constant);
215             }
216
217             fn visit_substs(&mut self,
218                             substs: & $($mutability)? SubstsRef<'tcx>,
219                             _: Location) {
220                 self.super_substs(substs);
221             }
222
223             fn visit_closure_substs(&mut self,
224                                     substs: & $($mutability)? ClosureSubsts<'tcx>,
225                                     _: Location) {
226                 self.super_closure_substs(substs);
227             }
228
229             fn visit_generator_substs(&mut self,
230                                       substs: & $($mutability)? GeneratorSubsts<'tcx>,
231                                     _: Location) {
232                 self.super_generator_substs(substs);
233             }
234
235             fn visit_local_decl(&mut self,
236                                 local: Local,
237                                 local_decl: & $($mutability)? LocalDecl<'tcx>) {
238                 self.super_local_decl(local, local_decl);
239             }
240
241             fn visit_local(&mut self,
242                             _local: & $($mutability)? Local,
243                             _context: PlaceContext,
244                             _location: Location) {
245             }
246
247             fn visit_source_scope(&mut self,
248                                       scope: & $($mutability)? SourceScope) {
249                 self.super_source_scope(scope);
250             }
251
252             // The `super_xxx` methods comprise the default behavior and are
253             // not meant to be overridden.
254
255             fn super_body(&mut self,
256                          body: & $($mutability)? Body<'tcx>) {
257                 if let Some(yield_ty) = &$($mutability)? body.yield_ty {
258                     self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
259                         span: body.span,
260                         scope: OUTERMOST_SOURCE_SCOPE,
261                     }));
262                 }
263
264                 // for best performance, we want to use an iterator rather
265                 // than a for-loop, to avoid calling `body::Body::invalidate` for
266                 // each basic block.
267                 macro_rules! basic_blocks {
268                     (mut) => (body.basic_blocks_mut().iter_enumerated_mut());
269                     () => (body.basic_blocks().iter_enumerated());
270                 };
271                 for (bb, data) in basic_blocks!($($mutability)?) {
272                     self.visit_basic_block_data(bb, data);
273                 }
274
275                 for scope in &$($mutability)? body.source_scopes {
276                     self.visit_source_scope_data(scope);
277                 }
278
279                 self.visit_ty(&$($mutability)? body.return_ty(), TyContext::ReturnTy(SourceInfo {
280                     span: body.span,
281                     scope: OUTERMOST_SOURCE_SCOPE,
282                 }));
283
284                 for local in body.local_decls.indices() {
285                     self.visit_local_decl(local, & $($mutability)? body.local_decls[local]);
286                 }
287
288                 macro_rules! type_annotations {
289                     (mut) => (body.user_type_annotations.iter_enumerated_mut());
290                     () => (body.user_type_annotations.iter_enumerated());
291                 };
292
293                 for (index, annotation) in type_annotations!($($mutability)?) {
294                     self.visit_user_type_annotation(
295                         index, annotation
296                     );
297                 }
298
299                 self.visit_span(&$($mutability)? body.span);
300             }
301
302             fn super_basic_block_data(&mut self,
303                                       block: BasicBlock,
304                                       data: & $($mutability)? BasicBlockData<'tcx>) {
305                 let BasicBlockData {
306                     statements,
307                     terminator,
308                     is_cleanup: _
309                 } = data;
310
311                 let mut index = 0;
312                 for statement in statements {
313                     let location = Location { block: block, statement_index: index };
314                     self.visit_statement(statement, location);
315                     index += 1;
316                 }
317
318                 if let Some(terminator) = terminator {
319                     let location = Location { block: block, statement_index: index };
320                     self.visit_terminator(terminator, location);
321                 }
322             }
323
324             fn super_source_scope_data(&mut self, scope_data: & $($mutability)? SourceScopeData) {
325                 let SourceScopeData {
326                     span,
327                     parent_scope,
328                 } = scope_data;
329
330                 self.visit_span(span);
331                 if let Some(parent_scope) = parent_scope {
332                     self.visit_source_scope(parent_scope);
333                 }
334             }
335
336             fn super_statement(&mut self,
337                                statement: & $($mutability)? Statement<'tcx>,
338                                location: Location) {
339                 let Statement {
340                     source_info,
341                     kind,
342                 } = statement;
343
344                 self.visit_source_info(source_info);
345                 match kind {
346                     StatementKind::Assign(place, rvalue) => {
347                         self.visit_assign(place, rvalue, location);
348                     }
349                     StatementKind::FakeRead(_, place) => {
350                         self.visit_place(
351                             place,
352                             PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
353                             location
354                         );
355                     }
356                     StatementKind::SetDiscriminant { place, .. } => {
357                         self.visit_place(
358                             place,
359                             PlaceContext::MutatingUse(MutatingUseContext::Store),
360                             location
361                         );
362                     }
363                     StatementKind::StorageLive(local) => {
364                         self.visit_local(
365                             local,
366                             PlaceContext::NonUse(NonUseContext::StorageLive),
367                             location
368                         );
369                     }
370                     StatementKind::StorageDead(local) => {
371                         self.visit_local(
372                             local,
373                             PlaceContext::NonUse(NonUseContext::StorageDead),
374                             location
375                         );
376                     }
377                     StatementKind::InlineAsm(asm) => {
378                         for output in & $($mutability)? asm.outputs[..] {
379                             self.visit_place(
380                                 output,
381                                 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
382                                 location
383                             );
384                         }
385                         for (span, input) in & $($mutability)? asm.inputs[..] {
386                             self.visit_span(span);
387                             self.visit_operand(input, location);
388                         }
389                     }
390                     StatementKind::Retag(kind, place) => {
391                         self.visit_retag(kind, place, location);
392                     }
393                     StatementKind::AscribeUserType(place, variance, user_ty) => {
394                         self.visit_ascribe_user_ty(place, variance, user_ty, location);
395                     }
396                     StatementKind::Nop => {}
397                 }
398             }
399
400             fn super_assign(&mut self,
401                             place: &$($mutability)? Place<'tcx>,
402                             rvalue: &$($mutability)? Rvalue<'tcx>,
403                             location: Location) {
404                 self.visit_place(
405                     place,
406                     PlaceContext::MutatingUse(MutatingUseContext::Store),
407                     location
408                 );
409                 self.visit_rvalue(rvalue, location);
410             }
411
412             fn super_terminator(&mut self,
413                                 terminator: &$($mutability)? Terminator<'tcx>,
414                                 location: Location) {
415                 let Terminator { source_info, kind } = terminator;
416
417                 self.visit_source_info(source_info);
418                 self.visit_terminator_kind(kind, location);
419             }
420
421             fn super_terminator_kind(&mut self,
422                                      kind: & $($mutability)? TerminatorKind<'tcx>,
423                                      source_location: Location) {
424                 match kind {
425                     TerminatorKind::Goto { .. } |
426                     TerminatorKind::Resume |
427                     TerminatorKind::Abort |
428                     TerminatorKind::Return |
429                     TerminatorKind::GeneratorDrop |
430                     TerminatorKind::Unreachable |
431                     TerminatorKind::FalseEdges { .. } |
432                     TerminatorKind::FalseUnwind { .. } => {
433                     }
434
435                     TerminatorKind::SwitchInt {
436                         discr,
437                         switch_ty,
438                         values: _,
439                         targets: _
440                     } => {
441                         self.visit_operand(discr, source_location);
442                         self.visit_ty(switch_ty, TyContext::Location(source_location));
443                     }
444
445                     TerminatorKind::Drop {
446                         location,
447                         target: _,
448                         unwind: _,
449                     } => {
450                         self.visit_place(
451                             location,
452                             PlaceContext::MutatingUse(MutatingUseContext::Drop),
453                             source_location
454                         );
455                     }
456
457                     TerminatorKind::DropAndReplace {
458                         location,
459                         value,
460                         target: _,
461                         unwind: _,
462                     } => {
463                         self.visit_place(
464                             location,
465                             PlaceContext::MutatingUse(MutatingUseContext::Drop),
466                             source_location
467                         );
468                         self.visit_operand(value, source_location);
469                     }
470
471                     TerminatorKind::Call {
472                         func,
473                         args,
474                         destination,
475                         cleanup: _,
476                         from_hir_call: _,
477                     } => {
478                         self.visit_operand(func, source_location);
479                         for arg in args {
480                             self.visit_operand(arg, source_location);
481                         }
482                         if let Some((destination, _)) = destination {
483                             self.visit_place(
484                                 destination,
485                                 PlaceContext::MutatingUse(MutatingUseContext::Call),
486                                 source_location
487                             );
488                         }
489                     }
490
491                     TerminatorKind::Assert {
492                         cond,
493                         expected: _,
494                         msg,
495                         target: _,
496                         cleanup: _,
497                     } => {
498                         self.visit_operand(cond, source_location);
499                         self.visit_assert_message(msg, source_location);
500                     }
501
502                     TerminatorKind::Yield {
503                         value,
504                         resume: _,
505                         drop: _,
506                     } => {
507                         self.visit_operand(value, source_location);
508                     }
509
510                 }
511             }
512
513             fn super_assert_message(&mut self,
514                                     msg: & $($mutability)? AssertMessage<'tcx>,
515                                     location: Location) {
516                 use crate::mir::interpret::InterpError::*;
517                 if let BoundsCheck { len, index } = msg {
518                     self.visit_operand(len, location);
519                     self.visit_operand(index, location);
520                 }
521             }
522
523             fn super_rvalue(&mut self,
524                             rvalue: & $($mutability)? Rvalue<'tcx>,
525                             location: Location) {
526                 match rvalue {
527                     Rvalue::Use(operand) => {
528                         self.visit_operand(operand, location);
529                     }
530
531                     Rvalue::Repeat(value, _) => {
532                         self.visit_operand(value, location);
533                     }
534
535                     Rvalue::Ref(r, bk, path) => {
536                         self.visit_region(r, location);
537                         let ctx = match bk {
538                             BorrowKind::Shared => PlaceContext::NonMutatingUse(
539                                 NonMutatingUseContext::SharedBorrow
540                             ),
541                             BorrowKind::Shallow => PlaceContext::NonMutatingUse(
542                                 NonMutatingUseContext::ShallowBorrow
543                             ),
544                             BorrowKind::Unique => PlaceContext::NonMutatingUse(
545                                 NonMutatingUseContext::UniqueBorrow
546                             ),
547                             BorrowKind::Mut { .. } =>
548                                 PlaceContext::MutatingUse(MutatingUseContext::Borrow),
549                         };
550                         self.visit_place(path, ctx, location);
551                     }
552
553                     Rvalue::Len(path) => {
554                         self.visit_place(
555                             path,
556                             PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
557                             location
558                         );
559                     }
560
561                     Rvalue::Cast(_cast_kind, operand, ty) => {
562                         self.visit_operand(operand, location);
563                         self.visit_ty(ty, TyContext::Location(location));
564                     }
565
566                     Rvalue::BinaryOp(_bin_op, lhs, rhs)
567                     | Rvalue::CheckedBinaryOp(_bin_op, lhs, rhs) => {
568                         self.visit_operand(lhs, location);
569                         self.visit_operand(rhs, location);
570                     }
571
572                     Rvalue::UnaryOp(_un_op, op) => {
573                         self.visit_operand(op, location);
574                     }
575
576                     Rvalue::Discriminant(place) => {
577                         self.visit_place(
578                             place,
579                             PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
580                             location
581                         );
582                     }
583
584                     Rvalue::NullaryOp(_op, ty) => {
585                         self.visit_ty(ty, TyContext::Location(location));
586                     }
587
588                     Rvalue::Aggregate(kind, operands) => {
589                         let kind = &$($mutability)? **kind;
590                         match kind {
591                             AggregateKind::Array(ty) => {
592                                 self.visit_ty(ty, TyContext::Location(location));
593                             }
594                             AggregateKind::Tuple => {
595                             }
596                             AggregateKind::Adt(
597                                 _adt_def,
598                                 _variant_index,
599                                 substs,
600                                 _user_substs,
601                                 _active_field_index
602                             ) => {
603                                 self.visit_substs(substs, location);
604                             }
605                             AggregateKind::Closure(
606                                 _,
607                                 closure_substs
608                             ) => {
609                                 self.visit_closure_substs(closure_substs, location);
610                             }
611                             AggregateKind::Generator(
612                                 _,
613                                 generator_substs,
614                                 _movability,
615                             ) => {
616                                 self.visit_generator_substs(generator_substs, location);
617                             }
618                         }
619
620                         for operand in operands {
621                             self.visit_operand(operand, location);
622                         }
623                     }
624                 }
625             }
626
627             fn super_operand(&mut self,
628                              operand: & $($mutability)? Operand<'tcx>,
629                              location: Location) {
630                 match operand {
631                     Operand::Copy(place) => {
632                         self.visit_place(
633                             place,
634                             PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
635                             location
636                         );
637                     }
638                     Operand::Move(place) => {
639                         self.visit_place(
640                             place,
641                             PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
642                             location
643                         );
644                     }
645                     Operand::Constant(constant) => {
646                         self.visit_constant(constant, location);
647                     }
648                 }
649             }
650
651             fn super_ascribe_user_ty(&mut self,
652                                      place: & $($mutability)? Place<'tcx>,
653                                      _variance: & $($mutability)? ty::Variance,
654                                      user_ty: & $($mutability)? UserTypeProjection,
655                                      location: Location) {
656                 self.visit_place(
657                     place,
658                     PlaceContext::NonUse(NonUseContext::AscribeUserTy),
659                     location
660                 );
661                 self.visit_user_type_projection(user_ty);
662             }
663
664             fn super_retag(&mut self,
665                            _kind: & $($mutability)? RetagKind,
666                            place: & $($mutability)? Place<'tcx>,
667                            location: Location) {
668                 self.visit_place(
669                     place,
670                     PlaceContext::MutatingUse(MutatingUseContext::Retag),
671                     location,
672                 );
673             }
674
675             fn super_place(&mut self,
676                             place: & $($mutability)? Place<'tcx>,
677                             context: PlaceContext,
678                             location: Location) {
679                 match place {
680                     Place::Base(place_base) => {
681                         self.visit_place_base(place_base, context, location);
682                     }
683                     Place::Projection(proj) => {
684                         let context = if context.is_mutating_use() {
685                             PlaceContext::MutatingUse(MutatingUseContext::Projection)
686                         } else {
687                             PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
688                         };
689
690                         self.visit_projection(proj, context, location);
691                     }
692                 }
693             }
694
695             fn super_place_base(&mut self,
696                                 place_base: & $($mutability)? PlaceBase<'tcx>,
697                                 context: PlaceContext,
698                                 location: Location) {
699                 match place_base {
700                     PlaceBase::Local(local) => {
701                         self.visit_local(local, context, location);
702                     }
703                     PlaceBase::Static(box Static { kind: _, ty }) => {
704                         self.visit_ty(& $($mutability)? *ty, TyContext::Location(location));
705                     }
706                 }
707             }
708
709             fn super_projection(&mut self,
710                                 proj: & $($mutability)? Projection<'tcx>,
711                                 context: PlaceContext,
712                                 location: Location) {
713                 // this is calling `super_place` in preparation for changing `Place` to be
714                 // a struct with a base and a slice of projections. `visit_place` should only ever
715                 // be called for the outermost place now.
716                 self.super_place(& $($mutability)? proj.base, context, location);
717                 match & $($mutability)? proj.elem {
718                     ProjectionElem::Deref => {
719                     }
720                     ProjectionElem::Subslice { from: _, to: _ } => {
721                     }
722                     ProjectionElem::Field(_field, ty) => {
723                         self.visit_ty(ty, TyContext::Location(location));
724                     }
725                     ProjectionElem::Index(local) => {
726                         self.visit_local(
727                             local,
728                             PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
729                             location
730                         );
731                     }
732                     ProjectionElem::ConstantIndex { offset: _,
733                                                     min_length: _,
734                                                     from_end: _ } => {
735                     }
736                     ProjectionElem::Downcast(_name, _variant_index) => {
737                     }
738                 }
739             }
740
741             fn super_local_decl(&mut self,
742                                 local: Local,
743                                 local_decl: & $($mutability)? LocalDecl<'tcx>) {
744                 let LocalDecl {
745                     mutability: _,
746                     ty,
747                     user_ty,
748                     name: _,
749                     source_info,
750                     visibility_scope,
751                     internal: _,
752                     is_user_variable: _,
753                     is_block_tail: _,
754                 } = local_decl;
755
756                 self.visit_ty(ty, TyContext::LocalDecl {
757                     local,
758                     source_info: *source_info,
759                 });
760                 for (user_ty, _) in & $($mutability)? user_ty.contents {
761                     self.visit_user_type_projection(user_ty);
762                 }
763                 self.visit_source_info(source_info);
764                 self.visit_source_scope(visibility_scope);
765             }
766
767             fn super_source_scope(&mut self,
768                                       _scope: & $($mutability)? SourceScope) {
769             }
770
771             fn super_constant(&mut self,
772                               constant: & $($mutability)? Constant<'tcx>,
773                               location: Location) {
774                 let Constant {
775                     span,
776                     ty,
777                     user_ty,
778                     literal,
779                 } = constant;
780
781                 self.visit_span(span);
782                 self.visit_ty(ty, TyContext::Location(location));
783                 drop(user_ty); // no visit method for this
784                 self.visit_const(literal, location);
785             }
786
787             fn super_span(&mut self, _span: & $($mutability)? Span) {
788             }
789
790             fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) {
791                 let SourceInfo {
792                     span,
793                     scope,
794                 } = source_info;
795
796                 self.visit_span(span);
797                 self.visit_source_scope(scope);
798             }
799
800             fn super_user_type_projection(
801                 &mut self,
802                 _ty: & $($mutability)? UserTypeProjection,
803             ) {
804             }
805
806             fn super_user_type_annotation(
807                 &mut self,
808                 _index: UserTypeAnnotationIndex,
809                 ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
810             ) {
811                 self.visit_span(& $($mutability)? ty.span);
812                 self.visit_ty(& $($mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
813             }
814
815             fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {
816             }
817
818             fn super_region(&mut self, _region: & $($mutability)? ty::Region<'tcx>) {
819             }
820
821             fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::Const<'tcx>) {
822             }
823
824             fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {
825             }
826
827             fn super_generator_substs(&mut self,
828                                       _substs: & $($mutability)? GeneratorSubsts<'tcx>) {
829             }
830
831             fn super_closure_substs(&mut self,
832                                     _substs: & $($mutability)? ClosureSubsts<'tcx>) {
833             }
834
835             // Convenience methods
836
837             fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) {
838                 let basic_block = & $($mutability)? body[location.block];
839                 if basic_block.statements.len() == location.statement_index {
840                     if let Some(ref $($mutability)? terminator) = basic_block.terminator {
841                         self.visit_terminator(terminator, location)
842                     }
843                 } else {
844                     let statement = & $($mutability)?
845                         basic_block.statements[location.statement_index];
846                     self.visit_statement(statement, location)
847                 }
848             }
849         }
850     }
851 }
852
853 make_mir_visitor!(Visitor,);
854 make_mir_visitor!(MutVisitor,mut);
855
856 pub trait MirVisitable<'tcx> {
857     fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>);
858 }
859
860 impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
861     fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
862     {
863         visitor.visit_statement(self, location)
864     }
865 }
866
867 impl<'tcx> MirVisitable<'tcx> for Terminator<'tcx> {
868     fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
869     {
870         visitor.visit_terminator(self, location)
871     }
872 }
873
874 impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
875     fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>)
876     {
877         visitor.visit_terminator(self.as_ref().unwrap(), location)
878     }
879 }
880
881 /// Extra information passed to `visit_ty` and friends to give context
882 /// about where the type etc appears.
883 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
884 pub enum TyContext {
885     LocalDecl {
886         /// The index of the local variable we are visiting.
887         local: Local,
888
889         /// The source location where this local variable was declared.
890         source_info: SourceInfo,
891     },
892
893     /// The inferred type of a user type annotation.
894     UserTy(Span),
895
896     /// The return type of the function.
897     ReturnTy(SourceInfo),
898
899     YieldTy(SourceInfo),
900
901     /// A type found at some location.
902     Location(Location),
903 }
904
905 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
906 pub enum NonMutatingUseContext {
907     /// Being inspected in some way, like loading a len.
908     Inspect,
909     /// Consumed as part of an operand.
910     Copy,
911     /// Consumed as part of an operand.
912     Move,
913     /// Shared borrow.
914     SharedBorrow,
915     /// Shallow borrow.
916     ShallowBorrow,
917     /// Unique borrow.
918     UniqueBorrow,
919     /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
920     /// For example, the projection `x.y` is not marked as a mutation in these cases:
921     ///
922     ///     z = x.y;
923     ///     f(&x.y);
924     ///
925     Projection,
926 }
927
928 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
929 pub enum MutatingUseContext {
930     /// Appears as LHS of an assignment.
931     Store,
932     /// Can often be treated as a `Store`, but needs to be separate because
933     /// ASM is allowed to read outputs as well, so a `Store`-`AsmOutput` sequence
934     /// cannot be simplified the way a `Store`-`Store` can be.
935     AsmOutput,
936     /// Destination of a call.
937     Call,
938     /// Being dropped.
939     Drop,
940     /// Mutable borrow.
941     Borrow,
942     /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
943     /// For example, the projection `x.y` is marked as a mutation in these cases:
944     ///
945     ///     x.y = ...;
946     ///     f(&mut x.y);
947     ///
948     Projection,
949     /// Retagging, a "Stacked Borrows" shadow state operation
950     Retag,
951 }
952
953 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
954 pub enum NonUseContext {
955     /// Starting a storage live range.
956     StorageLive,
957     /// Ending a storage live range.
958     StorageDead,
959     /// User type annotation assertions for NLL.
960     AscribeUserTy,
961 }
962
963 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
964 pub enum PlaceContext {
965     NonMutatingUse(NonMutatingUseContext),
966     MutatingUse(MutatingUseContext),
967     NonUse(NonUseContext),
968 }
969
970 impl<'tcx> PlaceContext {
971     /// Returns `true` if this place context represents a drop.
972     pub fn is_drop(&self) -> bool {
973         match *self {
974             PlaceContext::MutatingUse(MutatingUseContext::Drop) => true,
975             _ => false,
976         }
977     }
978
979     /// Returns `true` if this place context represents a borrow.
980     pub fn is_borrow(&self) -> bool {
981         match *self {
982             PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) |
983             PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
984             PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) |
985             PlaceContext::MutatingUse(MutatingUseContext::Borrow) => true,
986             _ => false,
987         }
988     }
989
990     /// Returns `true` if this place context represents a storage live or storage dead marker.
991     pub fn is_storage_marker(&self) -> bool {
992         match *self {
993             PlaceContext::NonUse(NonUseContext::StorageLive) |
994             PlaceContext::NonUse(NonUseContext::StorageDead) => true,
995             _ => false,
996         }
997     }
998
999     /// Returns `true` if this place context represents a storage live marker.
1000     pub fn is_storage_live_marker(&self) -> bool {
1001         match *self {
1002             PlaceContext::NonUse(NonUseContext::StorageLive) => true,
1003             _ => false,
1004         }
1005     }
1006
1007     /// Returns `true` if this place context represents a storage dead marker.
1008     pub fn is_storage_dead_marker(&self) -> bool {
1009         match *self {
1010             PlaceContext::NonUse(NonUseContext::StorageDead) => true,
1011             _ => false,
1012         }
1013     }
1014
1015     /// Returns `true` if this place context represents a use that potentially changes the value.
1016     pub fn is_mutating_use(&self) -> bool {
1017         match *self {
1018             PlaceContext::MutatingUse(..) => true,
1019             _ => false,
1020         }
1021     }
1022
1023     /// Returns `true` if this place context represents a use that does not change the value.
1024     pub fn is_nonmutating_use(&self) -> bool {
1025         match *self {
1026             PlaceContext::NonMutatingUse(..) => true,
1027             _ => false,
1028         }
1029     }
1030
1031     /// Returns `true` if this place context represents a use.
1032     pub fn is_use(&self) -> bool {
1033         match *self {
1034             PlaceContext::NonUse(..) => false,
1035             _ => true,
1036         }
1037     }
1038
1039     /// Returns `true` if this place context represents an assignment statement.
1040     pub fn is_place_assignment(&self) -> bool {
1041         match *self {
1042             PlaceContext::MutatingUse(MutatingUseContext::Store) |
1043             PlaceContext::MutatingUse(MutatingUseContext::Call) |
1044             PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) => true,
1045             _ => false,
1046         }
1047     }
1048 }