Skip to main content

rustc_middle/mir/
visit.rs

1//! # The MIR Visitor
2//!
3//! ## Overview
4//!
5//! There are two visitors, one for immutable and one for mutable references,
6//! but both are generated by the `make_mir_visitor` macro.
7//! The code is written according to the following conventions:
8//!
9//! - introduce a `visit_foo` and a `super_foo` method for every MIR type
10//! - `visit_foo`, by default, calls `super_foo`
11//! - `super_foo`, by default, destructures the `foo` and calls `visit_foo`
12//!
13//! This allows you to override `visit_foo` for types you are
14//! interested in, and invoke (within that method call)
15//! `self.super_foo` to get the default behavior. Just as in an OO
16//! language, you should never call `super` methods ordinarily except
17//! in that circumstance.
18//!
19//! For the most part, we do not destructure things external to the
20//! MIR, e.g., types, spans, etc, but simply visit them and stop. This
21//! avoids duplication with other visitors like `TypeFoldable`.
22//!
23//! ## Updating
24//!
25//! The code is written in a very deliberate style intended to minimize
26//! the chance of things being overlooked. You'll notice that we always
27//! use pattern matching to reference fields and we ensure that all
28//! matches are exhaustive.
29//!
30//! For example, the `super_basic_block_data` method begins like this:
31//!
32//! ```ignore (pseudo-rust)
33//! fn super_basic_block_data(
34//!     &mut self,
35//!     block: BasicBlock,
36//!     data: & $($mutability)? BasicBlockData<'tcx>
37//! ) {
38//!     let BasicBlockData {
39//!         statements,
40//!         terminator,
41//!         is_cleanup: _
42//!     } = *data;
43//!
44//!     for statement in statements {
45//!         self.visit_statement(block, statement);
46//!     }
47//!
48//!     ...
49//! }
50//! ```
51//!
52//! Here we used `let BasicBlockData { <fields> } = *data` deliberately,
53//! rather than writing `data.statements` in the body. This is because if one
54//! adds a new field to `BasicBlockData`, one will be forced to revise this code,
55//! and hence one will (hopefully) invoke the correct visit methods (if any).
56//!
57//! For this to work, ALL MATCHES MUST BE EXHAUSTIVE IN FIELDS AND VARIANTS.
58//! That means you never write `..` to skip over fields, nor do you write `_`
59//! to skip over variants in a `match`.
60//!
61//! The only place that `_` is acceptable is to match a field (or
62//! variant argument) that does not require visiting, as in
63//! `is_cleanup` above.
64
65use crate::mir::*;
66use crate::ty::CanonicalUserTypeAnnotation;
67
68macro_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(
75                &mut self,
76                body: &$($mutability)? Body<'tcx>,
77            ) {
78                self.super_body(body);
79            }
80
81            extra_body_methods!($($mutability)?);
82
83            fn visit_basic_block_data(
84                &mut self,
85                block: BasicBlock,
86                data: & $($mutability)? BasicBlockData<'tcx>,
87            ) {
88                self.super_basic_block_data(block, data);
89            }
90
91            fn visit_source_scope_data(
92                &mut self,
93                scope_data: & $($mutability)? SourceScopeData<'tcx>,
94            ) {
95                self.super_source_scope_data(scope_data);
96            }
97
98            fn visit_statement_debuginfo(
99                &mut self,
100                stmt_debuginfo: & $($mutability)? StmtDebugInfo<'tcx>,
101                location: Location
102            ) {
103                self.super_statement_debuginfo(stmt_debuginfo, location);
104            }
105
106            fn visit_statement(
107                &mut self,
108                statement: & $($mutability)? Statement<'tcx>,
109                location: Location,
110            ) {
111                self.super_statement(statement, location);
112            }
113
114            fn visit_assign(
115                &mut self,
116                place: & $($mutability)? Place<'tcx>,
117                rvalue: & $($mutability)? Rvalue<'tcx>,
118                location: Location,
119            ) {
120                self.super_assign(place, rvalue, location);
121            }
122
123            fn visit_terminator(
124                &mut self,
125                terminator: & $($mutability)? Terminator<'tcx>,
126                location: Location,
127            ) {
128                self.super_terminator(terminator, location);
129            }
130
131            fn visit_assert_message(
132                &mut self,
133                msg: & $($mutability)? AssertMessage<'tcx>,
134                location: Location,
135            ) {
136                self.super_assert_message(msg, location);
137            }
138
139            fn visit_rvalue(
140                &mut self,
141                rvalue: & $($mutability)? Rvalue<'tcx>,
142                location: Location,
143            ) {
144                self.super_rvalue(rvalue, location);
145            }
146
147            fn visit_operand(
148                &mut self,
149                operand: & $($mutability)? Operand<'tcx>,
150                location: Location,
151            ) {
152                self.super_operand(operand, location);
153            }
154
155            fn visit_ascribe_user_ty(
156                &mut self,
157                place: & $($mutability)? Place<'tcx>,
158                variance: $(& $mutability)? ty::Variance,
159                user_ty: & $($mutability)? UserTypeProjection,
160                location: Location,
161            ) {
162                self.super_ascribe_user_ty(place, variance, user_ty, location);
163            }
164
165            fn visit_coverage(
166                &mut self,
167                kind: & $($mutability)? coverage::CoverageKind,
168                location: Location,
169            ) {
170                self.super_coverage(kind, location);
171            }
172
173            fn visit_place(
174                &mut self,
175                place: & $($mutability)? Place<'tcx>,
176                context: PlaceContext,
177                location: Location,
178            ) {
179                self.super_place(place, context, location);
180            }
181
182            visit_place_fns!($($mutability)?);
183
184            /// This is called for every constant in the MIR body and every `required_consts`
185            /// (i.e., including consts that have been dead-code-eliminated).
186            fn visit_const_operand(
187                &mut self,
188                constant: & $($mutability)? ConstOperand<'tcx>,
189                location: Location,
190            ) {
191                self.super_const_operand(constant, location);
192            }
193
194            fn visit_ty_const(
195                &mut self,
196                ct: $( & $mutability)? ty::Const<'tcx>,
197                location: Location,
198            ) {
199                self.super_ty_const(ct, location);
200            }
201
202            fn visit_span(
203                &mut self,
204                span: $(& $mutability)? Span,
205            ) {
206                self.super_span(span);
207            }
208
209            fn visit_source_info(
210                &mut self,
211                source_info: & $($mutability)? SourceInfo,
212            ) {
213                self.super_source_info(source_info);
214            }
215
216            fn visit_ty(
217                &mut self,
218                ty: $(& $mutability)? Ty<'tcx>,
219                _: TyContext,
220            ) {
221                self.super_ty(ty);
222            }
223
224            fn visit_user_type_projection(
225                &mut self,
226                ty: & $($mutability)? UserTypeProjection,
227            ) {
228                self.super_user_type_projection(ty);
229            }
230
231            fn visit_user_type_annotation(
232                &mut self,
233                index: UserTypeAnnotationIndex,
234                ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
235            ) {
236                self.super_user_type_annotation(index, ty);
237            }
238
239            fn visit_region(
240                &mut self,
241                region: $(& $mutability)? ty::Region<'tcx>,
242                _: Location,
243            ) {
244                self.super_region(region);
245            }
246
247            fn visit_args(
248                &mut self,
249                args: & $($mutability)? GenericArgsRef<'tcx>,
250                _: Location,
251            ) {
252                self.super_args(args);
253            }
254
255            fn visit_local_decl(
256                &mut self,
257                local: Local,
258                local_decl: & $($mutability)? LocalDecl<'tcx>,
259            ) {
260                self.super_local_decl(local, local_decl);
261            }
262
263            fn visit_var_debug_info(
264                &mut self,
265                var_debug_info: & $($mutability)* VarDebugInfo<'tcx>,
266            ) {
267                self.super_var_debug_info(var_debug_info);
268            }
269
270            fn visit_local(
271                &mut self,
272                local: $(& $mutability)? Local,
273                context: PlaceContext,
274                location: Location,
275            ) {
276                self.super_local(local, context, location)
277            }
278
279            fn visit_source_scope(
280                &mut self,
281                scope: $(& $mutability)? SourceScope,
282            ) {
283                self.super_source_scope(scope);
284            }
285
286            // The `super_xxx` methods comprise the default behavior and are
287            // not meant to be overridden.
288
289            fn super_body(
290                &mut self,
291                body: &$($mutability)? Body<'tcx>,
292            ) {
293                super_body!(self, body, $($mutability, true)?);
294            }
295
296            fn super_basic_block_data(
297                &mut self,
298                block: BasicBlock,
299                data: & $($mutability)? BasicBlockData<'tcx>)
300            {
301                let BasicBlockData {
302                    statements,
303                    after_last_stmt_debuginfos,
304                    terminator,
305                    is_cleanup: _
306                } = data;
307
308                let mut index = 0;
309                for statement in statements {
310                    let location = Location { block, statement_index: index };
311                    self.visit_statement(statement, location);
312                    index += 1;
313                }
314
315                let location = Location { block, statement_index: index };
316                for debuginfo in after_last_stmt_debuginfos as & $($mutability)? [_] {
317                    self.visit_statement_debuginfo(debuginfo, location);
318                }
319                if let Some(terminator) = terminator {
320                    self.visit_terminator(terminator, location);
321                }
322            }
323
324            fn super_source_scope_data(
325                &mut self,
326                scope_data: & $($mutability)? SourceScopeData<'tcx>,
327            ) {
328                let SourceScopeData {
329                    span,
330                    parent_scope,
331                    inlined,
332                    inlined_parent_scope,
333                    local_data: _,
334                } = scope_data;
335
336                self.visit_span($(& $mutability)? *span);
337                if let Some(parent_scope) = parent_scope {
338                    self.visit_source_scope($(& $mutability)? *parent_scope);
339                }
340                if let Some((callee, callsite_span)) = inlined {
341                    let location = Location::START;
342
343                    self.visit_span($(& $mutability)? *callsite_span);
344
345                    let ty::Instance { def: callee_def, args: callee_args } = callee;
346                    match callee_def {
347                        ty::InstanceKind::Item(_def_id) => {}
348
349                        ty::InstanceKind::Intrinsic(_def_id)
350                        | ty::InstanceKind::LlvmIntrinsic(_def_id)
351                        | ty::InstanceKind::Shim(ty::ShimKind::VTable(_def_id))
352                        | ty::InstanceKind::Shim(ty::ShimKind::Reify(_def_id, _))
353                        | ty::InstanceKind::Virtual(_def_id, _)
354                        | ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(_def_id))
355                        | ty::InstanceKind::Shim(ty::ShimKind::ClosureOnce { call_once: _def_id, closure: _, track_caller: _ })
356                        | ty::InstanceKind::Shim(ty::ShimKind::ConstructCoroutineInClosure {
357                            coroutine_closure_def_id: _def_id,
358                            receiver_by_ref: _,
359                        })
360                        | ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_def_id, None)) => {}
361
362                        ty::InstanceKind::Shim(ty::ShimKind::FnPtr(_def_id, ty))
363                        | ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_def_id, Some(ty)))
364                        | ty::InstanceKind::Shim(ty::ShimKind::Clone(_def_id, ty))
365                        | ty::InstanceKind::Shim(ty::ShimKind::FnPtrAsPtr(_def_id, ty))
366                        | ty::InstanceKind::Shim(ty::ShimKind::FnPtrFromPtr(_def_id, ty))
367                        | ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlue(_def_id, ty))
368                        | ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlueCtor(_def_id, ty)) => {
369                            // FIXME(eddyb) use a better `TyContext` here.
370                            self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
371                        }
372                        ty::InstanceKind::Shim(ty::ShimKind::FutureDropPoll(_def_id, proxy_ty, impl_ty)) => {
373                            self.visit_ty($(& $mutability)? *proxy_ty, TyContext::Location(location));
374                            self.visit_ty($(& $mutability)? *impl_ty, TyContext::Location(location));
375                        }
376                    }
377                    self.visit_args(callee_args, location);
378                }
379                if let Some(inlined_parent_scope) = inlined_parent_scope {
380                    self.visit_source_scope($(& $mutability)? *inlined_parent_scope);
381                }
382            }
383
384            fn super_statement_debuginfo(
385                &mut self,
386                stmt_debuginfo: & $($mutability)? StmtDebugInfo<'tcx>,
387                location: Location
388            ) {
389                match stmt_debuginfo {
390                    StmtDebugInfo::AssignRef(local, place) => {
391                        self.visit_local(
392                            $(& $mutability)? *local,
393                            PlaceContext::NonUse(NonUseContext::VarDebugInfo),
394                            location
395                        );
396                        self.visit_place(
397                            place,
398                            PlaceContext::NonUse(NonUseContext::VarDebugInfo),
399                            location
400                        );
401                    },
402                    StmtDebugInfo::InvalidAssign(local) => {
403                        self.visit_local(
404                            $(& $mutability)? *local,
405                            PlaceContext::NonUse(NonUseContext::VarDebugInfo),
406                            location
407                        );
408                    }
409                }
410            }
411
412            fn super_statement(
413                &mut self,
414                statement: & $($mutability)? Statement<'tcx>,
415                location: Location
416            ) {
417                let Statement { source_info, kind, debuginfos } = statement;
418
419                self.visit_source_info(source_info);
420                for debuginfo in debuginfos as & $($mutability)? [_] {
421                    self.visit_statement_debuginfo(debuginfo, location);
422                }
423                match kind {
424                    StatementKind::Assign((place, rvalue)) => {
425                        self.visit_assign(place, rvalue, location);
426                    }
427                    StatementKind::FakeRead((_, place)) => {
428                        self.visit_place(
429                            place,
430                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
431                            location
432                        );
433                    }
434                    StatementKind::SetDiscriminant { place, .. } => {
435                        self.visit_place(
436                            place,
437                            PlaceContext::MutatingUse(MutatingUseContext::SetDiscriminant),
438                            location
439                        );
440                    }
441                    StatementKind::StorageLive(local) => {
442                        self.visit_local(
443                            $(& $mutability)? *local,
444                            PlaceContext::NonUse(NonUseContext::StorageLive),
445                            location
446                        );
447                    }
448                    StatementKind::StorageDead(local) => {
449                        self.visit_local(
450                            $(& $mutability)? *local,
451                            PlaceContext::NonUse(NonUseContext::StorageDead),
452                            location
453                        );
454                    }
455                    StatementKind::PlaceMention(place) => {
456                        self.visit_place(
457                            place,
458                            PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention),
459                            location
460                        );
461                    }
462                    StatementKind::AscribeUserType((place, user_ty), variance) => {
463                        self.visit_ascribe_user_ty(
464                            place,
465                            $(& $mutability)? *variance,
466                            user_ty,
467                            location
468                        );
469                    }
470                    StatementKind::Coverage(coverage) => {
471                        self.visit_coverage(
472                            coverage,
473                            location
474                        )
475                    }
476                    StatementKind::Intrinsic(intrinsic) => {
477                        match intrinsic {
478                            NonDivergingIntrinsic::Assume(op) => self.visit_operand(op, location),
479                            NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
480                                src,
481                                dst,
482                                count
483                            }) => {
484                                self.visit_operand(src, location);
485                                self.visit_operand(dst, location);
486                                self.visit_operand(count, location);
487                            }
488                        }
489                    }
490                    StatementKind::BackwardIncompatibleDropHint { place, .. } => {
491                        self.visit_place(
492                            place,
493                            PlaceContext::NonUse(NonUseContext::BackwardIncompatibleDropHint),
494                            location
495                        );
496                    }
497                    StatementKind::ConstEvalCounter => {}
498                    StatementKind::Nop => {}
499                }
500            }
501
502            fn super_assign(
503                &mut self,
504                place: &$($mutability)? Place<'tcx>,
505                rvalue: &$($mutability)? Rvalue<'tcx>,
506                location: Location
507            ) {
508                self.visit_place(
509                    place,
510                    PlaceContext::MutatingUse(MutatingUseContext::Store),
511                    location
512                );
513                self.visit_rvalue(rvalue, location);
514            }
515
516            fn super_terminator(
517                &mut self,
518                terminator: &$($mutability)? Terminator<'tcx>,
519                location: Location
520            ) {
521                let Terminator { source_info, kind, attributes: _ } = terminator;
522
523                self.visit_source_info(source_info);
524                match kind {
525                    TerminatorKind::Goto { .. }
526                    | TerminatorKind::UnwindResume
527                    | TerminatorKind::UnwindTerminate(_)
528                    | TerminatorKind::CoroutineDrop
529                    | TerminatorKind::Unreachable
530                    | TerminatorKind::FalseEdge { .. }
531                    | TerminatorKind::FalseUnwind { .. } => {}
532
533                    TerminatorKind::Return => {
534                        // `return` logically moves from the return place `_0`. Note that the place
535                        // cannot be changed by any visitor, though.
536                        let $($mutability)? local = RETURN_PLACE;
537                        self.visit_local(
538                            $(& $mutability)? local,
539                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
540                            location,
541                        );
542
543                        assert_eq!(
544                            local,
545                            RETURN_PLACE,
546                            "`MutVisitor` tried to mutate return place of `return` terminator"
547                        );
548                    }
549
550                    TerminatorKind::SwitchInt { discr, targets: _ } => {
551                        self.visit_operand(discr, location);
552                    }
553
554                    TerminatorKind::Drop {
555                        place,
556                        target: _,
557                        unwind: _,
558                        replace: _,
559                        drop: _,
560                    } => {
561                        self.visit_place(
562                            place,
563                            PlaceContext::MutatingUse(MutatingUseContext::Drop),
564                            location
565                        );
566                    }
567
568                    TerminatorKind::Call {
569                        func,
570                        args,
571                        destination,
572                        target: _,
573                        unwind: _,
574                        call_source: _,
575                        fn_span,
576                    } => {
577                        self.visit_span($(& $mutability)? *fn_span);
578                        self.visit_operand(func, location);
579                        for arg in args {
580                            self.visit_operand(&$($mutability)? arg.node, location);
581                        }
582                        self.visit_place(
583                            destination,
584                            PlaceContext::MutatingUse(MutatingUseContext::Call),
585                            location
586                        );
587                    }
588
589                    TerminatorKind::TailCall { func, args, fn_span } => {
590                        self.visit_span($(& $mutability)? *fn_span);
591                        self.visit_operand(func, location);
592                        for arg in args {
593                            self.visit_operand(&$($mutability)? arg.node, location);
594                        }
595                    },
596
597                    TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
598                        self.visit_operand(cond, location);
599                        self.visit_assert_message(msg, location);
600                    }
601
602                    TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
603                        self.visit_operand(value, location);
604                        self.visit_place(
605                            resume_arg,
606                            PlaceContext::MutatingUse(MutatingUseContext::Yield),
607                            location,
608                        );
609                    }
610
611                    TerminatorKind::InlineAsm {
612                        asm_macro: _,
613                        template: _,
614                        operands,
615                        options: _,
616                        line_spans: _,
617                        targets: _,
618                        unwind: _,
619                    } => {
620                        for op in operands {
621                            match op {
622                                InlineAsmOperand::In { value, .. } => {
623                                    self.visit_operand(value, location);
624                                }
625                                InlineAsmOperand::Out { place: Some(place), .. } => {
626                                    self.visit_place(
627                                        place,
628                                        PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
629                                        location,
630                                    );
631                                }
632                                InlineAsmOperand::InOut { in_value, out_place, .. } => {
633                                    self.visit_operand(in_value, location);
634                                    if let Some(out_place) = out_place {
635                                        self.visit_place(
636                                            out_place,
637                                            PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
638                                            location,
639                                        );
640                                    }
641                                }
642                                InlineAsmOperand::Const { value }
643                                | InlineAsmOperand::SymFn { value } => {
644                                    self.visit_const_operand(value, location);
645                                }
646                                InlineAsmOperand::Out { place: None, .. }
647                                | InlineAsmOperand::SymStatic { def_id: _ }
648                                | InlineAsmOperand::Label { target_index: _ } => {}
649                            }
650                        }
651                    }
652                }
653            }
654
655            fn super_assert_message(
656                &mut self,
657                msg: & $($mutability)? AssertMessage<'tcx>,
658                location: Location
659            ) {
660                use crate::mir::AssertKind::*;
661                match msg {
662                    BoundsCheck { len, index } => {
663                        self.visit_operand(len, location);
664                        self.visit_operand(index, location);
665                    }
666                    Overflow(_, l, r) => {
667                        self.visit_operand(l, location);
668                        self.visit_operand(r, location);
669                    }
670                    OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) | InvalidEnumConstruction(op) => {
671                        self.visit_operand(op, location);
672                    }
673                    ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference | NullReferenceConstructed | ResumedAfterDrop(_) => {
674                        // Nothing to visit
675                    }
676                    MisalignedPointerDereference { required, found } => {
677                        self.visit_operand(required, location);
678                        self.visit_operand(found, location);
679                    }
680                }
681            }
682
683            fn super_rvalue(
684                &mut self,
685                rvalue: & $($mutability)? Rvalue<'tcx>,
686                location: Location
687            ) {
688                match rvalue {
689                    Rvalue::Use(operand, _with_retag) => {
690                        self.visit_operand(operand, location);
691                    }
692
693                    Rvalue::Repeat(value, ct) => {
694                        self.visit_operand(value, location);
695                        self.visit_ty_const($(&$mutability)? *ct, location);
696                    }
697
698                    Rvalue::ThreadLocalRef(_) => {}
699
700                    Rvalue::Ref(r, bk, path) => {
701                        self.visit_region($(& $mutability)? *r, location);
702                        let ctx = match bk {
703                            BorrowKind::Shared => PlaceContext::NonMutatingUse(
704                                NonMutatingUseContext::SharedBorrow
705                            ),
706                            BorrowKind::Fake(_) => PlaceContext::NonMutatingUse(
707                                NonMutatingUseContext::FakeBorrow
708                            ),
709                            BorrowKind::Mut { .. } =>
710                                PlaceContext::MutatingUse(MutatingUseContext::Borrow),
711                        };
712                        self.visit_place(path, ctx, location);
713                    }
714
715                    Rvalue::Reborrow(target, mutability, place) => {
716                        self.visit_ty($(& $mutability)? *target, TyContext::Location(location));
717                        self.visit_place(
718                            place,
719                            match mutability {
720                                Mutability::Not => PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow),
721                                Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::Borrow),
722                            },
723                            location
724                        );
725                    }
726
727                    Rvalue::CopyForDeref(place) => {
728                        self.visit_place(
729                            place,
730                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
731                            location
732                        );
733                    }
734
735                    Rvalue::RawPtr(m, path) => {
736                        let ctx = match m {
737                            RawPtrKind::Mut => PlaceContext::MutatingUse(
738                                MutatingUseContext::RawBorrow
739                            ),
740                            RawPtrKind::Const => PlaceContext::NonMutatingUse(
741                                NonMutatingUseContext::RawBorrow
742                            ),
743                            RawPtrKind::FakeForPtrMetadata => PlaceContext::NonMutatingUse(
744                                NonMutatingUseContext::Inspect
745                            ),
746                        };
747                        self.visit_place(path, ctx, location);
748                    }
749
750                    Rvalue::Cast(_cast_kind, operand, ty) => {
751                        self.visit_operand(operand, location);
752                        self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
753                    }
754
755                    Rvalue::BinaryOp(_bin_op, (lhs, rhs)) => {
756                        self.visit_operand(lhs, location);
757                        self.visit_operand(rhs, location);
758                    }
759
760                    Rvalue::UnaryOp(_un_op, op) => {
761                        self.visit_operand(op, location);
762                    }
763
764                    Rvalue::Discriminant(place) => {
765                        self.visit_place(
766                            place,
767                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
768                            location
769                        );
770                    }
771
772                    Rvalue::Aggregate(kind, operands) => {
773                        let kind = &$($mutability)? **kind;
774                        match kind {
775                            AggregateKind::Array(ty) => {
776                                self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
777                            }
778                            AggregateKind::Tuple => {}
779                            AggregateKind::Adt(
780                                _adt_def,
781                                _variant_index,
782                                args,
783                                _user_args,
784                                _active_field_index
785                            ) => {
786                                self.visit_args(args, location);
787                            }
788                            AggregateKind::Closure(_, closure_args) => {
789                                self.visit_args(closure_args, location);
790                            }
791                            AggregateKind::Coroutine(_, coroutine_args) => {
792                                self.visit_args(coroutine_args, location);
793                            }
794                            AggregateKind::CoroutineClosure(_, coroutine_closure_args) => {
795                                self.visit_args(coroutine_closure_args, location);
796                            }
797                            AggregateKind::RawPtr(ty, _) => {
798                                self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
799                            }
800                        }
801
802                        for operand in operands {
803                            self.visit_operand(operand, location);
804                        }
805                    }
806
807                    Rvalue::WrapUnsafeBinder(op, ty) => {
808                        self.visit_operand(op, location);
809                        self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
810                    }
811
812
813                }
814            }
815
816            fn super_operand(
817                &mut self,
818                operand: & $($mutability)? Operand<'tcx>,
819                location: Location
820            ) {
821                match operand {
822                    Operand::Copy(place) => {
823                        self.visit_place(
824                            place,
825                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
826                            location
827                        );
828                    }
829                    Operand::Move(place) => {
830                        self.visit_place(
831                            place,
832                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
833                            location
834                        );
835                    }
836                    Operand::Constant(constant) => {
837                        self.visit_const_operand(constant, location);
838                    }
839                    Operand::RuntimeChecks(_) => {}
840                }
841            }
842
843            fn super_ascribe_user_ty(
844                &mut self,
845                place: & $($mutability)? Place<'tcx>,
846                variance: $(& $mutability)? ty::Variance,
847                user_ty: & $($mutability)? UserTypeProjection,
848                location: Location)
849            {
850                self.visit_place(
851                    place,
852                    PlaceContext::NonUse(
853                        NonUseContext::AscribeUserTy($(* &$mutability *)? variance)
854                    ),
855                    location
856                );
857                self.visit_user_type_projection(user_ty);
858            }
859
860            fn super_coverage(
861                &mut self,
862                _kind: & $($mutability)? coverage::CoverageKind,
863                _location: Location
864            ) {
865            }
866
867            fn super_local_decl(
868                &mut self,
869                local: Local,
870                local_decl: & $($mutability)? LocalDecl<'tcx>
871            ) {
872                let LocalDecl {
873                    mutability: _,
874                    ty,
875                    user_ty,
876                    source_info,
877                    local_info: _,
878                } = local_decl;
879
880                self.visit_source_info(source_info);
881
882                self.visit_ty($(& $mutability)? *ty, TyContext::LocalDecl {
883                    local,
884                    source_info: *source_info,
885                });
886                if let Some(user_ty) = user_ty {
887                    for user_ty in & $($mutability)? user_ty.contents {
888                        self.visit_user_type_projection(user_ty);
889                    }
890                }
891            }
892
893            fn super_local(
894                &mut self,
895                _local: $(& $mutability)? Local,
896                _context: PlaceContext,
897                _location: Location,
898            ) {
899            }
900
901            fn super_var_debug_info(
902                &mut self,
903                var_debug_info: & $($mutability)? VarDebugInfo<'tcx>
904            ) {
905                let VarDebugInfo {
906                    name: _,
907                    source_info,
908                    composite,
909                    value,
910                    argument_index: _,
911                } = var_debug_info;
912
913                self.visit_source_info(source_info);
914                let location = Location::START;
915                if let Some(VarDebugInfoFragment {
916                    ty,
917                    projection
918                }) = composite {
919                    self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
920                    for elem in projection {
921                        let ProjectionElem::Field(_, ty) = elem else { bug!() };
922                        self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
923                    }
924                }
925                match value {
926                    VarDebugInfoContents::Const(c) => self.visit_const_operand(c, location),
927                    VarDebugInfoContents::Place(place) =>
928                        self.visit_place(
929                            place,
930                            PlaceContext::NonUse(NonUseContext::VarDebugInfo),
931                            location
932                        ),
933                }
934            }
935
936            fn super_source_scope(&mut self, _scope: $(& $mutability)? SourceScope) {}
937
938            fn super_const_operand(
939                &mut self,
940                constant: & $($mutability)? ConstOperand<'tcx>,
941                location: Location
942            ) {
943                let ConstOperand {
944                    span,
945                    user_ty: _, // no visit method for this
946                    const_,
947                } = constant;
948
949                self.visit_span($(& $mutability)? *span);
950                match const_ {
951                    Const::Ty(_, ct) => self.visit_ty_const($(&$mutability)? *ct, location),
952                    Const::Val(_, ty) | Const::Unevaluated(_, ty) => {
953                        self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
954                    }
955                }
956            }
957
958            fn super_ty_const(
959                &mut self,
960                _ct: $(& $mutability)? ty::Const<'tcx>,
961                _location: Location,
962            ) {
963            }
964
965            fn super_span(&mut self, _span: $(& $mutability)? Span) {}
966
967            fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) {
968                let SourceInfo { span, scope } = source_info;
969
970                self.visit_span($(& $mutability)? *span);
971                self.visit_source_scope($(& $mutability)? *scope);
972            }
973
974            fn super_user_type_projection(&mut self, _ty: & $($mutability)? UserTypeProjection) {}
975
976            fn super_user_type_annotation(
977                &mut self,
978                _index: UserTypeAnnotationIndex,
979                ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
980            ) {
981                self.visit_span($(& $mutability)? ty.span);
982                self.visit_ty($(& $mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
983            }
984
985            fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {}
986
987            fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) {}
988
989            fn super_args(&mut self, _args: & $($mutability)? GenericArgsRef<'tcx>) {}
990
991            // Convenience methods
992
993            fn visit_location(
994                &mut self,
995                body: &$($mutability)? Body<'tcx>,
996                location: Location
997            ) {
998                let basic_block =
999                    & $($mutability)? basic_blocks!(body, $($mutability, true)?)[location.block];
1000                if basic_block.statements.len() == location.statement_index {
1001                    if let Some(ref $($mutability)? terminator) = basic_block.terminator {
1002                        self.visit_terminator(terminator, location)
1003                    }
1004                } else {
1005                    let statement = & $($mutability)?
1006                        basic_block.statements[location.statement_index];
1007                    self.visit_statement(statement, location)
1008                }
1009            }
1010        }
1011    }
1012}
1013
1014macro_rules! basic_blocks {
1015    ($body:ident, mut, true) => {
1016        $body.basic_blocks.as_mut()
1017    };
1018    ($body:ident, mut, false) => {
1019        $body.basic_blocks.as_mut_preserves_cfg()
1020    };
1021    ($body:ident,) => {
1022        $body.basic_blocks
1023    };
1024}
1025
1026macro_rules! basic_blocks_iter {
1027    ($body:ident, mut, $invalidate:tt) => {
1028        basic_blocks!($body, mut, $invalidate).iter_enumerated_mut()
1029    };
1030    ($body:ident,) => {
1031        basic_blocks!($body,).iter_enumerated()
1032    };
1033}
1034
1035macro_rules! extra_body_methods {
1036    (mut) => {
1037        fn visit_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
1038            self.super_body_preserves_cfg(body);
1039        }
1040
1041        fn super_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
1042            super_body!(self, body, mut, false);
1043        }
1044    };
1045    () => {};
1046}
1047
1048macro_rules! super_body {
1049    ($self:ident, $body:ident, $($mutability:ident, $invalidate:tt)?) => {
1050        let span = $body.span;
1051        if let Some(coroutine) = &$($mutability)? $body.coroutine {
1052            if let Some(yield_ty) = $(& $mutability)? coroutine.yield_ty {
1053                $self.visit_ty(
1054                    yield_ty,
1055                    TyContext::YieldTy(SourceInfo::outermost(span))
1056                );
1057            }
1058            if let Some(resume_ty) = $(& $mutability)? coroutine.resume_ty {
1059                $self.visit_ty(
1060                    resume_ty,
1061                    TyContext::ResumeTy(SourceInfo::outermost(span))
1062                );
1063            }
1064        }
1065
1066        for var_debug_info in &$($mutability)? $body.var_debug_info {
1067            $self.visit_var_debug_info(var_debug_info);
1068        }
1069
1070        for (bb, data) in basic_blocks_iter!($body, $($mutability, $invalidate)?) {
1071            $self.visit_basic_block_data(bb, data);
1072        }
1073
1074        for scope in &$($mutability)? $body.source_scopes {
1075            $self.visit_source_scope_data(scope);
1076        }
1077
1078        $self.visit_ty(
1079            $(& $mutability)? $body.return_ty(),
1080            TyContext::ReturnTy(SourceInfo::outermost($body.span))
1081        );
1082
1083        for local in $body.local_decls.indices() {
1084            $self.visit_local_decl(local, & $($mutability)? $body.local_decls[local]);
1085        }
1086
1087        macro_rules! type_annotations {
1088            (mut) => ($body.user_type_annotations.iter_enumerated_mut());
1089            () => ($body.user_type_annotations.iter_enumerated());
1090        }
1091
1092        for (index, annotation) in type_annotations!($($mutability)?) {
1093            $self.visit_user_type_annotation(
1094                index, annotation
1095            );
1096        }
1097
1098        $self.visit_span($(& $mutability)? $body.span);
1099
1100        if let Some(required_consts) = &$($mutability)? $body.required_consts {
1101            for const_ in required_consts {
1102                let location = Location::START;
1103                $self.visit_const_operand(const_, location);
1104            }
1105        }
1106    }
1107}
1108
1109macro_rules! visit_place_fns {
1110    (mut) => {
1111        fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
1112
1113        fn super_place(
1114            &mut self,
1115            place: &mut Place<'tcx>,
1116            context: PlaceContext,
1117            location: Location,
1118        ) {
1119            self.visit_local(&mut place.local, context, location);
1120
1121            if let Some(new_projection) = self.process_projection(&place.projection, location) {
1122                place.projection = self.tcx().mk_place_elems(&new_projection);
1123            }
1124        }
1125
1126        fn process_projection<'a>(
1127            &mut self,
1128            projection: &'a [PlaceElem<'tcx>],
1129            location: Location,
1130        ) -> Option<Vec<PlaceElem<'tcx>>> {
1131            let mut projection = Cow::Borrowed(projection);
1132
1133            for i in 0..projection.len() {
1134                if let Some(&elem) = projection.get(i) {
1135                    if let Some(elem) = self.process_projection_elem(elem, location) {
1136                        // This converts the borrowed projection into `Cow::Owned(_)` and returns a
1137                        // clone of the projection so we can mutate and reintern later.
1138                        let vec = projection.to_mut();
1139                        vec[i] = elem;
1140                    }
1141                }
1142            }
1143
1144            match projection {
1145                Cow::Borrowed(_) => None,
1146                Cow::Owned(vec) => Some(vec),
1147            }
1148        }
1149
1150        fn process_projection_elem(
1151            &mut self,
1152            elem: PlaceElem<'tcx>,
1153            location: Location,
1154        ) -> Option<PlaceElem<'tcx>> {
1155            match elem {
1156                PlaceElem::Index(local) => {
1157                    let mut new_local = local;
1158                    self.visit_local(
1159                        &mut new_local,
1160                        PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
1161                        location,
1162                    );
1163
1164                    if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
1165                }
1166                PlaceElem::Field(field, ty) => {
1167                    let mut new_ty = ty;
1168                    self.visit_ty(&mut new_ty, TyContext::Location(location));
1169                    if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
1170                }
1171                PlaceElem::OpaqueCast(ty) => {
1172                    let mut new_ty = ty;
1173                    self.visit_ty(&mut new_ty, TyContext::Location(location));
1174                    if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None }
1175                }
1176                PlaceElem::UnwrapUnsafeBinder(ty) => {
1177                    let mut new_ty = ty;
1178                    self.visit_ty(&mut new_ty, TyContext::Location(location));
1179                    if ty != new_ty { Some(PlaceElem::UnwrapUnsafeBinder(new_ty)) } else { None }
1180                }
1181                PlaceElem::Deref
1182                | PlaceElem::ConstantIndex { .. }
1183                | PlaceElem::Subslice { .. }
1184                | PlaceElem::Downcast(..) => None,
1185            }
1186        }
1187    };
1188
1189    () => {
1190        fn visit_projection(
1191            &mut self,
1192            place_ref: PlaceRef<'tcx>,
1193            context: PlaceContext,
1194            location: Location,
1195        ) {
1196            self.super_projection(place_ref, context, location);
1197        }
1198
1199        fn visit_projection_elem(
1200            &mut self,
1201            place_ref: PlaceRef<'tcx>,
1202            elem: PlaceElem<'tcx>,
1203            context: PlaceContext,
1204            location: Location,
1205        ) {
1206            self.super_projection_elem(place_ref, elem, context, location);
1207        }
1208
1209        fn super_place(
1210            &mut self,
1211            place: &Place<'tcx>,
1212            mut context: PlaceContext,
1213            location: Location,
1214        ) {
1215            if !place.projection.is_empty() && context.is_use() {
1216                // ^ Only change the context if it is a real use, not a "use" in debuginfo.
1217                context = if context.is_mutating_use() {
1218                    PlaceContext::MutatingUse(MutatingUseContext::Projection)
1219                } else {
1220                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
1221                };
1222            }
1223
1224            self.visit_local(place.local, context, location);
1225
1226            self.visit_projection(place.as_ref(), context, location);
1227        }
1228
1229        fn super_projection(
1230            &mut self,
1231            place_ref: PlaceRef<'tcx>,
1232            context: PlaceContext,
1233            location: Location,
1234        ) {
1235            for (base, elem) in place_ref.iter_projections().rev() {
1236                self.visit_projection_elem(base, elem, context, location);
1237            }
1238        }
1239
1240        fn super_projection_elem(
1241            &mut self,
1242            _place_ref: PlaceRef<'tcx>,
1243            elem: PlaceElem<'tcx>,
1244            context: PlaceContext,
1245            location: Location,
1246        ) {
1247            match elem {
1248                ProjectionElem::OpaqueCast(ty)
1249                | ProjectionElem::Field(_, ty)
1250                | ProjectionElem::UnwrapUnsafeBinder(ty) => {
1251                    self.visit_ty(ty, TyContext::Location(location));
1252                }
1253                ProjectionElem::Index(local) => {
1254                    self.visit_local(
1255                        local,
1256                        if context.is_use() {
1257                            // ^ Only change the context if it is a real use, not a "use" in debuginfo.
1258                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy)
1259                        } else {
1260                            context
1261                        },
1262                        location,
1263                    );
1264                }
1265                ProjectionElem::Deref
1266                | ProjectionElem::Subslice { from: _, to: _, from_end: _ }
1267                | ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ }
1268                | ProjectionElem::Downcast(_, _) => {}
1269            }
1270        }
1271    };
1272}
1273
1274pub trait Visitor<'tcx> {
    fn visit_body(&mut self, body: &Body<'tcx>) { self.super_body(body); }
    fn visit_basic_block_data(&mut self, block: BasicBlock,
        data: &BasicBlockData<'tcx>) {
        self.super_basic_block_data(block, data);
    }
    fn visit_source_scope_data(&mut self,
        scope_data: &SourceScopeData<'tcx>) {
        self.super_source_scope_data(scope_data);
    }
    fn visit_statement_debuginfo(&mut self,
        stmt_debuginfo: &StmtDebugInfo<'tcx>, location: Location) {
        self.super_statement_debuginfo(stmt_debuginfo, location);
    }
    fn visit_statement(&mut self, statement: &Statement<'tcx>,
        location: Location) {
        self.super_statement(statement, location);
    }
    fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>,
        location: Location) {
        self.super_assign(place, rvalue, location);
    }
    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>,
        location: Location) {
        self.super_terminator(terminator, location);
    }
    fn visit_assert_message(&mut self, msg: &AssertMessage<'tcx>,
        location: Location) {
        self.super_assert_message(msg, location);
    }
    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
        self.super_rvalue(rvalue, location);
    }
    fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
        self.super_operand(operand, location);
    }
    fn visit_ascribe_user_ty(&mut self, place: &Place<'tcx>,
        variance: ty::Variance, user_ty: &UserTypeProjection,
        location: Location) {
        self.super_ascribe_user_ty(place, variance, user_ty, location);
    }
    fn visit_coverage(&mut self, kind: &coverage::CoverageKind,
        location: Location) {
        self.super_coverage(kind, location);
    }
    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext,
        location: Location) {
        self.super_place(place, context, location);
    }
    fn visit_projection(&mut self, place_ref: PlaceRef<'tcx>,
        context: PlaceContext, location: Location) {
        self.super_projection(place_ref, context, location);
    }
    fn visit_projection_elem(&mut self, place_ref: PlaceRef<'tcx>,
        elem: PlaceElem<'tcx>, context: PlaceContext, location: Location) {
        self.super_projection_elem(place_ref, elem, context, location);
    }
    fn super_place(&mut self, place: &Place<'tcx>, mut context: PlaceContext,
        location: Location) {
        if !place.projection.is_empty() && context.is_use() {
            context =
                if context.is_mutating_use() {
                    PlaceContext::MutatingUse(MutatingUseContext::Projection)
                } else {
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
                };
        }
        self.visit_local(place.local, context, location);
        self.visit_projection(place.as_ref(), context, location);
    }
    fn super_projection(&mut self, place_ref: PlaceRef<'tcx>,
        context: PlaceContext, location: Location) {
        for (base, elem) in place_ref.iter_projections().rev() {
            self.visit_projection_elem(base, elem, context, location);
        }
    }
    fn super_projection_elem(&mut self, _place_ref: PlaceRef<'tcx>,
        elem: PlaceElem<'tcx>, context: PlaceContext, location: Location) {
        match elem {
            ProjectionElem::OpaqueCast(ty) | ProjectionElem::Field(_, ty) |
                ProjectionElem::UnwrapUnsafeBinder(ty) => {
                self.visit_ty(ty, TyContext::Location(location));
            }
            ProjectionElem::Index(local) => {
                self.visit_local(local,
                    if context.is_use() {
                        PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy)
                    } else { context }, location);
            }
            ProjectionElem::Deref | ProjectionElem::Subslice {
                from: _, to: _, from_end: _ } |
                ProjectionElem::ConstantIndex {
                offset: _, min_length: _, from_end: _ } |
                ProjectionElem::Downcast(_, _) => {}
        }
    }
    /// This is called for every constant in the MIR body and every `required_consts`
    /// (i.e., including consts that have been dead-code-eliminated).
    fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>,
        location: Location) {
        self.super_const_operand(constant, location);
    }
    fn visit_ty_const(&mut self, ct: ty::Const<'tcx>, location: Location) {
        self.super_ty_const(ct, location);
    }
    fn visit_span(&mut self, span: Span) { self.super_span(span); }
    fn visit_source_info(&mut self, source_info: &SourceInfo) {
        self.super_source_info(source_info);
    }
    fn visit_ty(&mut self, ty: Ty<'tcx>, _: TyContext) { self.super_ty(ty); }
    fn visit_user_type_projection(&mut self, ty: &UserTypeProjection) {
        self.super_user_type_projection(ty);
    }
    fn visit_user_type_annotation(&mut self, index: UserTypeAnnotationIndex,
        ty: &CanonicalUserTypeAnnotation<'tcx>) {
        self.super_user_type_annotation(index, ty);
    }
    fn visit_region(&mut self, region: ty::Region<'tcx>, _: Location) {
        self.super_region(region);
    }
    fn visit_args(&mut self, args: &GenericArgsRef<'tcx>, _: Location) {
        self.super_args(args);
    }
    fn visit_local_decl(&mut self, local: Local,
        local_decl: &LocalDecl<'tcx>) {
        self.super_local_decl(local, local_decl);
    }
    fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo<'tcx>) {
        self.super_var_debug_info(var_debug_info);
    }
    fn visit_local(&mut self, local: Local, context: PlaceContext,
        location: Location) {
        self.super_local(local, context, location)
    }
    fn visit_source_scope(&mut self, scope: SourceScope) {
        self.super_source_scope(scope);
    }
    fn super_body(&mut self, body: &Body<'tcx>) {
        let span = body.span;
        if let Some(coroutine) = &body.coroutine {
            if let Some(yield_ty) = coroutine.yield_ty {
                self.visit_ty(yield_ty,
                    TyContext::YieldTy(SourceInfo::outermost(span)));
            }
            if let Some(resume_ty) = coroutine.resume_ty {
                self.visit_ty(resume_ty,
                    TyContext::ResumeTy(SourceInfo::outermost(span)));
            }
        }
        for var_debug_info in &body.var_debug_info {
            self.visit_var_debug_info(var_debug_info);
        }
        for (bb, data) in body.basic_blocks.iter_enumerated() {
            self.visit_basic_block_data(bb, data);
        }
        for scope in &body.source_scopes {
            self.visit_source_scope_data(scope);
        }
        self.visit_ty(body.return_ty(),
            TyContext::ReturnTy(SourceInfo::outermost(body.span)));
        for local in body.local_decls.indices() {
            self.visit_local_decl(local, &body.local_decls[local]);
        }
        macro_rules! type_annotations {
            (mut) => (body.user_type_annotations.iter_enumerated_mut()); () =>
            (body.user_type_annotations.iter_enumerated());
        }
        for (index, annotation) in
            body.user_type_annotations.iter_enumerated() {
            self.visit_user_type_annotation(index, annotation);
        }
        self.visit_span(body.span);
        if let Some(required_consts) = &body.required_consts {
            for const_ in required_consts {
                let location = Location::START;
                self.visit_const_operand(const_, location);
            }
        };
    }
    fn super_basic_block_data(&mut self, block: BasicBlock,
        data: &BasicBlockData<'tcx>) {
        let BasicBlockData {
                statements,
                after_last_stmt_debuginfos,
                terminator,
                is_cleanup: _ } = data;
        let mut index = 0;
        for statement in statements {
            let location = Location { block, statement_index: index };
            self.visit_statement(statement, location);
            index += 1;
        }
        let location = Location { block, statement_index: index };
        for debuginfo in after_last_stmt_debuginfos as &[_] {
            self.visit_statement_debuginfo(debuginfo, location);
        }
        if let Some(terminator) = terminator {
            self.visit_terminator(terminator, location);
        }
    }
    fn super_source_scope_data(&mut self,
        scope_data: &SourceScopeData<'tcx>) {
        let SourceScopeData {
                span,
                parent_scope,
                inlined,
                inlined_parent_scope,
                local_data: _ } = scope_data;
        self.visit_span(*span);
        if let Some(parent_scope) = parent_scope {
            self.visit_source_scope(*parent_scope);
        }
        if let Some((callee, callsite_span)) = inlined {
            let location = Location::START;
            self.visit_span(*callsite_span);
            let ty::Instance { def: callee_def, args: callee_args } = callee;
            match callee_def {
                ty::InstanceKind::Item(_def_id) => {}
                ty::InstanceKind::Intrinsic(_def_id) |
                    ty::InstanceKind::LlvmIntrinsic(_def_id) |
                    ty::InstanceKind::Shim(ty::ShimKind::VTable(_def_id)) |
                    ty::InstanceKind::Shim(ty::ShimKind::Reify(_def_id, _)) |
                    ty::InstanceKind::Virtual(_def_id, _) |
                    ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(_def_id)) |
                    ty::InstanceKind::Shim(ty::ShimKind::ClosureOnce {
                    call_once: _def_id, closure: _, track_caller: _ }) |
                    ty::InstanceKind::Shim(ty::ShimKind::ConstructCoroutineInClosure {
                    coroutine_closure_def_id: _def_id, receiver_by_ref: _ }) |
                    ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_def_id,
                    None)) => {}
                ty::InstanceKind::Shim(ty::ShimKind::FnPtr(_def_id, ty)) |
                    ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_def_id,
                    Some(ty))) |
                    ty::InstanceKind::Shim(ty::ShimKind::Clone(_def_id, ty)) |
                    ty::InstanceKind::Shim(ty::ShimKind::FnPtrAsPtr(_def_id,
                    ty)) |
                    ty::InstanceKind::Shim(ty::ShimKind::FnPtrFromPtr(_def_id,
                    ty)) |
                    ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlue(_def_id,
                    ty)) |
                    ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlueCtor(_def_id,
                    ty)) => {
                    self.visit_ty(*ty, TyContext::Location(location));
                }
                ty::InstanceKind::Shim(ty::ShimKind::FutureDropPoll(_def_id,
                    proxy_ty, impl_ty)) => {
                    self.visit_ty(*proxy_ty, TyContext::Location(location));
                    self.visit_ty(*impl_ty, TyContext::Location(location));
                }
            }
            self.visit_args(callee_args, location);
        }
        if let Some(inlined_parent_scope) = inlined_parent_scope {
            self.visit_source_scope(*inlined_parent_scope);
        }
    }
    fn super_statement_debuginfo(&mut self,
        stmt_debuginfo: &StmtDebugInfo<'tcx>, location: Location) {
        match stmt_debuginfo {
            StmtDebugInfo::AssignRef(local, place) => {
                self.visit_local(*local,
                    PlaceContext::NonUse(NonUseContext::VarDebugInfo),
                    location);
                self.visit_place(place,
                    PlaceContext::NonUse(NonUseContext::VarDebugInfo),
                    location);
            }
            StmtDebugInfo::InvalidAssign(local) => {
                self.visit_local(*local,
                    PlaceContext::NonUse(NonUseContext::VarDebugInfo),
                    location);
            }
        }
    }
    fn super_statement(&mut self, statement: &Statement<'tcx>,
        location: Location) {
        let Statement { source_info, kind, debuginfos } = statement;
        self.visit_source_info(source_info);
        for debuginfo in debuginfos as &[_] {
            self.visit_statement_debuginfo(debuginfo, location);
        }
        match kind {
            StatementKind::Assign((place, rvalue)) => {
                self.visit_assign(place, rvalue, location);
            }
            StatementKind::FakeRead((_, place)) => {
                self.visit_place(place,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                    location);
            }
            StatementKind::SetDiscriminant { place, .. } => {
                self.visit_place(place,
                    PlaceContext::MutatingUse(MutatingUseContext::SetDiscriminant),
                    location);
            }
            StatementKind::StorageLive(local) => {
                self.visit_local(*local,
                    PlaceContext::NonUse(NonUseContext::StorageLive), location);
            }
            StatementKind::StorageDead(local) => {
                self.visit_local(*local,
                    PlaceContext::NonUse(NonUseContext::StorageDead), location);
            }
            StatementKind::PlaceMention(place) => {
                self.visit_place(place,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention),
                    location);
            }
            StatementKind::AscribeUserType((place, user_ty), variance) => {
                self.visit_ascribe_user_ty(place, *variance, user_ty,
                    location);
            }
            StatementKind::Coverage(coverage) => {
                self.visit_coverage(coverage, location)
            }
            StatementKind::Intrinsic(intrinsic) => {
                match intrinsic {
                    NonDivergingIntrinsic::Assume(op) =>
                        self.visit_operand(op, location),
                    NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
                        src, dst, count }) => {
                        self.visit_operand(src, location);
                        self.visit_operand(dst, location);
                        self.visit_operand(count, location);
                    }
                }
            }
            StatementKind::BackwardIncompatibleDropHint { place, .. } => {
                self.visit_place(place,
                    PlaceContext::NonUse(NonUseContext::BackwardIncompatibleDropHint),
                    location);
            }
            StatementKind::ConstEvalCounter => {}
            StatementKind::Nop => {}
        }
    }
    fn super_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>,
        location: Location) {
        self.visit_place(place,
            PlaceContext::MutatingUse(MutatingUseContext::Store), location);
        self.visit_rvalue(rvalue, location);
    }
    fn super_terminator(&mut self, terminator: &Terminator<'tcx>,
        location: Location) {
        let Terminator { source_info, kind, attributes: _ } = terminator;
        self.visit_source_info(source_info);
        match kind {
            TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume |
                TerminatorKind::UnwindTerminate(_) |
                TerminatorKind::CoroutineDrop | TerminatorKind::Unreachable |
                TerminatorKind::FalseEdge { .. } |
                TerminatorKind::FalseUnwind { .. } => {}
            TerminatorKind::Return => {
                let local = RETURN_PLACE;
                self.visit_local(local,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
                    location);
                {
                    match (&local, &RETURN_PLACE) {
                        (left_val, right_val) => {
                            if !(*left_val == *right_val) {
                                let kind = ::core::panicking::AssertKind::Eq;
                                ::core::panicking::assert_failed(kind, &*left_val,
                                    &*right_val,
                                    ::core::option::Option::Some(format_args!("`MutVisitor` tried to mutate return place of `return` terminator")));
                            }
                        }
                    }
                };
            }
            TerminatorKind::SwitchInt { discr, targets: _ } => {
                self.visit_operand(discr, location);
            }
            TerminatorKind::Drop {
                place, target: _, unwind: _, replace: _, drop: _ } => {
                self.visit_place(place,
                    PlaceContext::MutatingUse(MutatingUseContext::Drop),
                    location);
            }
            TerminatorKind::Call {
                func,
                args,
                destination,
                target: _,
                unwind: _,
                call_source: _,
                fn_span } => {
                self.visit_span(*fn_span);
                self.visit_operand(func, location);
                for arg in args { self.visit_operand(&arg.node, location); }
                self.visit_place(destination,
                    PlaceContext::MutatingUse(MutatingUseContext::Call),
                    location);
            }
            TerminatorKind::TailCall { func, args, fn_span } => {
                self.visit_span(*fn_span);
                self.visit_operand(func, location);
                for arg in args { self.visit_operand(&arg.node, location); }
            }
            TerminatorKind::Assert {
                cond, expected: _, msg, target: _, unwind: _ } => {
                self.visit_operand(cond, location);
                self.visit_assert_message(msg, location);
            }
            TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } =>
                {
                self.visit_operand(value, location);
                self.visit_place(resume_arg,
                    PlaceContext::MutatingUse(MutatingUseContext::Yield),
                    location);
            }
            TerminatorKind::InlineAsm {
                asm_macro: _,
                template: _,
                operands,
                options: _,
                line_spans: _,
                targets: _,
                unwind: _ } => {
                for op in operands {
                    match op {
                        InlineAsmOperand::In { value, .. } => {
                            self.visit_operand(value, location);
                        }
                        InlineAsmOperand::Out { place: Some(place), .. } => {
                            self.visit_place(place,
                                PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
                                location);
                        }
                        InlineAsmOperand::InOut { in_value, out_place, .. } => {
                            self.visit_operand(in_value, location);
                            if let Some(out_place) = out_place {
                                self.visit_place(out_place,
                                    PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
                                    location);
                            }
                        }
                        InlineAsmOperand::Const { value } |
                            InlineAsmOperand::SymFn { value } => {
                            self.visit_const_operand(value, location);
                        }
                        InlineAsmOperand::Out { place: None, .. } |
                            InlineAsmOperand::SymStatic { def_id: _ } |
                            InlineAsmOperand::Label { target_index: _ } => {}
                    }
                }
            }
        }
    }
    fn super_assert_message(&mut self, msg: &AssertMessage<'tcx>,
        location: Location) {
        use crate::mir::AssertKind::*;
        match msg {
            BoundsCheck { len, index } => {
                self.visit_operand(len, location);
                self.visit_operand(index, location);
            }
            Overflow(_, l, r) => {
                self.visit_operand(l, location);
                self.visit_operand(r, location);
            }
            OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) |
                InvalidEnumConstruction(op) => {
                self.visit_operand(op, location);
            }
            ResumedAfterReturn(_) | ResumedAfterPanic(_) |
                NullPointerDereference | NullReferenceConstructed |
                ResumedAfterDrop(_) => {}
            MisalignedPointerDereference { required, found } => {
                self.visit_operand(required, location);
                self.visit_operand(found, location);
            }
        }
    }
    fn super_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
        match rvalue {
            Rvalue::Use(operand, _with_retag) => {
                self.visit_operand(operand, location);
            }
            Rvalue::Repeat(value, ct) => {
                self.visit_operand(value, location);
                self.visit_ty_const(*ct, location);
            }
            Rvalue::ThreadLocalRef(_) => {}
            Rvalue::Ref(r, bk, path) => {
                self.visit_region(*r, location);
                let ctx =
                    match bk {
                        BorrowKind::Shared =>
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow),
                        BorrowKind::Fake(_) =>
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::FakeBorrow),
                        BorrowKind::Mut { .. } =>
                            PlaceContext::MutatingUse(MutatingUseContext::Borrow),
                    };
                self.visit_place(path, ctx, location);
            }
            Rvalue::Reborrow(target, mutability, place) => {
                self.visit_ty(*target, TyContext::Location(location));
                self.visit_place(place,
                    match mutability {
                        Mutability::Not =>
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow),
                        Mutability::Mut =>
                            PlaceContext::MutatingUse(MutatingUseContext::Borrow),
                    }, location);
            }
            Rvalue::CopyForDeref(place) => {
                self.visit_place(place,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                    location);
            }
            Rvalue::RawPtr(m, path) => {
                let ctx =
                    match m {
                        RawPtrKind::Mut =>
                            PlaceContext::MutatingUse(MutatingUseContext::RawBorrow),
                        RawPtrKind::Const =>
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow),
                        RawPtrKind::FakeForPtrMetadata =>
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                    };
                self.visit_place(path, ctx, location);
            }
            Rvalue::Cast(_cast_kind, operand, ty) => {
                self.visit_operand(operand, location);
                self.visit_ty(*ty, TyContext::Location(location));
            }
            Rvalue::BinaryOp(_bin_op, (lhs, rhs)) => {
                self.visit_operand(lhs, location);
                self.visit_operand(rhs, location);
            }
            Rvalue::UnaryOp(_un_op, op) => {
                self.visit_operand(op, location);
            }
            Rvalue::Discriminant(place) => {
                self.visit_place(place,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                    location);
            }
            Rvalue::Aggregate(kind, operands) => {
                let kind = &**kind;
                match kind {
                    AggregateKind::Array(ty) => {
                        self.visit_ty(*ty, TyContext::Location(location));
                    }
                    AggregateKind::Tuple => {}
                    AggregateKind::Adt(_adt_def, _variant_index, args,
                        _user_args, _active_field_index) => {
                        self.visit_args(args, location);
                    }
                    AggregateKind::Closure(_, closure_args) => {
                        self.visit_args(closure_args, location);
                    }
                    AggregateKind::Coroutine(_, coroutine_args) => {
                        self.visit_args(coroutine_args, location);
                    }
                    AggregateKind::CoroutineClosure(_, coroutine_closure_args)
                        => {
                        self.visit_args(coroutine_closure_args, location);
                    }
                    AggregateKind::RawPtr(ty, _) => {
                        self.visit_ty(*ty, TyContext::Location(location));
                    }
                }
                for operand in operands {
                    self.visit_operand(operand, location);
                }
            }
            Rvalue::WrapUnsafeBinder(op, ty) => {
                self.visit_operand(op, location);
                self.visit_ty(*ty, TyContext::Location(location));
            }
        }
    }
    fn super_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
        match operand {
            Operand::Copy(place) => {
                self.visit_place(place,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
                    location);
            }
            Operand::Move(place) => {
                self.visit_place(place,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
                    location);
            }
            Operand::Constant(constant) => {
                self.visit_const_operand(constant, location);
            }
            Operand::RuntimeChecks(_) => {}
        }
    }
    fn super_ascribe_user_ty(&mut self, place: &Place<'tcx>,
        variance: ty::Variance, user_ty: &UserTypeProjection,
        location: Location) {
        self.visit_place(place,
            PlaceContext::NonUse(NonUseContext::AscribeUserTy(variance)),
            location);
        self.visit_user_type_projection(user_ty);
    }
    fn super_coverage(&mut self, _kind: &coverage::CoverageKind,
        _location: Location) {}
    fn super_local_decl(&mut self, local: Local,
        local_decl: &LocalDecl<'tcx>) {
        let LocalDecl { mutability: _, ty, user_ty, source_info, local_info: _
                } = local_decl;
        self.visit_source_info(source_info);
        self.visit_ty(*ty,
            TyContext::LocalDecl { local, source_info: *source_info });
        if let Some(user_ty) = user_ty {
            for user_ty in &user_ty.contents {
                self.visit_user_type_projection(user_ty);
            }
        }
    }
    fn super_local(&mut self, _local: Local, _context: PlaceContext,
        _location: Location) {}
    fn super_var_debug_info(&mut self, var_debug_info: &VarDebugInfo<'tcx>) {
        let VarDebugInfo {
                name: _, source_info, composite, value, argument_index: _ } =
            var_debug_info;
        self.visit_source_info(source_info);
        let location = Location::START;
        if let Some(VarDebugInfoFragment { ty, projection }) = composite {
            self.visit_ty(*ty, TyContext::Location(location));
            for elem in projection {
                let ProjectionElem::Field(_, ty) =
                    elem else {
                        crate::util::bug::bug_fmt(format_args!("impossible case reached"))
                    };
                self.visit_ty(*ty, TyContext::Location(location));
            }
        }
        match value {
            VarDebugInfoContents::Const(c) =>
                self.visit_const_operand(c, location),
            VarDebugInfoContents::Place(place) =>
                self.visit_place(place,
                    PlaceContext::NonUse(NonUseContext::VarDebugInfo),
                    location),
        }
    }
    fn super_source_scope(&mut self, _scope: SourceScope) {}
    fn super_const_operand(&mut self, constant: &ConstOperand<'tcx>,
        location: Location) {
        let ConstOperand { span, user_ty: _, const_ } = constant;
        self.visit_span(*span);
        match const_ {
            Const::Ty(_, ct) => self.visit_ty_const(*ct, location),
            Const::Val(_, ty) | Const::Unevaluated(_, ty) => {
                self.visit_ty(*ty, TyContext::Location(location));
            }
        }
    }
    fn super_ty_const(&mut self, _ct: ty::Const<'tcx>, _location: Location) {}
    fn super_span(&mut self, _span: Span) {}
    fn super_source_info(&mut self, source_info: &SourceInfo) {
        let SourceInfo { span, scope } = source_info;
        self.visit_span(*span);
        self.visit_source_scope(*scope);
    }
    fn super_user_type_projection(&mut self, _ty: &UserTypeProjection) {}
    fn super_user_type_annotation(&mut self, _index: UserTypeAnnotationIndex,
        ty: &CanonicalUserTypeAnnotation<'tcx>) {
        self.visit_span(ty.span);
        self.visit_ty(ty.inferred_ty, TyContext::UserTy(ty.span));
    }
    fn super_ty(&mut self, _ty: Ty<'tcx>) {}
    fn super_region(&mut self, _region: ty::Region<'tcx>) {}
    fn super_args(&mut self, _args: &GenericArgsRef<'tcx>) {}
    fn visit_location(&mut self, body: &Body<'tcx>, location: Location) {
        let basic_block = &body.basic_blocks[location.block];
        if basic_block.statements.len() == location.statement_index {
            if let Some(ref terminator) = basic_block.terminator {
                self.visit_terminator(terminator, location)
            }
        } else {
            let statement = &basic_block.statements[location.statement_index];
            self.visit_statement(statement, location)
        }
    }
}make_mir_visitor!(Visitor,);
1275pub trait MutVisitor<'tcx> {
    fn visit_body(&mut self, body: &mut Body<'tcx>) { self.super_body(body); }
    fn visit_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
        self.super_body_preserves_cfg(body);
    }
    fn super_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
        let span = body.span;
        if let Some(coroutine) = &mut body.coroutine {
            if let Some(yield_ty) = &mut coroutine.yield_ty {
                self.visit_ty(yield_ty,
                    TyContext::YieldTy(SourceInfo::outermost(span)));
            }
            if let Some(resume_ty) = &mut coroutine.resume_ty {
                self.visit_ty(resume_ty,
                    TyContext::ResumeTy(SourceInfo::outermost(span)));
            }
        }
        for var_debug_info in &mut body.var_debug_info {
            self.visit_var_debug_info(var_debug_info);
        }
        for (bb, data) in
            body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
            self.visit_basic_block_data(bb, data);
        }
        for scope in &mut body.source_scopes {
            self.visit_source_scope_data(scope);
        }
        self.visit_ty(&mut body.return_ty(),
            TyContext::ReturnTy(SourceInfo::outermost(body.span)));
        for local in body.local_decls.indices() {
            self.visit_local_decl(local, &mut body.local_decls[local]);
        }
        macro_rules! type_annotations {
            (mut) => (body.user_type_annotations.iter_enumerated_mut()); () =>
            (body.user_type_annotations.iter_enumerated());
        }
        for (index, annotation) in
            body.user_type_annotations.iter_enumerated_mut() {
            self.visit_user_type_annotation(index, annotation);
        }
        self.visit_span(&mut body.span);
        if let Some(required_consts) = &mut body.required_consts {
            for const_ in required_consts {
                let location = Location::START;
                self.visit_const_operand(const_, location);
            }
        };
    }
    fn visit_basic_block_data(&mut self, block: BasicBlock,
        data: &mut BasicBlockData<'tcx>) {
        self.super_basic_block_data(block, data);
    }
    fn visit_source_scope_data(&mut self,
        scope_data: &mut SourceScopeData<'tcx>) {
        self.super_source_scope_data(scope_data);
    }
    fn visit_statement_debuginfo(&mut self,
        stmt_debuginfo: &mut StmtDebugInfo<'tcx>, location: Location) {
        self.super_statement_debuginfo(stmt_debuginfo, location);
    }
    fn visit_statement(&mut self, statement: &mut Statement<'tcx>,
        location: Location) {
        self.super_statement(statement, location);
    }
    fn visit_assign(&mut self, place: &mut Place<'tcx>,
        rvalue: &mut Rvalue<'tcx>, location: Location) {
        self.super_assign(place, rvalue, location);
    }
    fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>,
        location: Location) {
        self.super_terminator(terminator, location);
    }
    fn visit_assert_message(&mut self, msg: &mut AssertMessage<'tcx>,
        location: Location) {
        self.super_assert_message(msg, location);
    }
    fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>,
        location: Location) {
        self.super_rvalue(rvalue, location);
    }
    fn visit_operand(&mut self, operand: &mut Operand<'tcx>,
        location: Location) {
        self.super_operand(operand, location);
    }
    fn visit_ascribe_user_ty(&mut self, place: &mut Place<'tcx>,
        variance: &mut ty::Variance, user_ty: &mut UserTypeProjection,
        location: Location) {
        self.super_ascribe_user_ty(place, variance, user_ty, location);
    }
    fn visit_coverage(&mut self, kind: &mut coverage::CoverageKind,
        location: Location) {
        self.super_coverage(kind, location);
    }
    fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext,
        location: Location) {
        self.super_place(place, context, location);
    }
    fn tcx<'a>(&'a self)
    -> TyCtxt<'tcx>;
    fn super_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext,
        location: Location) {
        self.visit_local(&mut place.local, context, location);
        if let Some(new_projection) =
                self.process_projection(&place.projection, location) {
            place.projection = self.tcx().mk_place_elems(&new_projection);
        }
    }
    fn process_projection<'a>(&mut self, projection: &'a [PlaceElem<'tcx>],
        location: Location) -> Option<Vec<PlaceElem<'tcx>>> {
        let mut projection = Cow::Borrowed(projection);
        for i in 0..projection.len() {
            if let Some(&elem) = projection.get(i) {
                if let Some(elem) =
                        self.process_projection_elem(elem, location) {
                    let vec = projection.to_mut();
                    vec[i] = elem;
                }
            }
        }
        match projection {
            Cow::Borrowed(_) => None,
            Cow::Owned(vec) => Some(vec),
        }
    }
    fn process_projection_elem(&mut self, elem: PlaceElem<'tcx>,
        location: Location) -> Option<PlaceElem<'tcx>> {
        match elem {
            PlaceElem::Index(local) => {
                let mut new_local = local;
                self.visit_local(&mut new_local,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
                    location);
                if new_local == local {
                    None
                } else { Some(PlaceElem::Index(new_local)) }
            }
            PlaceElem::Field(field, ty) => {
                let mut new_ty = ty;
                self.visit_ty(&mut new_ty, TyContext::Location(location));
                if ty != new_ty {
                    Some(PlaceElem::Field(field, new_ty))
                } else { None }
            }
            PlaceElem::OpaqueCast(ty) => {
                let mut new_ty = ty;
                self.visit_ty(&mut new_ty, TyContext::Location(location));
                if ty != new_ty {
                    Some(PlaceElem::OpaqueCast(new_ty))
                } else { None }
            }
            PlaceElem::UnwrapUnsafeBinder(ty) => {
                let mut new_ty = ty;
                self.visit_ty(&mut new_ty, TyContext::Location(location));
                if ty != new_ty {
                    Some(PlaceElem::UnwrapUnsafeBinder(new_ty))
                } else { None }
            }
            PlaceElem::Deref | PlaceElem::ConstantIndex { .. } |
                PlaceElem::Subslice { .. } | PlaceElem::Downcast(..) => None,
        }
    }
    /// This is called for every constant in the MIR body and every `required_consts`
    /// (i.e., including consts that have been dead-code-eliminated).
    fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>,
        location: Location) {
        self.super_const_operand(constant, location);
    }
    fn visit_ty_const(&mut self, ct: &mut ty::Const<'tcx>,
        location: Location) {
        self.super_ty_const(ct, location);
    }
    fn visit_span(&mut self, span: &mut Span) { self.super_span(span); }
    fn visit_source_info(&mut self, source_info: &mut SourceInfo) {
        self.super_source_info(source_info);
    }
    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
        self.super_ty(ty);
    }
    fn visit_user_type_projection(&mut self, ty: &mut UserTypeProjection) {
        self.super_user_type_projection(ty);
    }
    fn visit_user_type_annotation(&mut self, index: UserTypeAnnotationIndex,
        ty: &mut CanonicalUserTypeAnnotation<'tcx>) {
        self.super_user_type_annotation(index, ty);
    }
    fn visit_region(&mut self, region: &mut ty::Region<'tcx>, _: Location) {
        self.super_region(region);
    }
    fn visit_args(&mut self, args: &mut GenericArgsRef<'tcx>, _: Location) {
        self.super_args(args);
    }
    fn visit_local_decl(&mut self, local: Local,
        local_decl: &mut LocalDecl<'tcx>) {
        self.super_local_decl(local, local_decl);
    }
    fn visit_var_debug_info(&mut self,
        var_debug_info: &mut VarDebugInfo<'tcx>) {
        self.super_var_debug_info(var_debug_info);
    }
    fn visit_local(&mut self, local: &mut Local, context: PlaceContext,
        location: Location) {
        self.super_local(local, context, location)
    }
    fn visit_source_scope(&mut self, scope: &mut SourceScope) {
        self.super_source_scope(scope);
    }
    fn super_body(&mut self, body: &mut Body<'tcx>) {
        let span = body.span;
        if let Some(coroutine) = &mut body.coroutine {
            if let Some(yield_ty) = &mut coroutine.yield_ty {
                self.visit_ty(yield_ty,
                    TyContext::YieldTy(SourceInfo::outermost(span)));
            }
            if let Some(resume_ty) = &mut coroutine.resume_ty {
                self.visit_ty(resume_ty,
                    TyContext::ResumeTy(SourceInfo::outermost(span)));
            }
        }
        for var_debug_info in &mut body.var_debug_info {
            self.visit_var_debug_info(var_debug_info);
        }
        for (bb, data) in body.basic_blocks.as_mut().iter_enumerated_mut() {
            self.visit_basic_block_data(bb, data);
        }
        for scope in &mut body.source_scopes {
            self.visit_source_scope_data(scope);
        }
        self.visit_ty(&mut body.return_ty(),
            TyContext::ReturnTy(SourceInfo::outermost(body.span)));
        for local in body.local_decls.indices() {
            self.visit_local_decl(local, &mut body.local_decls[local]);
        }
        macro_rules! type_annotations {
            (mut) => (body.user_type_annotations.iter_enumerated_mut()); () =>
            (body.user_type_annotations.iter_enumerated());
        }
        for (index, annotation) in
            body.user_type_annotations.iter_enumerated_mut() {
            self.visit_user_type_annotation(index, annotation);
        }
        self.visit_span(&mut body.span);
        if let Some(required_consts) = &mut body.required_consts {
            for const_ in required_consts {
                let location = Location::START;
                self.visit_const_operand(const_, location);
            }
        };
    }
    fn super_basic_block_data(&mut self, block: BasicBlock,
        data: &mut BasicBlockData<'tcx>) {
        let BasicBlockData {
                statements,
                after_last_stmt_debuginfos,
                terminator,
                is_cleanup: _ } = data;
        let mut index = 0;
        for statement in statements {
            let location = Location { block, statement_index: index };
            self.visit_statement(statement, location);
            index += 1;
        }
        let location = Location { block, statement_index: index };
        for debuginfo in after_last_stmt_debuginfos as &mut [_] {
            self.visit_statement_debuginfo(debuginfo, location);
        }
        if let Some(terminator) = terminator {
            self.visit_terminator(terminator, location);
        }
    }
    fn super_source_scope_data(&mut self,
        scope_data: &mut SourceScopeData<'tcx>) {
        let SourceScopeData {
                span,
                parent_scope,
                inlined,
                inlined_parent_scope,
                local_data: _ } = scope_data;
        self.visit_span(&mut *span);
        if let Some(parent_scope) = parent_scope {
            self.visit_source_scope(&mut *parent_scope);
        }
        if let Some((callee, callsite_span)) = inlined {
            let location = Location::START;
            self.visit_span(&mut *callsite_span);
            let ty::Instance { def: callee_def, args: callee_args } = callee;
            match callee_def {
                ty::InstanceKind::Item(_def_id) => {}
                ty::InstanceKind::Intrinsic(_def_id) |
                    ty::InstanceKind::LlvmIntrinsic(_def_id) |
                    ty::InstanceKind::Shim(ty::ShimKind::VTable(_def_id)) |
                    ty::InstanceKind::Shim(ty::ShimKind::Reify(_def_id, _)) |
                    ty::InstanceKind::Virtual(_def_id, _) |
                    ty::InstanceKind::Shim(ty::ShimKind::ThreadLocal(_def_id)) |
                    ty::InstanceKind::Shim(ty::ShimKind::ClosureOnce {
                    call_once: _def_id, closure: _, track_caller: _ }) |
                    ty::InstanceKind::Shim(ty::ShimKind::ConstructCoroutineInClosure {
                    coroutine_closure_def_id: _def_id, receiver_by_ref: _ }) |
                    ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_def_id,
                    None)) => {}
                ty::InstanceKind::Shim(ty::ShimKind::FnPtr(_def_id, ty)) |
                    ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_def_id,
                    Some(ty))) |
                    ty::InstanceKind::Shim(ty::ShimKind::Clone(_def_id, ty)) |
                    ty::InstanceKind::Shim(ty::ShimKind::FnPtrAsPtr(_def_id,
                    ty)) |
                    ty::InstanceKind::Shim(ty::ShimKind::FnPtrFromPtr(_def_id,
                    ty)) |
                    ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlue(_def_id,
                    ty)) |
                    ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlueCtor(_def_id,
                    ty)) => {
                    self.visit_ty(&mut *ty, TyContext::Location(location));
                }
                ty::InstanceKind::Shim(ty::ShimKind::FutureDropPoll(_def_id,
                    proxy_ty, impl_ty)) => {
                    self.visit_ty(&mut *proxy_ty,
                        TyContext::Location(location));
                    self.visit_ty(&mut *impl_ty, TyContext::Location(location));
                }
            }
            self.visit_args(callee_args, location);
        }
        if let Some(inlined_parent_scope) = inlined_parent_scope {
            self.visit_source_scope(&mut *inlined_parent_scope);
        }
    }
    fn super_statement_debuginfo(&mut self,
        stmt_debuginfo: &mut StmtDebugInfo<'tcx>, location: Location) {
        match stmt_debuginfo {
            StmtDebugInfo::AssignRef(local, place) => {
                self.visit_local(&mut *local,
                    PlaceContext::NonUse(NonUseContext::VarDebugInfo),
                    location);
                self.visit_place(place,
                    PlaceContext::NonUse(NonUseContext::VarDebugInfo),
                    location);
            }
            StmtDebugInfo::InvalidAssign(local) => {
                self.visit_local(&mut *local,
                    PlaceContext::NonUse(NonUseContext::VarDebugInfo),
                    location);
            }
        }
    }
    fn super_statement(&mut self, statement: &mut Statement<'tcx>,
        location: Location) {
        let Statement { source_info, kind, debuginfos } = statement;
        self.visit_source_info(source_info);
        for debuginfo in debuginfos as &mut [_] {
            self.visit_statement_debuginfo(debuginfo, location);
        }
        match kind {
            StatementKind::Assign((place, rvalue)) => {
                self.visit_assign(place, rvalue, location);
            }
            StatementKind::FakeRead((_, place)) => {
                self.visit_place(place,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                    location);
            }
            StatementKind::SetDiscriminant { place, .. } => {
                self.visit_place(place,
                    PlaceContext::MutatingUse(MutatingUseContext::SetDiscriminant),
                    location);
            }
            StatementKind::StorageLive(local) => {
                self.visit_local(&mut *local,
                    PlaceContext::NonUse(NonUseContext::StorageLive), location);
            }
            StatementKind::StorageDead(local) => {
                self.visit_local(&mut *local,
                    PlaceContext::NonUse(NonUseContext::StorageDead), location);
            }
            StatementKind::PlaceMention(place) => {
                self.visit_place(place,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention),
                    location);
            }
            StatementKind::AscribeUserType((place, user_ty), variance) => {
                self.visit_ascribe_user_ty(place, &mut *variance, user_ty,
                    location);
            }
            StatementKind::Coverage(coverage) => {
                self.visit_coverage(coverage, location)
            }
            StatementKind::Intrinsic(intrinsic) => {
                match intrinsic {
                    NonDivergingIntrinsic::Assume(op) =>
                        self.visit_operand(op, location),
                    NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
                        src, dst, count }) => {
                        self.visit_operand(src, location);
                        self.visit_operand(dst, location);
                        self.visit_operand(count, location);
                    }
                }
            }
            StatementKind::BackwardIncompatibleDropHint { place, .. } => {
                self.visit_place(place,
                    PlaceContext::NonUse(NonUseContext::BackwardIncompatibleDropHint),
                    location);
            }
            StatementKind::ConstEvalCounter => {}
            StatementKind::Nop => {}
        }
    }
    fn super_assign(&mut self, place: &mut Place<'tcx>,
        rvalue: &mut Rvalue<'tcx>, location: Location) {
        self.visit_place(place,
            PlaceContext::MutatingUse(MutatingUseContext::Store), location);
        self.visit_rvalue(rvalue, location);
    }
    fn super_terminator(&mut self, terminator: &mut Terminator<'tcx>,
        location: Location) {
        let Terminator { source_info, kind, attributes: _ } = terminator;
        self.visit_source_info(source_info);
        match kind {
            TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume |
                TerminatorKind::UnwindTerminate(_) |
                TerminatorKind::CoroutineDrop | TerminatorKind::Unreachable |
                TerminatorKind::FalseEdge { .. } |
                TerminatorKind::FalseUnwind { .. } => {}
            TerminatorKind::Return => {
                let mut local = RETURN_PLACE;
                self.visit_local(&mut local,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
                    location);
                {
                    match (&local, &RETURN_PLACE) {
                        (left_val, right_val) => {
                            if !(*left_val == *right_val) {
                                let kind = ::core::panicking::AssertKind::Eq;
                                ::core::panicking::assert_failed(kind, &*left_val,
                                    &*right_val,
                                    ::core::option::Option::Some(format_args!("`MutVisitor` tried to mutate return place of `return` terminator")));
                            }
                        }
                    }
                };
            }
            TerminatorKind::SwitchInt { discr, targets: _ } => {
                self.visit_operand(discr, location);
            }
            TerminatorKind::Drop {
                place, target: _, unwind: _, replace: _, drop: _ } => {
                self.visit_place(place,
                    PlaceContext::MutatingUse(MutatingUseContext::Drop),
                    location);
            }
            TerminatorKind::Call {
                func,
                args,
                destination,
                target: _,
                unwind: _,
                call_source: _,
                fn_span } => {
                self.visit_span(&mut *fn_span);
                self.visit_operand(func, location);
                for arg in args {
                    self.visit_operand(&mut arg.node, location);
                }
                self.visit_place(destination,
                    PlaceContext::MutatingUse(MutatingUseContext::Call),
                    location);
            }
            TerminatorKind::TailCall { func, args, fn_span } => {
                self.visit_span(&mut *fn_span);
                self.visit_operand(func, location);
                for arg in args {
                    self.visit_operand(&mut arg.node, location);
                }
            }
            TerminatorKind::Assert {
                cond, expected: _, msg, target: _, unwind: _ } => {
                self.visit_operand(cond, location);
                self.visit_assert_message(msg, location);
            }
            TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } =>
                {
                self.visit_operand(value, location);
                self.visit_place(resume_arg,
                    PlaceContext::MutatingUse(MutatingUseContext::Yield),
                    location);
            }
            TerminatorKind::InlineAsm {
                asm_macro: _,
                template: _,
                operands,
                options: _,
                line_spans: _,
                targets: _,
                unwind: _ } => {
                for op in operands {
                    match op {
                        InlineAsmOperand::In { value, .. } => {
                            self.visit_operand(value, location);
                        }
                        InlineAsmOperand::Out { place: Some(place), .. } => {
                            self.visit_place(place,
                                PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
                                location);
                        }
                        InlineAsmOperand::InOut { in_value, out_place, .. } => {
                            self.visit_operand(in_value, location);
                            if let Some(out_place) = out_place {
                                self.visit_place(out_place,
                                    PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
                                    location);
                            }
                        }
                        InlineAsmOperand::Const { value } |
                            InlineAsmOperand::SymFn { value } => {
                            self.visit_const_operand(value, location);
                        }
                        InlineAsmOperand::Out { place: None, .. } |
                            InlineAsmOperand::SymStatic { def_id: _ } |
                            InlineAsmOperand::Label { target_index: _ } => {}
                    }
                }
            }
        }
    }
    fn super_assert_message(&mut self, msg: &mut AssertMessage<'tcx>,
        location: Location) {
        use crate::mir::AssertKind::*;
        match msg {
            BoundsCheck { len, index } => {
                self.visit_operand(len, location);
                self.visit_operand(index, location);
            }
            Overflow(_, l, r) => {
                self.visit_operand(l, location);
                self.visit_operand(r, location);
            }
            OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) |
                InvalidEnumConstruction(op) => {
                self.visit_operand(op, location);
            }
            ResumedAfterReturn(_) | ResumedAfterPanic(_) |
                NullPointerDereference | NullReferenceConstructed |
                ResumedAfterDrop(_) => {}
            MisalignedPointerDereference { required, found } => {
                self.visit_operand(required, location);
                self.visit_operand(found, location);
            }
        }
    }
    fn super_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>,
        location: Location) {
        match rvalue {
            Rvalue::Use(operand, _with_retag) => {
                self.visit_operand(operand, location);
            }
            Rvalue::Repeat(value, ct) => {
                self.visit_operand(value, location);
                self.visit_ty_const(&mut *ct, location);
            }
            Rvalue::ThreadLocalRef(_) => {}
            Rvalue::Ref(r, bk, path) => {
                self.visit_region(&mut *r, location);
                let ctx =
                    match bk {
                        BorrowKind::Shared =>
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow),
                        BorrowKind::Fake(_) =>
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::FakeBorrow),
                        BorrowKind::Mut { .. } =>
                            PlaceContext::MutatingUse(MutatingUseContext::Borrow),
                    };
                self.visit_place(path, ctx, location);
            }
            Rvalue::Reborrow(target, mutability, place) => {
                self.visit_ty(&mut *target, TyContext::Location(location));
                self.visit_place(place,
                    match mutability {
                        Mutability::Not =>
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow),
                        Mutability::Mut =>
                            PlaceContext::MutatingUse(MutatingUseContext::Borrow),
                    }, location);
            }
            Rvalue::CopyForDeref(place) => {
                self.visit_place(place,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                    location);
            }
            Rvalue::RawPtr(m, path) => {
                let ctx =
                    match m {
                        RawPtrKind::Mut =>
                            PlaceContext::MutatingUse(MutatingUseContext::RawBorrow),
                        RawPtrKind::Const =>
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow),
                        RawPtrKind::FakeForPtrMetadata =>
                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                    };
                self.visit_place(path, ctx, location);
            }
            Rvalue::Cast(_cast_kind, operand, ty) => {
                self.visit_operand(operand, location);
                self.visit_ty(&mut *ty, TyContext::Location(location));
            }
            Rvalue::BinaryOp(_bin_op, (lhs, rhs)) => {
                self.visit_operand(lhs, location);
                self.visit_operand(rhs, location);
            }
            Rvalue::UnaryOp(_un_op, op) => {
                self.visit_operand(op, location);
            }
            Rvalue::Discriminant(place) => {
                self.visit_place(place,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
                    location);
            }
            Rvalue::Aggregate(kind, operands) => {
                let kind = &mut **kind;
                match kind {
                    AggregateKind::Array(ty) => {
                        self.visit_ty(&mut *ty, TyContext::Location(location));
                    }
                    AggregateKind::Tuple => {}
                    AggregateKind::Adt(_adt_def, _variant_index, args,
                        _user_args, _active_field_index) => {
                        self.visit_args(args, location);
                    }
                    AggregateKind::Closure(_, closure_args) => {
                        self.visit_args(closure_args, location);
                    }
                    AggregateKind::Coroutine(_, coroutine_args) => {
                        self.visit_args(coroutine_args, location);
                    }
                    AggregateKind::CoroutineClosure(_, coroutine_closure_args)
                        => {
                        self.visit_args(coroutine_closure_args, location);
                    }
                    AggregateKind::RawPtr(ty, _) => {
                        self.visit_ty(&mut *ty, TyContext::Location(location));
                    }
                }
                for operand in operands {
                    self.visit_operand(operand, location);
                }
            }
            Rvalue::WrapUnsafeBinder(op, ty) => {
                self.visit_operand(op, location);
                self.visit_ty(&mut *ty, TyContext::Location(location));
            }
        }
    }
    fn super_operand(&mut self, operand: &mut Operand<'tcx>,
        location: Location) {
        match operand {
            Operand::Copy(place) => {
                self.visit_place(place,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
                    location);
            }
            Operand::Move(place) => {
                self.visit_place(place,
                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
                    location);
            }
            Operand::Constant(constant) => {
                self.visit_const_operand(constant, location);
            }
            Operand::RuntimeChecks(_) => {}
        }
    }
    fn super_ascribe_user_ty(&mut self, place: &mut Place<'tcx>,
        variance: &mut ty::Variance, user_ty: &mut UserTypeProjection,
        location: Location) {
        self.visit_place(place,
            PlaceContext::NonUse(NonUseContext::AscribeUserTy(*&mut *variance)),
            location);
        self.visit_user_type_projection(user_ty);
    }
    fn super_coverage(&mut self, _kind: &mut coverage::CoverageKind,
        _location: Location) {}
    fn super_local_decl(&mut self, local: Local,
        local_decl: &mut LocalDecl<'tcx>) {
        let LocalDecl { mutability: _, ty, user_ty, source_info, local_info: _
                } = local_decl;
        self.visit_source_info(source_info);
        self.visit_ty(&mut *ty,
            TyContext::LocalDecl { local, source_info: *source_info });
        if let Some(user_ty) = user_ty {
            for user_ty in &mut user_ty.contents {
                self.visit_user_type_projection(user_ty);
            }
        }
    }
    fn super_local(&mut self, _local: &mut Local, _context: PlaceContext,
        _location: Location) {}
    fn super_var_debug_info(&mut self,
        var_debug_info: &mut VarDebugInfo<'tcx>) {
        let VarDebugInfo {
                name: _, source_info, composite, value, argument_index: _ } =
            var_debug_info;
        self.visit_source_info(source_info);
        let location = Location::START;
        if let Some(VarDebugInfoFragment { ty, projection }) = composite {
            self.visit_ty(&mut *ty, TyContext::Location(location));
            for elem in projection {
                let ProjectionElem::Field(_, ty) =
                    elem else {
                        crate::util::bug::bug_fmt(format_args!("impossible case reached"))
                    };
                self.visit_ty(&mut *ty, TyContext::Location(location));
            }
        }
        match value {
            VarDebugInfoContents::Const(c) =>
                self.visit_const_operand(c, location),
            VarDebugInfoContents::Place(place) =>
                self.visit_place(place,
                    PlaceContext::NonUse(NonUseContext::VarDebugInfo),
                    location),
        }
    }
    fn super_source_scope(&mut self, _scope: &mut SourceScope) {}
    fn super_const_operand(&mut self, constant: &mut ConstOperand<'tcx>,
        location: Location) {
        let ConstOperand { span, user_ty: _, const_ } = constant;
        self.visit_span(&mut *span);
        match const_ {
            Const::Ty(_, ct) => self.visit_ty_const(&mut *ct, location),
            Const::Val(_, ty) | Const::Unevaluated(_, ty) => {
                self.visit_ty(&mut *ty, TyContext::Location(location));
            }
        }
    }
    fn super_ty_const(&mut self, _ct: &mut ty::Const<'tcx>,
        _location: Location) {}
    fn super_span(&mut self, _span: &mut Span) {}
    fn super_source_info(&mut self, source_info: &mut SourceInfo) {
        let SourceInfo { span, scope } = source_info;
        self.visit_span(&mut *span);
        self.visit_source_scope(&mut *scope);
    }
    fn super_user_type_projection(&mut self, _ty: &mut UserTypeProjection) {}
    fn super_user_type_annotation(&mut self, _index: UserTypeAnnotationIndex,
        ty: &mut CanonicalUserTypeAnnotation<'tcx>) {
        self.visit_span(&mut ty.span);
        self.visit_ty(&mut ty.inferred_ty, TyContext::UserTy(ty.span));
    }
    fn super_ty(&mut self, _ty: &mut Ty<'tcx>) {}
    fn super_region(&mut self, _region: &mut ty::Region<'tcx>) {}
    fn super_args(&mut self, _args: &mut GenericArgsRef<'tcx>) {}
    fn visit_location(&mut self, body: &mut Body<'tcx>, location: Location) {
        let basic_block = &mut body.basic_blocks.as_mut()[location.block];
        if basic_block.statements.len() == location.statement_index {
            if let Some(ref mut terminator) = basic_block.terminator {
                self.visit_terminator(terminator, location)
            }
        } else {
            let statement =
                &mut basic_block.statements[location.statement_index];
            self.visit_statement(statement, location)
        }
    }
}make_mir_visitor!(MutVisitor, mut);
1276
1277/// Extra information passed to `visit_ty` and friends to give context
1278/// about where the type etc appears.
1279#[derive(#[automatically_derived]
impl ::core::marker::Copy for TyContext { }Copy, #[automatically_derived]
impl ::core::clone::Clone for TyContext {
    #[inline]
    fn clone(&self) -> TyContext {
        let _: ::core::clone::AssertParamIsClone<Local>;
        let _: ::core::clone::AssertParamIsClone<SourceInfo>;
        let _: ::core::clone::AssertParamIsClone<Span>;
        let _: ::core::clone::AssertParamIsClone<Location>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for TyContext {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            TyContext::LocalDecl { local: __self_0, source_info: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "LocalDecl", "local", __self_0, "source_info", &__self_1),
            TyContext::UserTy(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "UserTy",
                    &__self_0),
            TyContext::ReturnTy(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ReturnTy", &__self_0),
            TyContext::YieldTy(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "YieldTy", &__self_0),
            TyContext::ResumeTy(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ResumeTy", &__self_0),
            TyContext::Location(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Location", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::hash::Hash for TyContext {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            TyContext::LocalDecl { local: __self_0, source_info: __self_1 } =>
                {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            TyContext::UserTy(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            TyContext::ReturnTy(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            TyContext::YieldTy(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            TyContext::ResumeTy(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            TyContext::Location(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash, #[automatically_derived]
impl ::core::cmp::Eq for TyContext {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Local>;
        let _: ::core::cmp::AssertParamIsEq<SourceInfo>;
        let _: ::core::cmp::AssertParamIsEq<Span>;
        let _: ::core::cmp::AssertParamIsEq<Location>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for TyContext {
    #[inline]
    fn eq(&self, other: &TyContext) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (TyContext::LocalDecl { local: __self_0, source_info: __self_1
                    }, TyContext::LocalDecl {
                    local: __arg1_0, source_info: __arg1_1 }) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (TyContext::UserTy(__self_0), TyContext::UserTy(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (TyContext::ReturnTy(__self_0), TyContext::ReturnTy(__arg1_0))
                    => __self_0 == __arg1_0,
                (TyContext::YieldTy(__self_0), TyContext::YieldTy(__arg1_0))
                    => __self_0 == __arg1_0,
                (TyContext::ResumeTy(__self_0), TyContext::ResumeTy(__arg1_0))
                    => __self_0 == __arg1_0,
                (TyContext::Location(__self_0), TyContext::Location(__arg1_0))
                    => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq)]
1280pub enum TyContext {
1281    LocalDecl {
1282        /// The index of the local variable we are visiting.
1283        local: Local,
1284
1285        /// The source location where this local variable was declared.
1286        source_info: SourceInfo,
1287    },
1288
1289    /// The inferred type of a user type annotation.
1290    UserTy(Span),
1291
1292    /// The return type of the function.
1293    ReturnTy(SourceInfo),
1294
1295    YieldTy(SourceInfo),
1296
1297    ResumeTy(SourceInfo),
1298
1299    /// A type found at some location.
1300    Location(Location),
1301}
1302
1303#[derive(#[automatically_derived]
impl ::core::marker::Copy for NonMutatingUseContext { }Copy, #[automatically_derived]
impl ::core::clone::Clone for NonMutatingUseContext {
    #[inline]
    fn clone(&self) -> NonMutatingUseContext { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for NonMutatingUseContext {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                NonMutatingUseContext::Inspect => "Inspect",
                NonMutatingUseContext::Copy => "Copy",
                NonMutatingUseContext::Move => "Move",
                NonMutatingUseContext::SharedBorrow => "SharedBorrow",
                NonMutatingUseContext::FakeBorrow => "FakeBorrow",
                NonMutatingUseContext::RawBorrow => "RawBorrow",
                NonMutatingUseContext::PlaceMention => "PlaceMention",
                NonMutatingUseContext::Projection => "Projection",
            })
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for NonMutatingUseContext {
    #[inline]
    fn eq(&self, other: &NonMutatingUseContext) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for NonMutatingUseContext {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq)]
1304pub enum NonMutatingUseContext {
1305    /// Being inspected in some way, like loading a len.
1306    Inspect,
1307    /// Consumed as part of an operand.
1308    Copy,
1309    /// Consumed as part of an operand.
1310    Move,
1311    /// Shared borrow.
1312    SharedBorrow,
1313    /// A fake borrow.
1314    /// FIXME: do we need to distinguish shallow and deep fake borrows? In fact, do we need to
1315    /// distinguish fake and normal deep borrows?
1316    FakeBorrow,
1317    /// `&raw const`.
1318    RawBorrow,
1319    /// PlaceMention statement.
1320    ///
1321    /// This statement is executed as a check that the `Place` is live without reading from it,
1322    /// so it must be considered as a non-mutating use.
1323    PlaceMention,
1324    /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
1325    /// For example, the projection `x.y` is not marked as a mutation in these cases:
1326    /// ```ignore (illustrative)
1327    /// z = x.y;
1328    /// f(&x.y);
1329    /// ```
1330    Projection,
1331}
1332
1333#[derive(#[automatically_derived]
impl ::core::marker::Copy for MutatingUseContext { }Copy, #[automatically_derived]
impl ::core::clone::Clone for MutatingUseContext {
    #[inline]
    fn clone(&self) -> MutatingUseContext { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for MutatingUseContext {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                MutatingUseContext::Store => "Store",
                MutatingUseContext::SetDiscriminant => "SetDiscriminant",
                MutatingUseContext::AsmOutput => "AsmOutput",
                MutatingUseContext::Call => "Call",
                MutatingUseContext::Yield => "Yield",
                MutatingUseContext::Drop => "Drop",
                MutatingUseContext::Borrow => "Borrow",
                MutatingUseContext::RawBorrow => "RawBorrow",
                MutatingUseContext::Projection => "Projection",
            })
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for MutatingUseContext {
    #[inline]
    fn eq(&self, other: &MutatingUseContext) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for MutatingUseContext {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq)]
1334pub enum MutatingUseContext {
1335    /// Appears as LHS of an assignment.
1336    Store,
1337    /// Appears on `SetDiscriminant`
1338    SetDiscriminant,
1339    /// Output operand of an inline assembly block.
1340    AsmOutput,
1341    /// Destination of a call.
1342    Call,
1343    /// Destination of a yield.
1344    Yield,
1345    /// Being dropped.
1346    Drop,
1347    /// Mutable borrow.
1348    Borrow,
1349    /// `&raw mut`.
1350    RawBorrow,
1351    /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
1352    /// For example, the projection `x.y` is marked as a mutation in these cases:
1353    /// ```ignore (illustrative)
1354    /// x.y = ...;
1355    /// f(&mut x.y);
1356    /// ```
1357    Projection,
1358}
1359
1360#[derive(#[automatically_derived]
impl ::core::marker::Copy for NonUseContext { }Copy, #[automatically_derived]
impl ::core::clone::Clone for NonUseContext {
    #[inline]
    fn clone(&self) -> NonUseContext {
        let _: ::core::clone::AssertParamIsClone<ty::Variance>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for NonUseContext {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            NonUseContext::StorageLive =>
                ::core::fmt::Formatter::write_str(f, "StorageLive"),
            NonUseContext::StorageDead =>
                ::core::fmt::Formatter::write_str(f, "StorageDead"),
            NonUseContext::AscribeUserTy(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "AscribeUserTy", &__self_0),
            NonUseContext::VarDebugInfo =>
                ::core::fmt::Formatter::write_str(f, "VarDebugInfo"),
            NonUseContext::BackwardIncompatibleDropHint =>
                ::core::fmt::Formatter::write_str(f,
                    "BackwardIncompatibleDropHint"),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for NonUseContext {
    #[inline]
    fn eq(&self, other: &NonUseContext) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (NonUseContext::AscribeUserTy(__self_0),
                    NonUseContext::AscribeUserTy(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for NonUseContext {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ty::Variance>;
    }
}Eq)]
1361pub enum NonUseContext {
1362    /// Starting a storage live range.
1363    StorageLive,
1364    /// Ending a storage live range.
1365    StorageDead,
1366    /// User type annotation assertions for NLL.
1367    AscribeUserTy(ty::Variance),
1368    /// The data of a user variable, for debug info.
1369    VarDebugInfo,
1370    /// A `BackwardIncompatibleDropHint` statement, meant for edition 2024 lints.
1371    BackwardIncompatibleDropHint,
1372}
1373
1374#[derive(#[automatically_derived]
impl ::core::marker::Copy for PlaceContext { }Copy, #[automatically_derived]
impl ::core::clone::Clone for PlaceContext {
    #[inline]
    fn clone(&self) -> PlaceContext {
        let _: ::core::clone::AssertParamIsClone<NonMutatingUseContext>;
        let _: ::core::clone::AssertParamIsClone<MutatingUseContext>;
        let _: ::core::clone::AssertParamIsClone<NonUseContext>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for PlaceContext {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            PlaceContext::NonMutatingUse(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "NonMutatingUse", &__self_0),
            PlaceContext::MutatingUse(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "MutatingUse", &__self_0),
            PlaceContext::NonUse(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "NonUse",
                    &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for PlaceContext {
    #[inline]
    fn eq(&self, other: &PlaceContext) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (PlaceContext::NonMutatingUse(__self_0),
                    PlaceContext::NonMutatingUse(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (PlaceContext::MutatingUse(__self_0),
                    PlaceContext::MutatingUse(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (PlaceContext::NonUse(__self_0),
                    PlaceContext::NonUse(__arg1_0)) => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for PlaceContext {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<NonMutatingUseContext>;
        let _: ::core::cmp::AssertParamIsEq<MutatingUseContext>;
        let _: ::core::cmp::AssertParamIsEq<NonUseContext>;
    }
}Eq)]
1375pub enum PlaceContext {
1376    NonMutatingUse(NonMutatingUseContext),
1377    MutatingUse(MutatingUseContext),
1378    NonUse(NonUseContext),
1379}
1380
1381impl PlaceContext {
1382    /// Returns `true` if this place context represents a drop.
1383    #[inline]
1384    pub fn is_drop(self) -> bool {
1385        #[allow(non_exhaustive_omitted_patterns)] match self {
    PlaceContext::MutatingUse(MutatingUseContext::Drop) => true,
    _ => false,
}matches!(self, PlaceContext::MutatingUse(MutatingUseContext::Drop))
1386    }
1387
1388    /// Returns `true` if this place context represents a borrow, excluding fake borrows
1389    /// (which are an artifact of borrowck and not actually borrows in runtime MIR).
1390    pub fn is_borrow(self) -> bool {
1391        #[allow(non_exhaustive_omitted_patterns)] match self {
    PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) |
        PlaceContext::MutatingUse(MutatingUseContext::Borrow) => true,
    _ => false,
}matches!(
1392            self,
1393            PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
1394                | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
1395        )
1396    }
1397
1398    /// Returns `true` if this place context represents an address-of.
1399    pub fn is_address_of(self) -> bool {
1400        #[allow(non_exhaustive_omitted_patterns)] match self {
    PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) |
        PlaceContext::MutatingUse(MutatingUseContext::RawBorrow) => true,
    _ => false,
}matches!(
1401            self,
1402            PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow)
1403                | PlaceContext::MutatingUse(MutatingUseContext::RawBorrow)
1404        )
1405    }
1406
1407    /// Returns `true` if this place context may be used to know the address of the given place.
1408    #[inline]
1409    pub fn may_observe_address(self) -> bool {
1410        #[allow(non_exhaustive_omitted_patterns)] match self {
    PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow |
        NonMutatingUseContext::RawBorrow | NonMutatingUseContext::FakeBorrow)
        |
        PlaceContext::MutatingUse(MutatingUseContext::Drop |
        MutatingUseContext::Borrow | MutatingUseContext::RawBorrow |
        MutatingUseContext::AsmOutput) => true,
    _ => false,
}matches!(
1411            self,
1412            PlaceContext::NonMutatingUse(
1413                NonMutatingUseContext::SharedBorrow
1414                    | NonMutatingUseContext::RawBorrow
1415                    | NonMutatingUseContext::FakeBorrow
1416            ) | PlaceContext::MutatingUse(
1417                MutatingUseContext::Drop
1418                    | MutatingUseContext::Borrow
1419                    | MutatingUseContext::RawBorrow
1420                    | MutatingUseContext::AsmOutput
1421            )
1422        )
1423    }
1424
1425    /// Returns `true` if this place context represents a storage live or storage dead marker.
1426    #[inline]
1427    pub fn is_storage_marker(self) -> bool {
1428        #[allow(non_exhaustive_omitted_patterns)] match self {
    PlaceContext::NonUse(NonUseContext::StorageLive |
        NonUseContext::StorageDead) => true,
    _ => false,
}matches!(
1429            self,
1430            PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead)
1431        )
1432    }
1433
1434    /// Returns `true` if this place context represents a use that potentially changes the value.
1435    #[inline]
1436    pub fn is_mutating_use(self) -> bool {
1437        #[allow(non_exhaustive_omitted_patterns)] match self {
    PlaceContext::MutatingUse(..) => true,
    _ => false,
}matches!(self, PlaceContext::MutatingUse(..))
1438    }
1439
1440    /// Returns `true` if this place context represents a use.
1441    #[inline]
1442    pub fn is_use(self) -> bool {
1443        !#[allow(non_exhaustive_omitted_patterns)] match self {
    PlaceContext::NonUse(..) => true,
    _ => false,
}matches!(self, PlaceContext::NonUse(..))
1444    }
1445
1446    /// Returns `true` if this place context represents an assignment statement.
1447    pub fn is_place_assignment(self) -> bool {
1448        #[allow(non_exhaustive_omitted_patterns)] match self {
    PlaceContext::MutatingUse(MutatingUseContext::Store |
        MutatingUseContext::Call | MutatingUseContext::AsmOutput) => true,
    _ => false,
}matches!(
1449            self,
1450            PlaceContext::MutatingUse(
1451                MutatingUseContext::Store
1452                    | MutatingUseContext::Call
1453                    | MutatingUseContext::AsmOutput,
1454            )
1455        )
1456    }
1457
1458    /// The variance of a place in the given context.
1459    pub fn ambient_variance(self) -> ty::Variance {
1460        use NonMutatingUseContext::*;
1461        use NonUseContext::*;
1462        match self {
1463            PlaceContext::MutatingUse(_) => ty::Invariant,
1464            PlaceContext::NonUse(
1465                StorageDead | StorageLive | VarDebugInfo | BackwardIncompatibleDropHint,
1466            ) => ty::Invariant,
1467            PlaceContext::NonMutatingUse(
1468                Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | RawBorrow
1469                | Projection,
1470            ) => ty::Covariant,
1471            PlaceContext::NonUse(AscribeUserTy(variance)) => variance,
1472        }
1473    }
1474}
1475
1476/// Small utility to visit places and locals without manually implementing a full visitor.
1477pub struct VisitPlacesWith<F>(pub F);
1478
1479impl<'tcx, F> Visitor<'tcx> for VisitPlacesWith<F>
1480where
1481    F: FnMut(Place<'tcx>, PlaceContext),
1482{
1483    fn visit_local(&mut self, local: Local, ctxt: PlaceContext, _: Location) {
1484        (self.0)(local.into(), ctxt);
1485    }
1486
1487    fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, location: Location) {
1488        (self.0)(*place, ctxt);
1489        self.visit_projection(place.as_ref(), ctxt, location);
1490    }
1491}