1use 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 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(
99 &mut self,
100 statement: & $($mutability)? Statement<'tcx>,
101 location: Location,
102 ) {
103 self.super_statement(statement, location);
104 }
105
106 fn visit_assign(
107 &mut self,
108 place: & $($mutability)? Place<'tcx>,
109 rvalue: & $($mutability)? Rvalue<'tcx>,
110 location: Location,
111 ) {
112 self.super_assign(place, rvalue, location);
113 }
114
115 fn visit_terminator(
116 &mut self,
117 terminator: & $($mutability)? Terminator<'tcx>,
118 location: Location,
119 ) {
120 self.super_terminator(terminator, location);
121 }
122
123 fn visit_assert_message(
124 &mut self,
125 msg: & $($mutability)? AssertMessage<'tcx>,
126 location: Location,
127 ) {
128 self.super_assert_message(msg, location);
129 }
130
131 fn visit_rvalue(
132 &mut self,
133 rvalue: & $($mutability)? Rvalue<'tcx>,
134 location: Location,
135 ) {
136 self.super_rvalue(rvalue, location);
137 }
138
139 fn visit_operand(
140 &mut self,
141 operand: & $($mutability)? Operand<'tcx>,
142 location: Location,
143 ) {
144 self.super_operand(operand, location);
145 }
146
147 fn visit_ascribe_user_ty(
148 &mut self,
149 place: & $($mutability)? Place<'tcx>,
150 variance: $(& $mutability)? ty::Variance,
151 user_ty: & $($mutability)? UserTypeProjection,
152 location: Location,
153 ) {
154 self.super_ascribe_user_ty(place, variance, user_ty, location);
155 }
156
157 fn visit_coverage(
158 &mut self,
159 kind: & $($mutability)? coverage::CoverageKind,
160 location: Location,
161 ) {
162 self.super_coverage(kind, location);
163 }
164
165 fn visit_retag(
166 &mut self,
167 kind: $(& $mutability)? RetagKind,
168 place: & $($mutability)? Place<'tcx>,
169 location: Location,
170 ) {
171 self.super_retag(kind, place, location);
172 }
173
174 fn visit_place(
175 &mut self,
176 place: & $($mutability)? Place<'tcx>,
177 context: PlaceContext,
178 location: Location,
179 ) {
180 self.super_place(place, context, location);
181 }
182
183 visit_place_fns!($($mutability)?);
184
185 fn visit_const_operand(
188 &mut self,
189 constant: & $($mutability)? ConstOperand<'tcx>,
190 location: Location,
191 ) {
192 self.super_const_operand(constant, location);
193 }
194
195 fn visit_ty_const(
196 &mut self,
197 ct: $( & $mutability)? ty::Const<'tcx>,
198 location: Location,
199 ) {
200 self.super_ty_const(ct, location);
201 }
202
203 fn visit_span(
204 &mut self,
205 span: $(& $mutability)? Span,
206 ) {
207 self.super_span(span);
208 }
209
210 fn visit_source_info(
211 &mut self,
212 source_info: & $($mutability)? SourceInfo,
213 ) {
214 self.super_source_info(source_info);
215 }
216
217 fn visit_ty(
218 &mut self,
219 ty: $(& $mutability)? Ty<'tcx>,
220 _: TyContext,
221 ) {
222 self.super_ty(ty);
223 }
224
225 fn visit_user_type_projection(
226 &mut self,
227 ty: & $($mutability)? UserTypeProjection,
228 ) {
229 self.super_user_type_projection(ty);
230 }
231
232 fn visit_user_type_annotation(
233 &mut self,
234 index: UserTypeAnnotationIndex,
235 ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
236 ) {
237 self.super_user_type_annotation(index, ty);
238 }
239
240 fn visit_region(
241 &mut self,
242 region: $(& $mutability)? ty::Region<'tcx>,
243 _: Location,
244 ) {
245 self.super_region(region);
246 }
247
248 fn visit_args(
249 &mut self,
250 args: & $($mutability)? GenericArgsRef<'tcx>,
251 _: Location,
252 ) {
253 self.super_args(args);
254 }
255
256 fn visit_local_decl(
257 &mut self,
258 local: Local,
259 local_decl: & $($mutability)? LocalDecl<'tcx>,
260 ) {
261 self.super_local_decl(local, local_decl);
262 }
263
264 fn visit_var_debug_info(
265 &mut self,
266 var_debug_info: & $($mutability)* VarDebugInfo<'tcx>,
267 ) {
268 self.super_var_debug_info(var_debug_info);
269 }
270
271 fn visit_local(
272 &mut self,
273 local: $(& $mutability)? Local,
274 context: PlaceContext,
275 location: Location,
276 ) {
277 self.super_local(local, context, location)
278 }
279
280 fn visit_source_scope(
281 &mut self,
282 scope: $(& $mutability)? SourceScope,
283 ) {
284 self.super_source_scope(scope);
285 }
286
287 fn super_body(
291 &mut self,
292 body: &$($mutability)? Body<'tcx>,
293 ) {
294 super_body!(self, body, $($mutability, true)?);
295 }
296
297 fn super_basic_block_data(
298 &mut self,
299 block: BasicBlock,
300 data: & $($mutability)? BasicBlockData<'tcx>)
301 {
302 let BasicBlockData {
303 statements,
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 if let Some(terminator) = terminator {
316 let location = Location { block, statement_index: index };
317 self.visit_terminator(terminator, location);
318 }
319 }
320
321 fn super_source_scope_data(
322 &mut self,
323 scope_data: & $($mutability)? SourceScopeData<'tcx>,
324 ) {
325 let SourceScopeData {
326 span,
327 parent_scope,
328 inlined,
329 inlined_parent_scope,
330 local_data: _,
331 } = scope_data;
332
333 self.visit_span($(& $mutability)? *span);
334 if let Some(parent_scope) = parent_scope {
335 self.visit_source_scope($(& $mutability)? *parent_scope);
336 }
337 if let Some((callee, callsite_span)) = inlined {
338 let location = Location::START;
339
340 self.visit_span($(& $mutability)? *callsite_span);
341
342 let ty::Instance { def: callee_def, args: callee_args } = callee;
343 match callee_def {
344 ty::InstanceKind::Item(_def_id) => {}
345
346 ty::InstanceKind::Intrinsic(_def_id)
347 | ty::InstanceKind::VTableShim(_def_id)
348 | ty::InstanceKind::ReifyShim(_def_id, _)
349 | ty::InstanceKind::Virtual(_def_id, _)
350 | ty::InstanceKind::ThreadLocalShim(_def_id)
351 | ty::InstanceKind::ClosureOnceShim { call_once: _def_id, track_caller: _ }
352 | ty::InstanceKind::ConstructCoroutineInClosureShim {
353 coroutine_closure_def_id: _def_id,
354 receiver_by_ref: _,
355 }
356 | ty::InstanceKind::DropGlue(_def_id, None) => {}
357
358 ty::InstanceKind::FnPtrShim(_def_id, ty)
359 | ty::InstanceKind::DropGlue(_def_id, Some(ty))
360 | ty::InstanceKind::CloneShim(_def_id, ty)
361 | ty::InstanceKind::FnPtrAddrShim(_def_id, ty)
362 | ty::InstanceKind::AsyncDropGlue(_def_id, ty)
363 | ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, ty) => {
364 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
366 }
367 ty::InstanceKind::FutureDropPollShim(_def_id, proxy_ty, impl_ty) => {
368 self.visit_ty($(& $mutability)? *proxy_ty, TyContext::Location(location));
369 self.visit_ty($(& $mutability)? *impl_ty, TyContext::Location(location));
370 }
371 }
372 self.visit_args(callee_args, location);
373 }
374 if let Some(inlined_parent_scope) = inlined_parent_scope {
375 self.visit_source_scope($(& $mutability)? *inlined_parent_scope);
376 }
377 }
378
379 fn super_statement(
380 &mut self,
381 statement: & $($mutability)? Statement<'tcx>,
382 location: Location
383 ) {
384 let Statement { source_info, kind } = statement;
385
386 self.visit_source_info(source_info);
387 match kind {
388 StatementKind::Assign(box (place, rvalue)) => {
389 self.visit_assign(place, rvalue, location);
390 }
391 StatementKind::FakeRead(box (_, place)) => {
392 self.visit_place(
393 place,
394 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
395 location
396 );
397 }
398 StatementKind::SetDiscriminant { place, .. } => {
399 self.visit_place(
400 place,
401 PlaceContext::MutatingUse(MutatingUseContext::SetDiscriminant),
402 location
403 );
404 }
405 StatementKind::Deinit(place) => {
406 self.visit_place(
407 place,
408 PlaceContext::MutatingUse(MutatingUseContext::Deinit),
409 location
410 )
411 }
412 StatementKind::StorageLive(local) => {
413 self.visit_local(
414 $(& $mutability)? *local,
415 PlaceContext::NonUse(NonUseContext::StorageLive),
416 location
417 );
418 }
419 StatementKind::StorageDead(local) => {
420 self.visit_local(
421 $(& $mutability)? *local,
422 PlaceContext::NonUse(NonUseContext::StorageDead),
423 location
424 );
425 }
426 StatementKind::Retag(kind, place) => {
427 self.visit_retag($(& $mutability)? *kind, place, location);
428 }
429 StatementKind::PlaceMention(place) => {
430 self.visit_place(
431 place,
432 PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention),
433 location
434 );
435 }
436 StatementKind::AscribeUserType(box (place, user_ty), variance) => {
437 self.visit_ascribe_user_ty(
438 place,
439 $(& $mutability)? *variance,
440 user_ty,
441 location
442 );
443 }
444 StatementKind::Coverage(coverage) => {
445 self.visit_coverage(
446 coverage,
447 location
448 )
449 }
450 StatementKind::Intrinsic(box intrinsic) => {
451 match intrinsic {
452 NonDivergingIntrinsic::Assume(op) => self.visit_operand(op, location),
453 NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
454 src,
455 dst,
456 count
457 }) => {
458 self.visit_operand(src, location);
459 self.visit_operand(dst, location);
460 self.visit_operand(count, location);
461 }
462 }
463 }
464 StatementKind::BackwardIncompatibleDropHint { place, .. } => {
465 self.visit_place(
466 place,
467 PlaceContext::NonUse(NonUseContext::BackwardIncompatibleDropHint),
468 location
469 );
470 }
471 StatementKind::ConstEvalCounter => {}
472 StatementKind::Nop => {}
473 }
474 }
475
476 fn super_assign(
477 &mut self,
478 place: &$($mutability)? Place<'tcx>,
479 rvalue: &$($mutability)? Rvalue<'tcx>,
480 location: Location
481 ) {
482 self.visit_place(
483 place,
484 PlaceContext::MutatingUse(MutatingUseContext::Store),
485 location
486 );
487 self.visit_rvalue(rvalue, location);
488 }
489
490 fn super_terminator(
491 &mut self,
492 terminator: &$($mutability)? Terminator<'tcx>,
493 location: Location
494 ) {
495 let Terminator { source_info, kind } = terminator;
496
497 self.visit_source_info(source_info);
498 match kind {
499 TerminatorKind::Goto { .. }
500 | TerminatorKind::UnwindResume
501 | TerminatorKind::UnwindTerminate(_)
502 | TerminatorKind::CoroutineDrop
503 | TerminatorKind::Unreachable
504 | TerminatorKind::FalseEdge { .. }
505 | TerminatorKind::FalseUnwind { .. } => {}
506
507 TerminatorKind::Return => {
508 let $($mutability)? local = RETURN_PLACE;
511 self.visit_local(
512 $(& $mutability)? local,
513 PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
514 location,
515 );
516
517 assert_eq!(
518 local,
519 RETURN_PLACE,
520 "`MutVisitor` tried to mutate return place of `return` terminator"
521 );
522 }
523
524 TerminatorKind::SwitchInt { discr, targets: _ } => {
525 self.visit_operand(discr, location);
526 }
527
528 TerminatorKind::Drop {
529 place,
530 target: _,
531 unwind: _,
532 replace: _,
533 drop: _,
534 async_fut: _,
535 } => {
536 self.visit_place(
537 place,
538 PlaceContext::MutatingUse(MutatingUseContext::Drop),
539 location
540 );
541 }
542
543 TerminatorKind::Call {
544 func,
545 args,
546 destination,
547 target: _,
548 unwind: _,
549 call_source: _,
550 fn_span,
551 } => {
552 self.visit_span($(& $mutability)? *fn_span);
553 self.visit_operand(func, location);
554 for arg in args {
555 self.visit_operand(&$($mutability)? arg.node, location);
556 }
557 self.visit_place(
558 destination,
559 PlaceContext::MutatingUse(MutatingUseContext::Call),
560 location
561 );
562 }
563
564 TerminatorKind::TailCall { func, args, fn_span } => {
565 self.visit_span($(& $mutability)? *fn_span);
566 self.visit_operand(func, location);
567 for arg in args {
568 self.visit_operand(&$($mutability)? arg.node, location);
569 }
570 },
571
572 TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
573 self.visit_operand(cond, location);
574 self.visit_assert_message(msg, location);
575 }
576
577 TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
578 self.visit_operand(value, location);
579 self.visit_place(
580 resume_arg,
581 PlaceContext::MutatingUse(MutatingUseContext::Yield),
582 location,
583 );
584 }
585
586 TerminatorKind::InlineAsm {
587 asm_macro: _,
588 template: _,
589 operands,
590 options: _,
591 line_spans: _,
592 targets: _,
593 unwind: _,
594 } => {
595 for op in operands {
596 match op {
597 InlineAsmOperand::In { value, .. } => {
598 self.visit_operand(value, location);
599 }
600 InlineAsmOperand::Out { place: Some(place), .. } => {
601 self.visit_place(
602 place,
603 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
604 location,
605 );
606 }
607 InlineAsmOperand::InOut { in_value, out_place, .. } => {
608 self.visit_operand(in_value, location);
609 if let Some(out_place) = out_place {
610 self.visit_place(
611 out_place,
612 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
613 location,
614 );
615 }
616 }
617 InlineAsmOperand::Const { value }
618 | InlineAsmOperand::SymFn { value } => {
619 self.visit_const_operand(value, location);
620 }
621 InlineAsmOperand::Out { place: None, .. }
622 | InlineAsmOperand::SymStatic { def_id: _ }
623 | InlineAsmOperand::Label { target_index: _ } => {}
624 }
625 }
626 }
627 }
628 }
629
630 fn super_assert_message(
631 &mut self,
632 msg: & $($mutability)? AssertMessage<'tcx>,
633 location: Location
634 ) {
635 use crate::mir::AssertKind::*;
636 match msg {
637 BoundsCheck { len, index } => {
638 self.visit_operand(len, location);
639 self.visit_operand(index, location);
640 }
641 Overflow(_, l, r) => {
642 self.visit_operand(l, location);
643 self.visit_operand(r, location);
644 }
645 OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
646 self.visit_operand(op, location);
647 }
648 ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference | ResumedAfterDrop(_) => {
649 }
651 MisalignedPointerDereference { required, found } => {
652 self.visit_operand(required, location);
653 self.visit_operand(found, location);
654 }
655 }
656 }
657
658 fn super_rvalue(
659 &mut self,
660 rvalue: & $($mutability)? Rvalue<'tcx>,
661 location: Location
662 ) {
663 match rvalue {
664 Rvalue::Use(operand) => {
665 self.visit_operand(operand, location);
666 }
667
668 Rvalue::Repeat(value, ct) => {
669 self.visit_operand(value, location);
670 self.visit_ty_const($(&$mutability)? *ct, location);
671 }
672
673 Rvalue::ThreadLocalRef(_) => {}
674
675 Rvalue::Ref(r, bk, path) => {
676 self.visit_region($(& $mutability)? *r, location);
677 let ctx = match bk {
678 BorrowKind::Shared => PlaceContext::NonMutatingUse(
679 NonMutatingUseContext::SharedBorrow
680 ),
681 BorrowKind::Fake(_) => PlaceContext::NonMutatingUse(
682 NonMutatingUseContext::FakeBorrow
683 ),
684 BorrowKind::Mut { .. } =>
685 PlaceContext::MutatingUse(MutatingUseContext::Borrow),
686 };
687 self.visit_place(path, ctx, location);
688 }
689
690 Rvalue::CopyForDeref(place) => {
691 self.visit_place(
692 place,
693 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
694 location
695 );
696 }
697
698 Rvalue::RawPtr(m, path) => {
699 let ctx = match m {
700 RawPtrKind::Mut => PlaceContext::MutatingUse(
701 MutatingUseContext::RawBorrow
702 ),
703 RawPtrKind::Const => PlaceContext::NonMutatingUse(
704 NonMutatingUseContext::RawBorrow
705 ),
706 RawPtrKind::FakeForPtrMetadata => PlaceContext::NonMutatingUse(
707 NonMutatingUseContext::Inspect
708 ),
709 };
710 self.visit_place(path, ctx, location);
711 }
712
713 Rvalue::Len(path) => {
714 self.visit_place(
715 path,
716 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
717 location
718 );
719 }
720
721 Rvalue::Cast(_cast_kind, operand, ty) => {
722 self.visit_operand(operand, location);
723 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
724 }
725
726 Rvalue::BinaryOp(_bin_op, box(lhs, rhs)) => {
727 self.visit_operand(lhs, location);
728 self.visit_operand(rhs, location);
729 }
730
731 Rvalue::UnaryOp(_un_op, op) => {
732 self.visit_operand(op, location);
733 }
734
735 Rvalue::Discriminant(place) => {
736 self.visit_place(
737 place,
738 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
739 location
740 );
741 }
742
743 Rvalue::NullaryOp(_op, ty) => {
744 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
745 }
746
747 Rvalue::Aggregate(kind, operands) => {
748 let kind = &$($mutability)? **kind;
749 match kind {
750 AggregateKind::Array(ty) => {
751 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
752 }
753 AggregateKind::Tuple => {}
754 AggregateKind::Adt(
755 _adt_def,
756 _variant_index,
757 args,
758 _user_args,
759 _active_field_index
760 ) => {
761 self.visit_args(args, location);
762 }
763 AggregateKind::Closure(_, closure_args) => {
764 self.visit_args(closure_args, location);
765 }
766 AggregateKind::Coroutine(_, coroutine_args) => {
767 self.visit_args(coroutine_args, location);
768 }
769 AggregateKind::CoroutineClosure(_, coroutine_closure_args) => {
770 self.visit_args(coroutine_closure_args, location);
771 }
772 AggregateKind::RawPtr(ty, _) => {
773 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
774 }
775 }
776
777 for operand in operands {
778 self.visit_operand(operand, location);
779 }
780 }
781
782 Rvalue::ShallowInitBox(operand, ty) => {
783 self.visit_operand(operand, location);
784 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
785 }
786
787 Rvalue::WrapUnsafeBinder(op, ty) => {
788 self.visit_operand(op, location);
789 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
790 }
791 }
792 }
793
794 fn super_operand(
795 &mut self,
796 operand: & $($mutability)? Operand<'tcx>,
797 location: Location
798 ) {
799 match operand {
800 Operand::Copy(place) => {
801 self.visit_place(
802 place,
803 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
804 location
805 );
806 }
807 Operand::Move(place) => {
808 self.visit_place(
809 place,
810 PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
811 location
812 );
813 }
814 Operand::Constant(constant) => {
815 self.visit_const_operand(constant, location);
816 }
817 }
818 }
819
820 fn super_ascribe_user_ty(
821 &mut self,
822 place: & $($mutability)? Place<'tcx>,
823 variance: $(& $mutability)? ty::Variance,
824 user_ty: & $($mutability)? UserTypeProjection,
825 location: Location)
826 {
827 self.visit_place(
828 place,
829 PlaceContext::NonUse(
830 NonUseContext::AscribeUserTy($(* &$mutability *)? variance)
831 ),
832 location
833 );
834 self.visit_user_type_projection(user_ty);
835 }
836
837 fn super_coverage(
838 &mut self,
839 _kind: & $($mutability)? coverage::CoverageKind,
840 _location: Location
841 ) {
842 }
843
844 fn super_retag(
845 &mut self,
846 _kind: $(& $mutability)? RetagKind,
847 place: & $($mutability)? Place<'tcx>,
848 location: Location
849 ) {
850 self.visit_place(
851 place,
852 PlaceContext::MutatingUse(MutatingUseContext::Retag),
853 location,
854 );
855 }
856
857 fn super_local_decl(
858 &mut self,
859 local: Local,
860 local_decl: & $($mutability)? LocalDecl<'tcx>
861 ) {
862 let LocalDecl {
863 mutability: _,
864 ty,
865 user_ty,
866 source_info,
867 local_info: _,
868 } = local_decl;
869
870 self.visit_source_info(source_info);
871
872 self.visit_ty($(& $mutability)? *ty, TyContext::LocalDecl {
873 local,
874 source_info: *source_info,
875 });
876 if let Some(user_ty) = user_ty {
877 for user_ty in & $($mutability)? user_ty.contents {
878 self.visit_user_type_projection(user_ty);
879 }
880 }
881 }
882
883 fn super_local(
884 &mut self,
885 _local: $(& $mutability)? Local,
886 _context: PlaceContext,
887 _location: Location,
888 ) {
889 }
890
891 fn super_var_debug_info(
892 &mut self,
893 var_debug_info: & $($mutability)? VarDebugInfo<'tcx>
894 ) {
895 let VarDebugInfo {
896 name: _,
897 source_info,
898 composite,
899 value,
900 argument_index: _,
901 } = var_debug_info;
902
903 self.visit_source_info(source_info);
904 let location = Location::START;
905 if let Some(box VarDebugInfoFragment {
906 ty,
907 projection
908 }) = composite {
909 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
910 for elem in projection {
911 let ProjectionElem::Field(_, ty) = elem else { bug!() };
912 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
913 }
914 }
915 match value {
916 VarDebugInfoContents::Const(c) => self.visit_const_operand(c, location),
917 VarDebugInfoContents::Place(place) =>
918 self.visit_place(
919 place,
920 PlaceContext::NonUse(NonUseContext::VarDebugInfo),
921 location
922 ),
923 }
924 }
925
926 fn super_source_scope(&mut self, _scope: $(& $mutability)? SourceScope) {}
927
928 fn super_const_operand(
929 &mut self,
930 constant: & $($mutability)? ConstOperand<'tcx>,
931 location: Location
932 ) {
933 let ConstOperand {
934 span,
935 user_ty: _, const_,
937 } = constant;
938
939 self.visit_span($(& $mutability)? *span);
940 match const_ {
941 Const::Ty(_, ct) => self.visit_ty_const($(&$mutability)? *ct, location),
942 Const::Val(_, ty) => {
943 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
944 }
945 Const::Unevaluated(_, ty) => {
946 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
947 }
948 }
949 }
950
951 fn super_ty_const(
952 &mut self,
953 _ct: $(& $mutability)? ty::Const<'tcx>,
954 _location: Location,
955 ) {
956 }
957
958 fn super_span(&mut self, _span: $(& $mutability)? Span) {}
959
960 fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) {
961 let SourceInfo { span, scope } = source_info;
962
963 self.visit_span($(& $mutability)? *span);
964 self.visit_source_scope($(& $mutability)? *scope);
965 }
966
967 fn super_user_type_projection(&mut self, _ty: & $($mutability)? UserTypeProjection) {}
968
969 fn super_user_type_annotation(
970 &mut self,
971 _index: UserTypeAnnotationIndex,
972 ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
973 ) {
974 self.visit_span($(& $mutability)? ty.span);
975 self.visit_ty($(& $mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
976 }
977
978 fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {}
979
980 fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) {}
981
982 fn super_args(&mut self, _args: & $($mutability)? GenericArgsRef<'tcx>) {}
983
984 fn visit_location(
987 &mut self,
988 body: &$($mutability)? Body<'tcx>,
989 location: Location
990 ) {
991 let basic_block =
992 & $($mutability)? basic_blocks!(body, $($mutability, true)?)[location.block];
993 if basic_block.statements.len() == location.statement_index {
994 if let Some(ref $($mutability)? terminator) = basic_block.terminator {
995 self.visit_terminator(terminator, location)
996 }
997 } else {
998 let statement = & $($mutability)?
999 basic_block.statements[location.statement_index];
1000 self.visit_statement(statement, location)
1001 }
1002 }
1003 }
1004 }
1005}
1006
1007macro_rules! basic_blocks {
1008 ($body:ident, mut, true) => {
1009 $body.basic_blocks.as_mut()
1010 };
1011 ($body:ident, mut, false) => {
1012 $body.basic_blocks.as_mut_preserves_cfg()
1013 };
1014 ($body:ident,) => {
1015 $body.basic_blocks
1016 };
1017}
1018
1019macro_rules! basic_blocks_iter {
1020 ($body:ident, mut, $invalidate:tt) => {
1021 basic_blocks!($body, mut, $invalidate).iter_enumerated_mut()
1022 };
1023 ($body:ident,) => {
1024 basic_blocks!($body,).iter_enumerated()
1025 };
1026}
1027
1028macro_rules! extra_body_methods {
1029 (mut) => {
1030 fn visit_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
1031 self.super_body_preserves_cfg(body);
1032 }
1033
1034 fn super_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
1035 super_body!(self, body, mut, false);
1036 }
1037 };
1038 () => {};
1039}
1040
1041macro_rules! super_body {
1042 ($self:ident, $body:ident, $($mutability:ident, $invalidate:tt)?) => {
1043 let span = $body.span;
1044 if let Some(coroutine) = &$($mutability)? $body.coroutine {
1045 if let Some(yield_ty) = $(& $mutability)? coroutine.yield_ty {
1046 $self.visit_ty(
1047 yield_ty,
1048 TyContext::YieldTy(SourceInfo::outermost(span))
1049 );
1050 }
1051 if let Some(resume_ty) = $(& $mutability)? coroutine.resume_ty {
1052 $self.visit_ty(
1053 resume_ty,
1054 TyContext::ResumeTy(SourceInfo::outermost(span))
1055 );
1056 }
1057 }
1058
1059 for (bb, data) in basic_blocks_iter!($body, $($mutability, $invalidate)?) {
1060 $self.visit_basic_block_data(bb, data);
1061 }
1062
1063 for scope in &$($mutability)? $body.source_scopes {
1064 $self.visit_source_scope_data(scope);
1065 }
1066
1067 $self.visit_ty(
1068 $(& $mutability)? $body.return_ty(),
1069 TyContext::ReturnTy(SourceInfo::outermost($body.span))
1070 );
1071
1072 for local in $body.local_decls.indices() {
1073 $self.visit_local_decl(local, & $($mutability)? $body.local_decls[local]);
1074 }
1075
1076 #[allow(unused_macro_rules)]
1077 macro_rules! type_annotations {
1078 (mut) => ($body.user_type_annotations.iter_enumerated_mut());
1079 () => ($body.user_type_annotations.iter_enumerated());
1080 }
1081
1082 for (index, annotation) in type_annotations!($($mutability)?) {
1083 $self.visit_user_type_annotation(
1084 index, annotation
1085 );
1086 }
1087
1088 for var_debug_info in &$($mutability)? $body.var_debug_info {
1089 $self.visit_var_debug_info(var_debug_info);
1090 }
1091
1092 $self.visit_span($(& $mutability)? $body.span);
1093
1094 if let Some(required_consts) = &$($mutability)? $body.required_consts {
1095 for const_ in required_consts {
1096 let location = Location::START;
1097 $self.visit_const_operand(const_, location);
1098 }
1099 }
1100 }
1101}
1102
1103macro_rules! visit_place_fns {
1104 (mut) => {
1105 fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
1106
1107 fn super_place(
1108 &mut self,
1109 place: &mut Place<'tcx>,
1110 context: PlaceContext,
1111 location: Location,
1112 ) {
1113 self.visit_local(&mut place.local, context, location);
1114
1115 if let Some(new_projection) = self.process_projection(&place.projection, location) {
1116 place.projection = self.tcx().mk_place_elems(&new_projection);
1117 }
1118 }
1119
1120 fn process_projection<'a>(
1121 &mut self,
1122 projection: &'a [PlaceElem<'tcx>],
1123 location: Location,
1124 ) -> Option<Vec<PlaceElem<'tcx>>> {
1125 let mut projection = Cow::Borrowed(projection);
1126
1127 for i in 0..projection.len() {
1128 if let Some(&elem) = projection.get(i) {
1129 if let Some(elem) = self.process_projection_elem(elem, location) {
1130 let vec = projection.to_mut();
1133 vec[i] = elem;
1134 }
1135 }
1136 }
1137
1138 match projection {
1139 Cow::Borrowed(_) => None,
1140 Cow::Owned(vec) => Some(vec),
1141 }
1142 }
1143
1144 fn process_projection_elem(
1145 &mut self,
1146 elem: PlaceElem<'tcx>,
1147 location: Location,
1148 ) -> Option<PlaceElem<'tcx>> {
1149 match elem {
1150 PlaceElem::Index(local) => {
1151 let mut new_local = local;
1152 self.visit_local(
1153 &mut new_local,
1154 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
1155 location,
1156 );
1157
1158 if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
1159 }
1160 PlaceElem::Field(field, ty) => {
1161 let mut new_ty = ty;
1162 self.visit_ty(&mut new_ty, TyContext::Location(location));
1163 if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
1164 }
1165 PlaceElem::OpaqueCast(ty) => {
1166 let mut new_ty = ty;
1167 self.visit_ty(&mut new_ty, TyContext::Location(location));
1168 if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None }
1169 }
1170 PlaceElem::Subtype(ty) => {
1171 let mut new_ty = ty;
1172 self.visit_ty(&mut new_ty, TyContext::Location(location));
1173 if ty != new_ty { Some(PlaceElem::Subtype(new_ty)) } else { None }
1174 }
1175 PlaceElem::UnwrapUnsafeBinder(ty) => {
1176 let mut new_ty = ty;
1177 self.visit_ty(&mut new_ty, TyContext::Location(location));
1178 if ty != new_ty { Some(PlaceElem::UnwrapUnsafeBinder(new_ty)) } else { None }
1179 }
1180 PlaceElem::Deref
1181 | PlaceElem::ConstantIndex { .. }
1182 | PlaceElem::Subslice { .. }
1183 | PlaceElem::Downcast(..) => None,
1184 }
1185 }
1186 };
1187
1188 () => {
1189 fn visit_projection(
1190 &mut self,
1191 place_ref: PlaceRef<'tcx>,
1192 context: PlaceContext,
1193 location: Location,
1194 ) {
1195 self.super_projection(place_ref, context, location);
1196 }
1197
1198 fn visit_projection_elem(
1199 &mut self,
1200 place_ref: PlaceRef<'tcx>,
1201 elem: PlaceElem<'tcx>,
1202 context: PlaceContext,
1203 location: Location,
1204 ) {
1205 self.super_projection_elem(place_ref, elem, context, location);
1206 }
1207
1208 fn super_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
1209 let mut context = context;
1210
1211 if !place.projection.is_empty() {
1212 if context.is_use() {
1213 context = if context.is_mutating_use() {
1215 PlaceContext::MutatingUse(MutatingUseContext::Projection)
1216 } else {
1217 PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
1218 };
1219 }
1220 }
1221
1222 self.visit_local(place.local, context, location);
1223
1224 self.visit_projection(place.as_ref(), context, location);
1225 }
1226
1227 fn super_projection(
1228 &mut self,
1229 place_ref: PlaceRef<'tcx>,
1230 context: PlaceContext,
1231 location: Location,
1232 ) {
1233 for (base, elem) in place_ref.iter_projections().rev() {
1234 self.visit_projection_elem(base, elem, context, location);
1235 }
1236 }
1237
1238 fn super_projection_elem(
1239 &mut self,
1240 _place_ref: PlaceRef<'tcx>,
1241 elem: PlaceElem<'tcx>,
1242 _context: PlaceContext,
1243 location: Location,
1244 ) {
1245 match elem {
1246 ProjectionElem::OpaqueCast(ty)
1247 | ProjectionElem::Subtype(ty)
1248 | ProjectionElem::Field(_, ty)
1249 | ProjectionElem::UnwrapUnsafeBinder(ty) => {
1250 self.visit_ty(ty, TyContext::Location(location));
1251 }
1252 ProjectionElem::Index(local) => {
1253 self.visit_local(
1254 local,
1255 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
1256 location,
1257 );
1258 }
1259 ProjectionElem::Deref
1260 | ProjectionElem::Subslice { from: _, to: _, from_end: _ }
1261 | ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ }
1262 | ProjectionElem::Downcast(_, _) => {}
1263 }
1264 }
1265 };
1266}
1267
1268make_mir_visitor!(Visitor,);
1269make_mir_visitor!(MutVisitor, mut);
1270
1271#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1274pub enum TyContext {
1275 LocalDecl {
1276 local: Local,
1278
1279 source_info: SourceInfo,
1281 },
1282
1283 UserTy(Span),
1285
1286 ReturnTy(SourceInfo),
1288
1289 YieldTy(SourceInfo),
1290
1291 ResumeTy(SourceInfo),
1292
1293 Location(Location),
1295}
1296
1297#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1298pub enum NonMutatingUseContext {
1299 Inspect,
1301 Copy,
1303 Move,
1305 SharedBorrow,
1307 FakeBorrow,
1311 RawBorrow,
1313 PlaceMention,
1318 Projection,
1325}
1326
1327#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1328pub enum MutatingUseContext {
1329 Store,
1331 SetDiscriminant,
1333 Deinit,
1335 AsmOutput,
1337 Call,
1339 Yield,
1341 Drop,
1343 Borrow,
1345 RawBorrow,
1347 Projection,
1354 Retag,
1356}
1357
1358#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1359pub enum NonUseContext {
1360 StorageLive,
1362 StorageDead,
1364 AscribeUserTy(ty::Variance),
1366 VarDebugInfo,
1368 BackwardIncompatibleDropHint,
1370}
1371
1372#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1373pub enum PlaceContext {
1374 NonMutatingUse(NonMutatingUseContext),
1375 MutatingUse(MutatingUseContext),
1376 NonUse(NonUseContext),
1377}
1378
1379impl PlaceContext {
1380 #[inline]
1382 pub fn is_drop(self) -> bool {
1383 matches!(self, PlaceContext::MutatingUse(MutatingUseContext::Drop))
1384 }
1385
1386 pub fn is_borrow(self) -> bool {
1389 matches!(
1390 self,
1391 PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
1392 | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
1393 )
1394 }
1395
1396 pub fn is_address_of(self) -> bool {
1398 matches!(
1399 self,
1400 PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow)
1401 | PlaceContext::MutatingUse(MutatingUseContext::RawBorrow)
1402 )
1403 }
1404
1405 #[inline]
1407 pub fn is_storage_marker(self) -> bool {
1408 matches!(
1409 self,
1410 PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead)
1411 )
1412 }
1413
1414 #[inline]
1416 pub fn is_mutating_use(self) -> bool {
1417 matches!(self, PlaceContext::MutatingUse(..))
1418 }
1419
1420 #[inline]
1422 pub fn is_use(self) -> bool {
1423 !matches!(self, PlaceContext::NonUse(..))
1424 }
1425
1426 pub fn is_place_assignment(self) -> bool {
1428 matches!(
1429 self,
1430 PlaceContext::MutatingUse(
1431 MutatingUseContext::Store
1432 | MutatingUseContext::Call
1433 | MutatingUseContext::AsmOutput,
1434 )
1435 )
1436 }
1437
1438 pub fn ambient_variance(self) -> ty::Variance {
1440 use NonMutatingUseContext::*;
1441 use NonUseContext::*;
1442 match self {
1443 PlaceContext::MutatingUse(_) => ty::Invariant,
1444 PlaceContext::NonUse(
1445 StorageDead | StorageLive | VarDebugInfo | BackwardIncompatibleDropHint,
1446 ) => ty::Invariant,
1447 PlaceContext::NonMutatingUse(
1448 Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | RawBorrow
1449 | Projection,
1450 ) => ty::Covariant,
1451 PlaceContext::NonUse(AscribeUserTy(variance)) => variance,
1452 }
1453 }
1454}