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