]> git.lizzy.rs Git - rust.git/blob - src/librustc/mir/visit.rs
Fix invalid associated type rendering in rustdoc
[rust.git] / src / librustc / mir / visit.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use middle::const_val::ConstVal;
12 use hir::def_id::DefId;
13 use ty::subst::Substs;
14 use ty::{ClosureSubsts, Region, Ty};
15 use mir::*;
16 use rustc_const_math::ConstUsize;
17 use rustc_data_structures::indexed_vec::Idx;
18 use syntax_pos::Span;
19
20 // # The MIR Visitor
21 //
22 // ## Overview
23 //
24 // There are two visitors, one for immutable and one for mutable references,
25 // but both are generated by the following macro. The code is written according
26 // to the following conventions:
27 //
28 // - introduce a `visit_foo` and a `super_foo` method for every MIR type
29 // - `visit_foo`, by default, calls `super_foo`
30 // - `super_foo`, by default, destructures the `foo` and calls `visit_foo`
31 //
32 // This allows you as a user to override `visit_foo` for types are
33 // interested in, and invoke (within that method) call
34 // `self.super_foo` to get the default behavior. Just as in an OO
35 // language, you should never call `super` methods ordinarily except
36 // in that circumstance.
37 //
38 // For the most part, we do not destructure things external to the
39 // MIR, e.g. types, spans, etc, but simply visit them and stop. This
40 // avoids duplication with other visitors like `TypeFoldable`.
41 //
42 // ## Updating
43 //
44 // The code is written in a very deliberate style intended to minimize
45 // the chance of things being overlooked. You'll notice that we always
46 // use pattern matching to reference fields and we ensure that all
47 // matches are exhaustive.
48 //
49 // For example, the `super_basic_block_data` method begins like this:
50 //
51 // ```rust
52 // fn super_basic_block_data(&mut self,
53 //                           block: BasicBlock,
54 //                           data: & $($mutability)* BasicBlockData<'tcx>) {
55 //     let BasicBlockData {
56 //         ref $($mutability)* statements,
57 //         ref $($mutability)* terminator,
58 //         is_cleanup: _
59 //     } = *data;
60 //
61 //     for statement in statements {
62 //         self.visit_statement(block, statement);
63 //     }
64 //
65 //     ...
66 // }
67 // ```
68 //
69 // Here we used `let BasicBlockData { <fields> } = *data` deliberately,
70 // rather than writing `data.statements` in the body. This is because if one
71 // adds a new field to `BasicBlockData`, one will be forced to revise this code,
72 // and hence one will (hopefully) invoke the correct visit methods (if any).
73 //
74 // For this to work, ALL MATCHES MUST BE EXHAUSTIVE IN FIELDS AND VARIANTS.
75 // That means you never write `..` to skip over fields, nor do you write `_`
76 // to skip over variants in a `match`.
77 //
78 // The only place that `_` is acceptable is to match a field (or
79 // variant argument) that does not require visiting, as in
80 // `is_cleanup` above.
81
82 macro_rules! make_mir_visitor {
83     ($visitor_trait_name:ident, $($mutability:ident)*) => {
84         pub trait $visitor_trait_name<'tcx> {
85             // Override these, and call `self.super_xxx` to revert back to the
86             // default behavior.
87
88             fn visit_mir(&mut self, mir: & $($mutability)* Mir<'tcx>) {
89                 self.super_mir(mir);
90             }
91
92             fn visit_basic_block_data(&mut self,
93                                       block: BasicBlock,
94                                       data: & $($mutability)* BasicBlockData<'tcx>) {
95                 self.super_basic_block_data(block, data);
96             }
97
98             fn visit_visibility_scope_data(&mut self,
99                                            scope_data: & $($mutability)* VisibilityScopeData) {
100                 self.super_visibility_scope_data(scope_data);
101             }
102
103             fn visit_statement(&mut self,
104                                block: BasicBlock,
105                                statement: & $($mutability)* Statement<'tcx>,
106                                location: Location) {
107                 self.super_statement(block, statement, location);
108             }
109
110             fn visit_assign(&mut self,
111                             block: BasicBlock,
112                             lvalue: & $($mutability)* Lvalue<'tcx>,
113                             rvalue: & $($mutability)* Rvalue<'tcx>,
114                             location: Location) {
115                 self.super_assign(block, lvalue, rvalue, location);
116             }
117
118             fn visit_terminator(&mut self,
119                                 block: BasicBlock,
120                                 terminator: & $($mutability)* Terminator<'tcx>,
121                                 location: Location) {
122                 self.super_terminator(block, terminator, location);
123             }
124
125             fn visit_terminator_kind(&mut self,
126                                      block: BasicBlock,
127                                      kind: & $($mutability)* TerminatorKind<'tcx>,
128                                      location: Location) {
129                 self.super_terminator_kind(block, kind, location);
130             }
131
132             fn visit_assert_message(&mut self,
133                                     msg: & $($mutability)* AssertMessage<'tcx>,
134                                     location: Location) {
135                 self.super_assert_message(msg, location);
136             }
137
138             fn visit_rvalue(&mut self,
139                             rvalue: & $($mutability)* Rvalue<'tcx>,
140                             location: Location) {
141                 self.super_rvalue(rvalue, location);
142             }
143
144             fn visit_operand(&mut self,
145                              operand: & $($mutability)* Operand<'tcx>,
146                              location: Location) {
147                 self.super_operand(operand, location);
148             }
149
150             fn visit_lvalue(&mut self,
151                             lvalue: & $($mutability)* Lvalue<'tcx>,
152                             context: LvalueContext<'tcx>,
153                             location: Location) {
154                 self.super_lvalue(lvalue, context, location);
155             }
156
157             fn visit_static(&mut self,
158                             static_: & $($mutability)* Static<'tcx>,
159                             context: LvalueContext<'tcx>,
160                             location: Location) {
161                 self.super_static(static_, context, location);
162             }
163
164             fn visit_projection(&mut self,
165                                 lvalue: & $($mutability)* LvalueProjection<'tcx>,
166                                 context: LvalueContext<'tcx>,
167                                 location: Location) {
168                 self.super_projection(lvalue, context, location);
169             }
170
171             fn visit_projection_elem(&mut self,
172                                      lvalue: & $($mutability)* LvalueElem<'tcx>,
173                                      context: LvalueContext<'tcx>,
174                                      location: Location) {
175                 self.super_projection_elem(lvalue, context, location);
176             }
177
178             fn visit_branch(&mut self,
179                             source: BasicBlock,
180                             target: BasicBlock) {
181                 self.super_branch(source, target);
182             }
183
184             fn visit_constant(&mut self,
185                               constant: & $($mutability)* Constant<'tcx>,
186                               location: Location) {
187                 self.super_constant(constant, location);
188             }
189
190             fn visit_literal(&mut self,
191                              literal: & $($mutability)* Literal<'tcx>,
192                              location: Location) {
193                 self.super_literal(literal, location);
194             }
195
196             fn visit_def_id(&mut self,
197                             def_id: & $($mutability)* DefId,
198                             _: Location) {
199                 self.super_def_id(def_id);
200             }
201
202             fn visit_span(&mut self,
203                           span: & $($mutability)* Span) {
204                 self.super_span(span);
205             }
206
207             fn visit_source_info(&mut self,
208                                  source_info: & $($mutability)* SourceInfo) {
209                 self.super_source_info(source_info);
210             }
211
212             fn visit_ty(&mut self,
213                         ty: & $($mutability)* Ty<'tcx>) {
214                 self.super_ty(ty);
215             }
216
217             fn visit_substs(&mut self,
218                             substs: & $($mutability)* &'tcx Substs<'tcx>) {
219                 self.super_substs(substs);
220             }
221
222             fn visit_closure_substs(&mut self,
223                                     substs: & $($mutability)* ClosureSubsts<'tcx>) {
224                 self.super_closure_substs(substs);
225             }
226
227             fn visit_const_val(&mut self,
228                                const_val: & $($mutability)* ConstVal,
229                                _: Location) {
230                 self.super_const_val(const_val);
231             }
232
233             fn visit_const_int(&mut self,
234                                const_int: &ConstInt,
235                                _: Location) {
236                 self.super_const_int(const_int);
237             }
238
239             fn visit_const_usize(&mut self,
240                                  const_usize: & $($mutability)* ConstUsize,
241                                  _: Location) {
242                 self.super_const_usize(const_usize);
243             }
244
245             fn visit_local_decl(&mut self,
246                                 local_decl: & $($mutability)* LocalDecl<'tcx>) {
247                 self.super_local_decl(local_decl);
248             }
249
250             fn visit_visibility_scope(&mut self,
251                                       scope: & $($mutability)* VisibilityScope) {
252                 self.super_visibility_scope(scope);
253             }
254
255             // The `super_xxx` methods comprise the default behavior and are
256             // not meant to be overridden.
257
258             fn super_mir(&mut self,
259                          mir: & $($mutability)* Mir<'tcx>) {
260                 for index in 0..mir.basic_blocks().len() {
261                     let block = BasicBlock::new(index);
262                     self.visit_basic_block_data(block, &$($mutability)* mir[block]);
263                 }
264
265                 for scope in &$($mutability)* mir.visibility_scopes {
266                     self.visit_visibility_scope_data(scope);
267                 }
268
269                 self.visit_ty(&$($mutability)* mir.return_ty);
270
271                 for local_decl in &$($mutability)* mir.local_decls {
272                     self.visit_local_decl(local_decl);
273                 }
274
275                 self.visit_span(&$($mutability)* mir.span);
276             }
277
278             fn super_basic_block_data(&mut self,
279                                       block: BasicBlock,
280                                       data: & $($mutability)* BasicBlockData<'tcx>) {
281                 let BasicBlockData {
282                     ref $($mutability)* statements,
283                     ref $($mutability)* terminator,
284                     is_cleanup: _
285                 } = *data;
286
287                 let mut index = 0;
288                 for statement in statements {
289                     let location = Location { block: block, statement_index: index };
290                     self.visit_statement(block, statement, location);
291                     index += 1;
292                 }
293
294                 if let Some(ref $($mutability)* terminator) = *terminator {
295                     let location = Location { block: block, statement_index: index };
296                     self.visit_terminator(block, terminator, location);
297                 }
298             }
299
300             fn super_visibility_scope_data(&mut self,
301                                            scope_data: & $($mutability)* VisibilityScopeData) {
302                 let VisibilityScopeData {
303                     ref $($mutability)* span,
304                     ref $($mutability)* parent_scope,
305                 } = *scope_data;
306
307                 self.visit_span(span);
308                 if let Some(ref $($mutability)* parent_scope) = *parent_scope {
309                     self.visit_visibility_scope(parent_scope);
310                 }
311             }
312
313             fn super_statement(&mut self,
314                                block: BasicBlock,
315                                statement: & $($mutability)* Statement<'tcx>,
316                                location: Location) {
317                 let Statement {
318                     ref $($mutability)* source_info,
319                     ref $($mutability)* kind,
320                 } = *statement;
321
322                 self.visit_source_info(source_info);
323                 match *kind {
324                     StatementKind::Assign(ref $($mutability)* lvalue,
325                                           ref $($mutability)* rvalue) => {
326                         self.visit_assign(block, lvalue, rvalue, location);
327                     }
328                     StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
329                         self.visit_lvalue(lvalue, LvalueContext::Store, location);
330                     }
331                     StatementKind::StorageLive(ref $($mutability)* lvalue) => {
332                         self.visit_lvalue(lvalue, LvalueContext::StorageLive, location);
333                     }
334                     StatementKind::StorageDead(ref $($mutability)* lvalue) => {
335                         self.visit_lvalue(lvalue, LvalueContext::StorageDead, location);
336                     }
337                     StatementKind::InlineAsm { ref $($mutability)* outputs,
338                                                ref $($mutability)* inputs,
339                                                asm: _ } => {
340                         for output in & $($mutability)* outputs[..] {
341                             self.visit_lvalue(output, LvalueContext::Store, location);
342                         }
343                         for input in & $($mutability)* inputs[..] {
344                             self.visit_operand(input, location);
345                         }
346                     }
347                     StatementKind::Nop => {}
348                 }
349             }
350
351             fn super_assign(&mut self,
352                             _block: BasicBlock,
353                             lvalue: &$($mutability)* Lvalue<'tcx>,
354                             rvalue: &$($mutability)* Rvalue<'tcx>,
355                             location: Location) {
356                 self.visit_lvalue(lvalue, LvalueContext::Store, location);
357                 self.visit_rvalue(rvalue, location);
358             }
359
360             fn super_terminator(&mut self,
361                                 block: BasicBlock,
362                                 terminator: &$($mutability)* Terminator<'tcx>,
363                                 location: Location) {
364                 let Terminator {
365                     ref $($mutability)* source_info,
366                     ref $($mutability)* kind,
367                 } = *terminator;
368
369                 self.visit_source_info(source_info);
370                 self.visit_terminator_kind(block, kind, location);
371             }
372
373             fn super_terminator_kind(&mut self,
374                                      block: BasicBlock,
375                                      kind: & $($mutability)* TerminatorKind<'tcx>,
376                                      source_location: Location) {
377                 match *kind {
378                     TerminatorKind::Goto { target } => {
379                         self.visit_branch(block, target);
380                     }
381
382                     TerminatorKind::SwitchInt { ref $($mutability)* discr,
383                                                 ref $($mutability)* switch_ty,
384                                                 ref values,
385                                                 ref targets } => {
386                         self.visit_operand(discr, source_location);
387                         self.visit_ty(switch_ty);
388                         for value in &values[..] {
389                             self.visit_const_int(value, source_location);
390                         }
391                         for &target in targets {
392                             self.visit_branch(block, target);
393                         }
394                     }
395
396                     TerminatorKind::Resume |
397                     TerminatorKind::Return |
398                     TerminatorKind::Unreachable => {
399                     }
400
401                     TerminatorKind::Drop { ref $($mutability)* location,
402                                            target,
403                                            unwind } => {
404                         self.visit_lvalue(location, LvalueContext::Drop, source_location);
405                         self.visit_branch(block, target);
406                         unwind.map(|t| self.visit_branch(block, t));
407                     }
408
409                     TerminatorKind::DropAndReplace { ref $($mutability)* location,
410                                                      ref $($mutability)* value,
411                                                      target,
412                                                      unwind } => {
413                         self.visit_lvalue(location, LvalueContext::Drop, source_location);
414                         self.visit_operand(value, source_location);
415                         self.visit_branch(block, target);
416                         unwind.map(|t| self.visit_branch(block, t));
417                     }
418
419                     TerminatorKind::Call { ref $($mutability)* func,
420                                            ref $($mutability)* args,
421                                            ref $($mutability)* destination,
422                                            cleanup } => {
423                         self.visit_operand(func, source_location);
424                         for arg in args {
425                             self.visit_operand(arg, source_location);
426                         }
427                         if let Some((ref $($mutability)* destination, target)) = *destination {
428                             self.visit_lvalue(destination, LvalueContext::Call, source_location);
429                             self.visit_branch(block, target);
430                         }
431                         cleanup.map(|t| self.visit_branch(block, t));
432                     }
433
434                     TerminatorKind::Assert { ref $($mutability)* cond,
435                                              expected: _,
436                                              ref $($mutability)* msg,
437                                              target,
438                                              cleanup } => {
439                         self.visit_operand(cond, source_location);
440                         self.visit_assert_message(msg, source_location);
441                         self.visit_branch(block, target);
442                         cleanup.map(|t| self.visit_branch(block, t));
443                     }
444                 }
445             }
446
447             fn super_assert_message(&mut self,
448                                     msg: & $($mutability)* AssertMessage<'tcx>,
449                                     location: Location) {
450                 match *msg {
451                     AssertMessage::BoundsCheck {
452                         ref $($mutability)* len,
453                         ref $($mutability)* index
454                     } => {
455                         self.visit_operand(len, location);
456                         self.visit_operand(index, location);
457                     }
458                     AssertMessage::Math(_) => {}
459                 }
460             }
461
462             fn super_rvalue(&mut self,
463                             rvalue: & $($mutability)* Rvalue<'tcx>,
464                             location: Location) {
465                 match *rvalue {
466                     Rvalue::Use(ref $($mutability)* operand) => {
467                         self.visit_operand(operand, location);
468                     }
469
470                     Rvalue::Repeat(ref $($mutability)* value,
471                                    ref $($mutability)* length) => {
472                         self.visit_operand(value, location);
473                         self.visit_const_usize(length, location);
474                     }
475
476                     Rvalue::Ref(r, bk, ref $($mutability)* path) => {
477                         self.visit_lvalue(path, LvalueContext::Borrow {
478                             region: r,
479                             kind: bk
480                         }, location);
481                     }
482
483                     Rvalue::Len(ref $($mutability)* path) => {
484                         self.visit_lvalue(path, LvalueContext::Inspect, location);
485                     }
486
487                     Rvalue::Cast(_cast_kind,
488                                  ref $($mutability)* operand,
489                                  ref $($mutability)* ty) => {
490                         self.visit_operand(operand, location);
491                         self.visit_ty(ty);
492                     }
493
494                     Rvalue::BinaryOp(_bin_op,
495                                      ref $($mutability)* lhs,
496                                      ref $($mutability)* rhs) |
497                     Rvalue::CheckedBinaryOp(_bin_op,
498                                      ref $($mutability)* lhs,
499                                      ref $($mutability)* rhs) => {
500                         self.visit_operand(lhs, location);
501                         self.visit_operand(rhs, location);
502                     }
503
504                     Rvalue::UnaryOp(_un_op, ref $($mutability)* op) => {
505                         self.visit_operand(op, location);
506                     }
507
508                     Rvalue::Discriminant(ref $($mutability)* lvalue) => {
509                         self.visit_lvalue(lvalue, LvalueContext::Inspect, location);
510                     }
511
512                     Rvalue::Box(ref $($mutability)* ty) => {
513                         self.visit_ty(ty);
514                     }
515
516                     Rvalue::Aggregate(ref $($mutability)* kind,
517                                       ref $($mutability)* operands) => {
518                         match *kind {
519                             AggregateKind::Array(ref $($mutability)* ty) => {
520                                 self.visit_ty(ty);
521                             }
522                             AggregateKind::Tuple => {
523                             }
524                             AggregateKind::Adt(_adt_def,
525                                                _variant_index,
526                                                ref $($mutability)* substs,
527                                                _active_field_index) => {
528                                 self.visit_substs(substs);
529                             }
530                             AggregateKind::Closure(ref $($mutability)* def_id,
531                                                    ref $($mutability)* closure_substs) => {
532                                 self.visit_def_id(def_id, location);
533                                 self.visit_closure_substs(closure_substs);
534                             }
535                         }
536
537                         for operand in operands {
538                             self.visit_operand(operand, location);
539                         }
540                     }
541                 }
542             }
543
544             fn super_operand(&mut self,
545                              operand: & $($mutability)* Operand<'tcx>,
546                              location: Location) {
547                 match *operand {
548                     Operand::Consume(ref $($mutability)* lvalue) => {
549                         self.visit_lvalue(lvalue, LvalueContext::Consume, location);
550                     }
551                     Operand::Constant(ref $($mutability)* constant) => {
552                         self.visit_constant(constant, location);
553                     }
554                 }
555             }
556
557             fn super_lvalue(&mut self,
558                             lvalue: & $($mutability)* Lvalue<'tcx>,
559                             context: LvalueContext<'tcx>,
560                             location: Location) {
561                 match *lvalue {
562                     Lvalue::Local(_) => {
563                     }
564                     Lvalue::Static(ref $($mutability)* static_) => {
565                         self.visit_static(static_, context, location);
566                     }
567                     Lvalue::Projection(ref $($mutability)* proj) => {
568                         self.visit_projection(proj, context, location);
569                     }
570                 }
571             }
572
573             fn super_static(&mut self,
574                             static_: & $($mutability)* Static<'tcx>,
575                             _context: LvalueContext<'tcx>,
576                             location: Location) {
577                 let Static {
578                     ref $($mutability)* def_id,
579                     ref $($mutability)* ty,
580                 } = *static_;
581                 self.visit_def_id(def_id, location);
582                 self.visit_ty(ty);
583             }
584
585             fn super_projection(&mut self,
586                                 proj: & $($mutability)* LvalueProjection<'tcx>,
587                                 context: LvalueContext<'tcx>,
588                                 location: Location) {
589                 let Projection {
590                     ref $($mutability)* base,
591                     ref $($mutability)* elem,
592                 } = *proj;
593                 let context = if context.is_mutating_use() {
594                     LvalueContext::Projection(Mutability::Mut)
595                 } else {
596                     LvalueContext::Projection(Mutability::Not)
597                 };
598                 self.visit_lvalue(base, context, location);
599                 self.visit_projection_elem(elem, context, location);
600             }
601
602             fn super_projection_elem(&mut self,
603                                      proj: & $($mutability)* LvalueElem<'tcx>,
604                                      _context: LvalueContext<'tcx>,
605                                      location: Location) {
606                 match *proj {
607                     ProjectionElem::Deref => {
608                     }
609                     ProjectionElem::Subslice { from: _, to: _ } => {
610                     }
611                     ProjectionElem::Field(_field, ref $($mutability)* ty) => {
612                         self.visit_ty(ty);
613                     }
614                     ProjectionElem::Index(ref $($mutability)* operand) => {
615                         self.visit_operand(operand, location);
616                     }
617                     ProjectionElem::ConstantIndex { offset: _,
618                                                     min_length: _,
619                                                     from_end: _ } => {
620                     }
621                     ProjectionElem::Downcast(_adt_def, _variant_index) => {
622                     }
623                 }
624             }
625
626             fn super_local_decl(&mut self,
627                                 local_decl: & $($mutability)* LocalDecl<'tcx>) {
628                 let LocalDecl {
629                     mutability: _,
630                     ref $($mutability)* ty,
631                     name: _,
632                     ref $($mutability)* source_info,
633                 } = *local_decl;
634
635                 self.visit_ty(ty);
636                 if let Some(ref $($mutability)* info) = *source_info {
637                     self.visit_source_info(info);
638                 }
639             }
640
641             fn super_visibility_scope(&mut self,
642                                       _scope: & $($mutability)* VisibilityScope) {
643             }
644
645             fn super_branch(&mut self,
646                             _source: BasicBlock,
647                             _target: BasicBlock) {
648             }
649
650             fn super_constant(&mut self,
651                               constant: & $($mutability)* Constant<'tcx>,
652                               location: Location) {
653                 let Constant {
654                     ref $($mutability)* span,
655                     ref $($mutability)* ty,
656                     ref $($mutability)* literal,
657                 } = *constant;
658
659                 self.visit_span(span);
660                 self.visit_ty(ty);
661                 self.visit_literal(literal, location);
662             }
663
664             fn super_literal(&mut self,
665                              literal: & $($mutability)* Literal<'tcx>,
666                              location: Location) {
667                 match *literal {
668                     Literal::Item { ref $($mutability)* def_id,
669                                     ref $($mutability)* substs } => {
670                         self.visit_def_id(def_id, location);
671                         self.visit_substs(substs);
672                     }
673                     Literal::Value { ref $($mutability)* value } => {
674                         self.visit_const_val(value, location);
675                     }
676                     Literal::Promoted { index: _ } => {}
677                 }
678             }
679
680             fn super_def_id(&mut self, _def_id: & $($mutability)* DefId) {
681             }
682
683             fn super_span(&mut self, _span: & $($mutability)* Span) {
684             }
685
686             fn super_source_info(&mut self, source_info: & $($mutability)* SourceInfo) {
687                 let SourceInfo {
688                     ref $($mutability)* span,
689                     ref $($mutability)* scope,
690                 } = *source_info;
691
692                 self.visit_span(span);
693                 self.visit_visibility_scope(scope);
694             }
695
696             fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
697             }
698
699             fn super_substs(&mut self, _substs: & $($mutability)* &'tcx Substs<'tcx>) {
700             }
701
702             fn super_closure_substs(&mut self,
703                                     _substs: & $($mutability)* ClosureSubsts<'tcx>) {
704             }
705
706             fn super_const_val(&mut self, _const_val: & $($mutability)* ConstVal) {
707             }
708
709             fn super_const_int(&mut self, _const_int: &ConstInt) {
710             }
711
712             fn super_const_usize(&mut self, _const_usize: & $($mutability)* ConstUsize) {
713             }
714
715             // Convenience methods
716
717             fn visit_location(&mut self, mir: & $($mutability)* Mir<'tcx>, location: Location) {
718                 let basic_block = & $($mutability)* mir[location.block];
719                 if basic_block.statements.len() == location.statement_index {
720                     if let Some(ref $($mutability)* terminator) = basic_block.terminator {
721                         self.visit_terminator(location.block, terminator, location)
722                     }
723                 } else {
724                     let statement = & $($mutability)*
725                         basic_block.statements[location.statement_index];
726                     self.visit_statement(location.block, statement, location)
727                 }
728             }
729         }
730     }
731 }
732
733 make_mir_visitor!(Visitor,);
734 make_mir_visitor!(MutVisitor,mut);
735
736 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
737 pub enum LvalueContext<'tcx> {
738     // Appears as LHS of an assignment
739     Store,
740
741     // Dest of a call
742     Call,
743
744     // Being dropped
745     Drop,
746
747     // Being inspected in some way, like loading a len
748     Inspect,
749
750     // Being borrowed
751     Borrow { region: &'tcx Region, kind: BorrowKind },
752
753     // Used as base for another lvalue, e.g. `x` in `x.y`.
754     //
755     // The `Mutability` argument specifies whether the projection is being performed in order to
756     // (potentially) mutate the lvalue. For example, the projection `x.y` is marked as a mutation
757     // in these cases:
758     //
759     //     x.y = ...;
760     //     f(&mut x.y);
761     //
762     // But not in these cases:
763     //
764     //     z = x.y;
765     //     f(&x.y);
766     Projection(Mutability),
767
768     // Consumed as part of an operand
769     Consume,
770
771     // Starting and ending a storage live range
772     StorageLive,
773     StorageDead,
774 }
775
776 impl<'tcx> LvalueContext<'tcx> {
777     /// Returns true if this lvalue context represents a drop.
778     pub fn is_drop(&self) -> bool {
779         match *self {
780             LvalueContext::Drop => true,
781             _ => false,
782         }
783     }
784
785     /// Returns true if this lvalue context represents a storage live or storage dead marker.
786     pub fn is_storage_marker(&self) -> bool {
787         match *self {
788             LvalueContext::StorageLive | LvalueContext::StorageDead => true,
789             _ => false,
790         }
791     }
792
793     /// Returns true if this lvalue context represents a storage live marker.
794     pub fn is_storage_live_marker(&self) -> bool {
795         match *self {
796             LvalueContext::StorageLive => true,
797             _ => false,
798         }
799     }
800
801     /// Returns true if this lvalue context represents a storage dead marker.
802     pub fn is_storage_dead_marker(&self) -> bool {
803         match *self {
804             LvalueContext::StorageDead => true,
805             _ => false,
806         }
807     }
808
809     /// Returns true if this lvalue context represents a use that potentially changes the value.
810     pub fn is_mutating_use(&self) -> bool {
811         match *self {
812             LvalueContext::Store | LvalueContext::Call |
813             LvalueContext::Borrow { kind: BorrowKind::Mut, .. } |
814             LvalueContext::Projection(Mutability::Mut) |
815             LvalueContext::Drop => true,
816             LvalueContext::Inspect |
817             LvalueContext::Borrow { kind: BorrowKind::Shared, .. } |
818             LvalueContext::Borrow { kind: BorrowKind::Unique, .. } |
819             LvalueContext::Projection(Mutability::Not) | LvalueContext::Consume |
820             LvalueContext::StorageLive | LvalueContext::StorageDead => false,
821         }
822     }
823
824     /// Returns true if this lvalue context represents a use that does not change the value.
825     pub fn is_nonmutating_use(&self) -> bool {
826         match *self {
827             LvalueContext::Inspect | LvalueContext::Borrow { kind: BorrowKind::Shared, .. } |
828             LvalueContext::Borrow { kind: BorrowKind::Unique, .. } |
829             LvalueContext::Projection(Mutability::Not) | LvalueContext::Consume => true,
830             LvalueContext::Borrow { kind: BorrowKind::Mut, .. } | LvalueContext::Store |
831             LvalueContext::Call | LvalueContext::Projection(Mutability::Mut) |
832             LvalueContext::Drop | LvalueContext::StorageLive | LvalueContext::StorageDead => false,
833         }
834     }
835
836     pub fn is_use(&self) -> bool {
837         self.is_mutating_use() || self.is_nonmutating_use()
838     }
839 }