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::AsyncDropGlueCtorShim(_def_id, None)
357 | ty::InstanceKind::DropGlue(_def_id, None) => {}
358
359 ty::InstanceKind::FnPtrShim(_def_id, ty)
360 | ty::InstanceKind::DropGlue(_def_id, Some(ty))
361 | ty::InstanceKind::CloneShim(_def_id, ty)
362 | ty::InstanceKind::FnPtrAddrShim(_def_id, ty)
363 | ty::InstanceKind::AsyncDropGlueCtorShim(_def_id, Some(ty)) => {
364 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
366 }
367 }
368 self.visit_args(callee_args, location);
369 }
370 if let Some(inlined_parent_scope) = inlined_parent_scope {
371 self.visit_source_scope($(& $mutability)? *inlined_parent_scope);
372 }
373 }
374
375 fn super_statement(
376 &mut self,
377 statement: & $($mutability)? Statement<'tcx>,
378 location: Location
379 ) {
380 let Statement { source_info, kind } = statement;
381
382 self.visit_source_info(source_info);
383 match kind {
384 StatementKind::Assign(box (place, rvalue)) => {
385 self.visit_assign(place, rvalue, location);
386 }
387 StatementKind::FakeRead(box (_, place)) => {
388 self.visit_place(
389 place,
390 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
391 location
392 );
393 }
394 StatementKind::SetDiscriminant { place, .. } => {
395 self.visit_place(
396 place,
397 PlaceContext::MutatingUse(MutatingUseContext::SetDiscriminant),
398 location
399 );
400 }
401 StatementKind::Deinit(place) => {
402 self.visit_place(
403 place,
404 PlaceContext::MutatingUse(MutatingUseContext::Deinit),
405 location
406 )
407 }
408 StatementKind::StorageLive(local) => {
409 self.visit_local(
410 $(& $mutability)? *local,
411 PlaceContext::NonUse(NonUseContext::StorageLive),
412 location
413 );
414 }
415 StatementKind::StorageDead(local) => {
416 self.visit_local(
417 $(& $mutability)? *local,
418 PlaceContext::NonUse(NonUseContext::StorageDead),
419 location
420 );
421 }
422 StatementKind::Retag(kind, place) => {
423 self.visit_retag($(& $mutability)? *kind, place, location);
424 }
425 StatementKind::PlaceMention(place) => {
426 self.visit_place(
427 place,
428 PlaceContext::NonMutatingUse(NonMutatingUseContext::PlaceMention),
429 location
430 );
431 }
432 StatementKind::AscribeUserType(box (place, user_ty), variance) => {
433 self.visit_ascribe_user_ty(
434 place,
435 $(& $mutability)? *variance,
436 user_ty,
437 location
438 );
439 }
440 StatementKind::Coverage(coverage) => {
441 self.visit_coverage(
442 coverage,
443 location
444 )
445 }
446 StatementKind::Intrinsic(box intrinsic) => {
447 match intrinsic {
448 NonDivergingIntrinsic::Assume(op) => self.visit_operand(op, location),
449 NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
450 src,
451 dst,
452 count
453 }) => {
454 self.visit_operand(src, location);
455 self.visit_operand(dst, location);
456 self.visit_operand(count, location);
457 }
458 }
459 }
460 StatementKind::ConstEvalCounter => {}
461 StatementKind::Nop => {}
462 StatementKind::BackwardIncompatibleDropHint { .. } => {}
463 }
464 }
465
466 fn super_assign(
467 &mut self,
468 place: &$($mutability)? Place<'tcx>,
469 rvalue: &$($mutability)? Rvalue<'tcx>,
470 location: Location
471 ) {
472 self.visit_place(
473 place,
474 PlaceContext::MutatingUse(MutatingUseContext::Store),
475 location
476 );
477 self.visit_rvalue(rvalue, location);
478 }
479
480 fn super_terminator(
481 &mut self,
482 terminator: &$($mutability)? Terminator<'tcx>,
483 location: Location
484 ) {
485 let Terminator { source_info, kind } = terminator;
486
487 self.visit_source_info(source_info);
488 match kind {
489 TerminatorKind::Goto { .. }
490 | TerminatorKind::UnwindResume
491 | TerminatorKind::UnwindTerminate(_)
492 | TerminatorKind::CoroutineDrop
493 | TerminatorKind::Unreachable
494 | TerminatorKind::FalseEdge { .. }
495 | TerminatorKind::FalseUnwind { .. } => {}
496
497 TerminatorKind::Return => {
498 let $($mutability)? local = RETURN_PLACE;
501 self.visit_local(
502 $(& $mutability)? local,
503 PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
504 location,
505 );
506
507 assert_eq!(
508 local,
509 RETURN_PLACE,
510 "`MutVisitor` tried to mutate return place of `return` terminator"
511 );
512 }
513
514 TerminatorKind::SwitchInt { discr, targets: _ } => {
515 self.visit_operand(discr, location);
516 }
517
518 TerminatorKind::Drop { place, target: _, unwind: _, replace: _ } => {
519 self.visit_place(
520 place,
521 PlaceContext::MutatingUse(MutatingUseContext::Drop),
522 location
523 );
524 }
525
526 TerminatorKind::Call {
527 func,
528 args,
529 destination,
530 target: _,
531 unwind: _,
532 call_source: _,
533 fn_span,
534 } => {
535 self.visit_span($(& $mutability)? *fn_span);
536 self.visit_operand(func, location);
537 for arg in args {
538 self.visit_operand(&$($mutability)? arg.node, location);
539 }
540 self.visit_place(
541 destination,
542 PlaceContext::MutatingUse(MutatingUseContext::Call),
543 location
544 );
545 }
546
547 TerminatorKind::TailCall { func, args, fn_span } => {
548 self.visit_span($(& $mutability)? *fn_span);
549 self.visit_operand(func, location);
550 for arg in args {
551 self.visit_operand(&$($mutability)? arg.node, location);
552 }
553 },
554
555 TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
556 self.visit_operand(cond, location);
557 self.visit_assert_message(msg, location);
558 }
559
560 TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
561 self.visit_operand(value, location);
562 self.visit_place(
563 resume_arg,
564 PlaceContext::MutatingUse(MutatingUseContext::Yield),
565 location,
566 );
567 }
568
569 TerminatorKind::InlineAsm {
570 asm_macro: _,
571 template: _,
572 operands,
573 options: _,
574 line_spans: _,
575 targets: _,
576 unwind: _,
577 } => {
578 for op in operands {
579 match op {
580 InlineAsmOperand::In { value, .. } => {
581 self.visit_operand(value, location);
582 }
583 InlineAsmOperand::Out { place: Some(place), .. } => {
584 self.visit_place(
585 place,
586 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
587 location,
588 );
589 }
590 InlineAsmOperand::InOut { in_value, out_place, .. } => {
591 self.visit_operand(in_value, location);
592 if let Some(out_place) = out_place {
593 self.visit_place(
594 out_place,
595 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
596 location,
597 );
598 }
599 }
600 InlineAsmOperand::Const { value }
601 | InlineAsmOperand::SymFn { value } => {
602 self.visit_const_operand(value, location);
603 }
604 InlineAsmOperand::Out { place: None, .. }
605 | InlineAsmOperand::SymStatic { def_id: _ }
606 | InlineAsmOperand::Label { target_index: _ } => {}
607 }
608 }
609 }
610 }
611 }
612
613 fn super_assert_message(
614 &mut self,
615 msg: & $($mutability)? AssertMessage<'tcx>,
616 location: Location
617 ) {
618 use crate::mir::AssertKind::*;
619 match msg {
620 BoundsCheck { len, index } => {
621 self.visit_operand(len, location);
622 self.visit_operand(index, location);
623 }
624 Overflow(_, l, r) => {
625 self.visit_operand(l, location);
626 self.visit_operand(r, location);
627 }
628 OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
629 self.visit_operand(op, location);
630 }
631 ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference => {
632 }
634 MisalignedPointerDereference { required, found } => {
635 self.visit_operand(required, location);
636 self.visit_operand(found, location);
637 }
638 }
639 }
640
641 fn super_rvalue(
642 &mut self,
643 rvalue: & $($mutability)? Rvalue<'tcx>,
644 location: Location
645 ) {
646 match rvalue {
647 Rvalue::Use(operand) => {
648 self.visit_operand(operand, location);
649 }
650
651 Rvalue::Repeat(value, ct) => {
652 self.visit_operand(value, location);
653 self.visit_ty_const($(&$mutability)? *ct, location);
654 }
655
656 Rvalue::ThreadLocalRef(_) => {}
657
658 Rvalue::Ref(r, bk, path) => {
659 self.visit_region($(& $mutability)? *r, location);
660 let ctx = match bk {
661 BorrowKind::Shared => PlaceContext::NonMutatingUse(
662 NonMutatingUseContext::SharedBorrow
663 ),
664 BorrowKind::Fake(_) => PlaceContext::NonMutatingUse(
665 NonMutatingUseContext::FakeBorrow
666 ),
667 BorrowKind::Mut { .. } =>
668 PlaceContext::MutatingUse(MutatingUseContext::Borrow),
669 };
670 self.visit_place(path, ctx, location);
671 }
672
673 Rvalue::CopyForDeref(place) => {
674 self.visit_place(
675 place,
676 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
677 location
678 );
679 }
680
681 Rvalue::RawPtr(m, path) => {
682 let ctx = match m {
683 RawPtrKind::Mut => PlaceContext::MutatingUse(
684 MutatingUseContext::RawBorrow
685 ),
686 RawPtrKind::Const => PlaceContext::NonMutatingUse(
687 NonMutatingUseContext::RawBorrow
688 ),
689 RawPtrKind::FakeForPtrMetadata => PlaceContext::NonMutatingUse(
690 NonMutatingUseContext::Inspect
691 ),
692 };
693 self.visit_place(path, ctx, location);
694 }
695
696 Rvalue::Len(path) => {
697 self.visit_place(
698 path,
699 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
700 location
701 );
702 }
703
704 Rvalue::Cast(_cast_kind, operand, ty) => {
705 self.visit_operand(operand, location);
706 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
707 }
708
709 Rvalue::BinaryOp(_bin_op, box(lhs, rhs)) => {
710 self.visit_operand(lhs, location);
711 self.visit_operand(rhs, location);
712 }
713
714 Rvalue::UnaryOp(_un_op, op) => {
715 self.visit_operand(op, location);
716 }
717
718 Rvalue::Discriminant(place) => {
719 self.visit_place(
720 place,
721 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
722 location
723 );
724 }
725
726 Rvalue::NullaryOp(_op, ty) => {
727 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
728 }
729
730 Rvalue::Aggregate(kind, operands) => {
731 let kind = &$($mutability)? **kind;
732 match kind {
733 AggregateKind::Array(ty) => {
734 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
735 }
736 AggregateKind::Tuple => {}
737 AggregateKind::Adt(
738 _adt_def,
739 _variant_index,
740 args,
741 _user_args,
742 _active_field_index
743 ) => {
744 self.visit_args(args, location);
745 }
746 AggregateKind::Closure(_, closure_args) => {
747 self.visit_args(closure_args, location);
748 }
749 AggregateKind::Coroutine(_, coroutine_args) => {
750 self.visit_args(coroutine_args, location);
751 }
752 AggregateKind::CoroutineClosure(_, coroutine_closure_args) => {
753 self.visit_args(coroutine_closure_args, location);
754 }
755 AggregateKind::RawPtr(ty, _) => {
756 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
757 }
758 }
759
760 for operand in operands {
761 self.visit_operand(operand, location);
762 }
763 }
764
765 Rvalue::ShallowInitBox(operand, ty) => {
766 self.visit_operand(operand, location);
767 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
768 }
769
770 Rvalue::WrapUnsafeBinder(op, ty) => {
771 self.visit_operand(op, location);
772 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
773 }
774 }
775 }
776
777 fn super_operand(
778 &mut self,
779 operand: & $($mutability)? Operand<'tcx>,
780 location: Location
781 ) {
782 match operand {
783 Operand::Copy(place) => {
784 self.visit_place(
785 place,
786 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
787 location
788 );
789 }
790 Operand::Move(place) => {
791 self.visit_place(
792 place,
793 PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
794 location
795 );
796 }
797 Operand::Constant(constant) => {
798 self.visit_const_operand(constant, location);
799 }
800 }
801 }
802
803 fn super_ascribe_user_ty(
804 &mut self,
805 place: & $($mutability)? Place<'tcx>,
806 variance: $(& $mutability)? ty::Variance,
807 user_ty: & $($mutability)? UserTypeProjection,
808 location: Location)
809 {
810 self.visit_place(
811 place,
812 PlaceContext::NonUse(
813 NonUseContext::AscribeUserTy($(* &$mutability *)? variance)
814 ),
815 location
816 );
817 self.visit_user_type_projection(user_ty);
818 }
819
820 fn super_coverage(
821 &mut self,
822 _kind: & $($mutability)? coverage::CoverageKind,
823 _location: Location
824 ) {
825 }
826
827 fn super_retag(
828 &mut self,
829 _kind: $(& $mutability)? RetagKind,
830 place: & $($mutability)? Place<'tcx>,
831 location: Location
832 ) {
833 self.visit_place(
834 place,
835 PlaceContext::MutatingUse(MutatingUseContext::Retag),
836 location,
837 );
838 }
839
840 fn super_local_decl(
841 &mut self,
842 local: Local,
843 local_decl: & $($mutability)? LocalDecl<'tcx>
844 ) {
845 let LocalDecl {
846 mutability: _,
847 ty,
848 user_ty,
849 source_info,
850 local_info: _,
851 } = local_decl;
852
853 self.visit_source_info(source_info);
854
855 self.visit_ty($(& $mutability)? *ty, TyContext::LocalDecl {
856 local,
857 source_info: *source_info,
858 });
859 if let Some(user_ty) = user_ty {
860 for user_ty in & $($mutability)? user_ty.contents {
861 self.visit_user_type_projection(user_ty);
862 }
863 }
864 }
865
866 fn super_local(
867 &mut self,
868 _local: $(& $mutability)? Local,
869 _context: PlaceContext,
870 _location: Location,
871 ) {
872 }
873
874 fn super_var_debug_info(
875 &mut self,
876 var_debug_info: & $($mutability)? VarDebugInfo<'tcx>
877 ) {
878 let VarDebugInfo {
879 name: _,
880 source_info,
881 composite,
882 value,
883 argument_index: _,
884 } = var_debug_info;
885
886 self.visit_source_info(source_info);
887 let location = Location::START;
888 if let Some(box VarDebugInfoFragment {
889 ty,
890 projection
891 }) = composite {
892 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
893 for elem in projection {
894 let ProjectionElem::Field(_, ty) = elem else { bug!() };
895 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
896 }
897 }
898 match value {
899 VarDebugInfoContents::Const(c) => self.visit_const_operand(c, location),
900 VarDebugInfoContents::Place(place) =>
901 self.visit_place(
902 place,
903 PlaceContext::NonUse(NonUseContext::VarDebugInfo),
904 location
905 ),
906 }
907 }
908
909 fn super_source_scope(&mut self, _scope: $(& $mutability)? SourceScope) {}
910
911 fn super_const_operand(
912 &mut self,
913 constant: & $($mutability)? ConstOperand<'tcx>,
914 location: Location
915 ) {
916 let ConstOperand {
917 span,
918 user_ty: _, const_,
920 } = constant;
921
922 self.visit_span($(& $mutability)? *span);
923 match const_ {
924 Const::Ty(_, ct) => self.visit_ty_const($(&$mutability)? *ct, location),
925 Const::Val(_, ty) => {
926 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
927 }
928 Const::Unevaluated(_, ty) => {
929 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
930 }
931 }
932 }
933
934 fn super_ty_const(
935 &mut self,
936 _ct: $(& $mutability)? ty::Const<'tcx>,
937 _location: Location,
938 ) {
939 }
940
941 fn super_span(&mut self, _span: $(& $mutability)? Span) {}
942
943 fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) {
944 let SourceInfo { span, scope } = source_info;
945
946 self.visit_span($(& $mutability)? *span);
947 self.visit_source_scope($(& $mutability)? *scope);
948 }
949
950 fn super_user_type_projection(&mut self, _ty: & $($mutability)? UserTypeProjection) {}
951
952 fn super_user_type_annotation(
953 &mut self,
954 _index: UserTypeAnnotationIndex,
955 ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
956 ) {
957 self.visit_span($(& $mutability)? ty.span);
958 self.visit_ty($(& $mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
959 }
960
961 fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {}
962
963 fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) {}
964
965 fn super_args(&mut self, _args: & $($mutability)? GenericArgsRef<'tcx>) {}
966
967 fn visit_location(
970 &mut self,
971 body: &$($mutability)? Body<'tcx>,
972 location: Location
973 ) {
974 let basic_block =
975 & $($mutability)? basic_blocks!(body, $($mutability, true)?)[location.block];
976 if basic_block.statements.len() == location.statement_index {
977 if let Some(ref $($mutability)? terminator) = basic_block.terminator {
978 self.visit_terminator(terminator, location)
979 }
980 } else {
981 let statement = & $($mutability)?
982 basic_block.statements[location.statement_index];
983 self.visit_statement(statement, location)
984 }
985 }
986 }
987 }
988}
989
990macro_rules! basic_blocks {
991 ($body:ident, mut, true) => {
992 $body.basic_blocks.as_mut()
993 };
994 ($body:ident, mut, false) => {
995 $body.basic_blocks.as_mut_preserves_cfg()
996 };
997 ($body:ident,) => {
998 $body.basic_blocks
999 };
1000}
1001
1002macro_rules! basic_blocks_iter {
1003 ($body:ident, mut, $invalidate:tt) => {
1004 basic_blocks!($body, mut, $invalidate).iter_enumerated_mut()
1005 };
1006 ($body:ident,) => {
1007 basic_blocks!($body,).iter_enumerated()
1008 };
1009}
1010
1011macro_rules! extra_body_methods {
1012 (mut) => {
1013 fn visit_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
1014 self.super_body_preserves_cfg(body);
1015 }
1016
1017 fn super_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
1018 super_body!(self, body, mut, false);
1019 }
1020 };
1021 () => {};
1022}
1023
1024macro_rules! super_body {
1025 ($self:ident, $body:ident, $($mutability:ident, $invalidate:tt)?) => {
1026 let span = $body.span;
1027 if let Some(coroutine) = &$($mutability)? $body.coroutine {
1028 if let Some(yield_ty) = $(& $mutability)? coroutine.yield_ty {
1029 $self.visit_ty(
1030 yield_ty,
1031 TyContext::YieldTy(SourceInfo::outermost(span))
1032 );
1033 }
1034 if let Some(resume_ty) = $(& $mutability)? coroutine.resume_ty {
1035 $self.visit_ty(
1036 resume_ty,
1037 TyContext::ResumeTy(SourceInfo::outermost(span))
1038 );
1039 }
1040 }
1041
1042 for (bb, data) in basic_blocks_iter!($body, $($mutability, $invalidate)?) {
1043 $self.visit_basic_block_data(bb, data);
1044 }
1045
1046 for scope in &$($mutability)? $body.source_scopes {
1047 $self.visit_source_scope_data(scope);
1048 }
1049
1050 $self.visit_ty(
1051 $(& $mutability)? $body.return_ty(),
1052 TyContext::ReturnTy(SourceInfo::outermost($body.span))
1053 );
1054
1055 for local in $body.local_decls.indices() {
1056 $self.visit_local_decl(local, & $($mutability)? $body.local_decls[local]);
1057 }
1058
1059 #[allow(unused_macro_rules)]
1060 macro_rules! type_annotations {
1061 (mut) => ($body.user_type_annotations.iter_enumerated_mut());
1062 () => ($body.user_type_annotations.iter_enumerated());
1063 }
1064
1065 for (index, annotation) in type_annotations!($($mutability)?) {
1066 $self.visit_user_type_annotation(
1067 index, annotation
1068 );
1069 }
1070
1071 for var_debug_info in &$($mutability)? $body.var_debug_info {
1072 $self.visit_var_debug_info(var_debug_info);
1073 }
1074
1075 $self.visit_span($(& $mutability)? $body.span);
1076
1077 if let Some(required_consts) = &$($mutability)? $body.required_consts {
1078 for const_ in required_consts {
1079 let location = Location::START;
1080 $self.visit_const_operand(const_, location);
1081 }
1082 }
1083 }
1084}
1085
1086macro_rules! visit_place_fns {
1087 (mut) => {
1088 fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
1089
1090 fn super_place(
1091 &mut self,
1092 place: &mut Place<'tcx>,
1093 context: PlaceContext,
1094 location: Location,
1095 ) {
1096 self.visit_local(&mut place.local, context, location);
1097
1098 if let Some(new_projection) = self.process_projection(&place.projection, location) {
1099 place.projection = self.tcx().mk_place_elems(&new_projection);
1100 }
1101 }
1102
1103 fn process_projection<'a>(
1104 &mut self,
1105 projection: &'a [PlaceElem<'tcx>],
1106 location: Location,
1107 ) -> Option<Vec<PlaceElem<'tcx>>> {
1108 let mut projection = Cow::Borrowed(projection);
1109
1110 for i in 0..projection.len() {
1111 if let Some(&elem) = projection.get(i) {
1112 if let Some(elem) = self.process_projection_elem(elem, location) {
1113 let vec = projection.to_mut();
1116 vec[i] = elem;
1117 }
1118 }
1119 }
1120
1121 match projection {
1122 Cow::Borrowed(_) => None,
1123 Cow::Owned(vec) => Some(vec),
1124 }
1125 }
1126
1127 fn process_projection_elem(
1128 &mut self,
1129 elem: PlaceElem<'tcx>,
1130 location: Location,
1131 ) -> Option<PlaceElem<'tcx>> {
1132 match elem {
1133 PlaceElem::Index(local) => {
1134 let mut new_local = local;
1135 self.visit_local(
1136 &mut new_local,
1137 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
1138 location,
1139 );
1140
1141 if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
1142 }
1143 PlaceElem::Field(field, ty) => {
1144 let mut new_ty = ty;
1145 self.visit_ty(&mut new_ty, TyContext::Location(location));
1146 if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
1147 }
1148 PlaceElem::OpaqueCast(ty) => {
1149 let mut new_ty = ty;
1150 self.visit_ty(&mut new_ty, TyContext::Location(location));
1151 if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None }
1152 }
1153 PlaceElem::Subtype(ty) => {
1154 let mut new_ty = ty;
1155 self.visit_ty(&mut new_ty, TyContext::Location(location));
1156 if ty != new_ty { Some(PlaceElem::Subtype(new_ty)) } else { None }
1157 }
1158 PlaceElem::UnwrapUnsafeBinder(ty) => {
1159 let mut new_ty = ty;
1160 self.visit_ty(&mut new_ty, TyContext::Location(location));
1161 if ty != new_ty { Some(PlaceElem::UnwrapUnsafeBinder(new_ty)) } else { None }
1162 }
1163 PlaceElem::Deref
1164 | PlaceElem::ConstantIndex { .. }
1165 | PlaceElem::Subslice { .. }
1166 | PlaceElem::Downcast(..) => None,
1167 }
1168 }
1169 };
1170
1171 () => {
1172 fn visit_projection(
1173 &mut self,
1174 place_ref: PlaceRef<'tcx>,
1175 context: PlaceContext,
1176 location: Location,
1177 ) {
1178 self.super_projection(place_ref, context, location);
1179 }
1180
1181 fn visit_projection_elem(
1182 &mut self,
1183 place_ref: PlaceRef<'tcx>,
1184 elem: PlaceElem<'tcx>,
1185 context: PlaceContext,
1186 location: Location,
1187 ) {
1188 self.super_projection_elem(place_ref, elem, context, location);
1189 }
1190
1191 fn super_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
1192 let mut context = context;
1193
1194 if !place.projection.is_empty() {
1195 if context.is_use() {
1196 context = if context.is_mutating_use() {
1198 PlaceContext::MutatingUse(MutatingUseContext::Projection)
1199 } else {
1200 PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
1201 };
1202 }
1203 }
1204
1205 self.visit_local(place.local, context, location);
1206
1207 self.visit_projection(place.as_ref(), context, location);
1208 }
1209
1210 fn super_projection(
1211 &mut self,
1212 place_ref: PlaceRef<'tcx>,
1213 context: PlaceContext,
1214 location: Location,
1215 ) {
1216 for (base, elem) in place_ref.iter_projections().rev() {
1217 self.visit_projection_elem(base, elem, context, location);
1218 }
1219 }
1220
1221 fn super_projection_elem(
1222 &mut self,
1223 _place_ref: PlaceRef<'tcx>,
1224 elem: PlaceElem<'tcx>,
1225 _context: PlaceContext,
1226 location: Location,
1227 ) {
1228 match elem {
1229 ProjectionElem::OpaqueCast(ty)
1230 | ProjectionElem::Subtype(ty)
1231 | ProjectionElem::Field(_, ty)
1232 | ProjectionElem::UnwrapUnsafeBinder(ty) => {
1233 self.visit_ty(ty, TyContext::Location(location));
1234 }
1235 ProjectionElem::Index(local) => {
1236 self.visit_local(
1237 local,
1238 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
1239 location,
1240 );
1241 }
1242 ProjectionElem::Deref
1243 | ProjectionElem::Subslice { from: _, to: _, from_end: _ }
1244 | ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ }
1245 | ProjectionElem::Downcast(_, _) => {}
1246 }
1247 }
1248 };
1249}
1250
1251make_mir_visitor!(Visitor,);
1252make_mir_visitor!(MutVisitor, mut);
1253
1254#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1257pub enum TyContext {
1258 LocalDecl {
1259 local: Local,
1261
1262 source_info: SourceInfo,
1264 },
1265
1266 UserTy(Span),
1268
1269 ReturnTy(SourceInfo),
1271
1272 YieldTy(SourceInfo),
1273
1274 ResumeTy(SourceInfo),
1275
1276 Location(Location),
1278}
1279
1280#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1281pub enum NonMutatingUseContext {
1282 Inspect,
1284 Copy,
1286 Move,
1288 SharedBorrow,
1290 FakeBorrow,
1294 RawBorrow,
1296 PlaceMention,
1301 Projection,
1308}
1309
1310#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1311pub enum MutatingUseContext {
1312 Store,
1314 SetDiscriminant,
1316 Deinit,
1318 AsmOutput,
1320 Call,
1322 Yield,
1324 Drop,
1326 Borrow,
1328 RawBorrow,
1330 Projection,
1337 Retag,
1339}
1340
1341#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1342pub enum NonUseContext {
1343 StorageLive,
1345 StorageDead,
1347 AscribeUserTy(ty::Variance),
1349 VarDebugInfo,
1351}
1352
1353#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1354pub enum PlaceContext {
1355 NonMutatingUse(NonMutatingUseContext),
1356 MutatingUse(MutatingUseContext),
1357 NonUse(NonUseContext),
1358}
1359
1360impl PlaceContext {
1361 #[inline]
1363 pub fn is_drop(self) -> bool {
1364 matches!(self, PlaceContext::MutatingUse(MutatingUseContext::Drop))
1365 }
1366
1367 pub fn is_borrow(self) -> bool {
1370 matches!(
1371 self,
1372 PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
1373 | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
1374 )
1375 }
1376
1377 pub fn is_address_of(self) -> bool {
1379 matches!(
1380 self,
1381 PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow)
1382 | PlaceContext::MutatingUse(MutatingUseContext::RawBorrow)
1383 )
1384 }
1385
1386 #[inline]
1388 pub fn is_storage_marker(self) -> bool {
1389 matches!(
1390 self,
1391 PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead)
1392 )
1393 }
1394
1395 #[inline]
1397 pub fn is_mutating_use(self) -> bool {
1398 matches!(self, PlaceContext::MutatingUse(..))
1399 }
1400
1401 #[inline]
1403 pub fn is_use(self) -> bool {
1404 !matches!(self, PlaceContext::NonUse(..))
1405 }
1406
1407 pub fn is_place_assignment(self) -> bool {
1409 matches!(
1410 self,
1411 PlaceContext::MutatingUse(
1412 MutatingUseContext::Store
1413 | MutatingUseContext::Call
1414 | MutatingUseContext::AsmOutput,
1415 )
1416 )
1417 }
1418
1419 pub fn ambient_variance(self) -> ty::Variance {
1421 use NonMutatingUseContext::*;
1422 use NonUseContext::*;
1423 match self {
1424 PlaceContext::MutatingUse(_) => ty::Invariant,
1425 PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
1426 PlaceContext::NonMutatingUse(
1427 Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | RawBorrow
1428 | Projection,
1429 ) => ty::Covariant,
1430 PlaceContext::NonUse(AscribeUserTy(variance)) => variance,
1431 }
1432 }
1433}