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 if let Some(async_fut) = async_fut {
542 self.visit_local(
543 $(&$mutability)? *async_fut,
544 PlaceContext::MutatingUse(MutatingUseContext::Borrow),
545 location
546 );
547 }
548 }
549
550 TerminatorKind::Call {
551 func,
552 args,
553 destination,
554 target: _,
555 unwind: _,
556 call_source: _,
557 fn_span,
558 } => {
559 self.visit_span($(& $mutability)? *fn_span);
560 self.visit_operand(func, location);
561 for arg in args {
562 self.visit_operand(&$($mutability)? arg.node, location);
563 }
564 self.visit_place(
565 destination,
566 PlaceContext::MutatingUse(MutatingUseContext::Call),
567 location
568 );
569 }
570
571 TerminatorKind::TailCall { func, args, fn_span } => {
572 self.visit_span($(& $mutability)? *fn_span);
573 self.visit_operand(func, location);
574 for arg in args {
575 self.visit_operand(&$($mutability)? arg.node, location);
576 }
577 },
578
579 TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
580 self.visit_operand(cond, location);
581 self.visit_assert_message(msg, location);
582 }
583
584 TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
585 self.visit_operand(value, location);
586 self.visit_place(
587 resume_arg,
588 PlaceContext::MutatingUse(MutatingUseContext::Yield),
589 location,
590 );
591 }
592
593 TerminatorKind::InlineAsm {
594 asm_macro: _,
595 template: _,
596 operands,
597 options: _,
598 line_spans: _,
599 targets: _,
600 unwind: _,
601 } => {
602 for op in operands {
603 match op {
604 InlineAsmOperand::In { value, .. } => {
605 self.visit_operand(value, location);
606 }
607 InlineAsmOperand::Out { place: Some(place), .. } => {
608 self.visit_place(
609 place,
610 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
611 location,
612 );
613 }
614 InlineAsmOperand::InOut { in_value, out_place, .. } => {
615 self.visit_operand(in_value, location);
616 if let Some(out_place) = out_place {
617 self.visit_place(
618 out_place,
619 PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
620 location,
621 );
622 }
623 }
624 InlineAsmOperand::Const { value }
625 | InlineAsmOperand::SymFn { value } => {
626 self.visit_const_operand(value, location);
627 }
628 InlineAsmOperand::Out { place: None, .. }
629 | InlineAsmOperand::SymStatic { def_id: _ }
630 | InlineAsmOperand::Label { target_index: _ } => {}
631 }
632 }
633 }
634 }
635 }
636
637 fn super_assert_message(
638 &mut self,
639 msg: & $($mutability)? AssertMessage<'tcx>,
640 location: Location
641 ) {
642 use crate::mir::AssertKind::*;
643 match msg {
644 BoundsCheck { len, index } => {
645 self.visit_operand(len, location);
646 self.visit_operand(index, location);
647 }
648 Overflow(_, l, r) => {
649 self.visit_operand(l, location);
650 self.visit_operand(r, location);
651 }
652 OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) | InvalidEnumConstruction(op) => {
653 self.visit_operand(op, location);
654 }
655 ResumedAfterReturn(_) | ResumedAfterPanic(_) | NullPointerDereference | ResumedAfterDrop(_) => {
656 }
658 MisalignedPointerDereference { required, found } => {
659 self.visit_operand(required, location);
660 self.visit_operand(found, location);
661 }
662 }
663 }
664
665 fn super_rvalue(
666 &mut self,
667 rvalue: & $($mutability)? Rvalue<'tcx>,
668 location: Location
669 ) {
670 match rvalue {
671 Rvalue::Use(operand) => {
672 self.visit_operand(operand, location);
673 }
674
675 Rvalue::Repeat(value, ct) => {
676 self.visit_operand(value, location);
677 self.visit_ty_const($(&$mutability)? *ct, location);
678 }
679
680 Rvalue::ThreadLocalRef(_) => {}
681
682 Rvalue::Ref(r, bk, path) => {
683 self.visit_region($(& $mutability)? *r, location);
684 let ctx = match bk {
685 BorrowKind::Shared => PlaceContext::NonMutatingUse(
686 NonMutatingUseContext::SharedBorrow
687 ),
688 BorrowKind::Fake(_) => PlaceContext::NonMutatingUse(
689 NonMutatingUseContext::FakeBorrow
690 ),
691 BorrowKind::Mut { .. } =>
692 PlaceContext::MutatingUse(MutatingUseContext::Borrow),
693 };
694 self.visit_place(path, ctx, location);
695 }
696
697 Rvalue::CopyForDeref(place) => {
698 self.visit_place(
699 place,
700 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
701 location
702 );
703 }
704
705 Rvalue::RawPtr(m, path) => {
706 let ctx = match m {
707 RawPtrKind::Mut => PlaceContext::MutatingUse(
708 MutatingUseContext::RawBorrow
709 ),
710 RawPtrKind::Const => PlaceContext::NonMutatingUse(
711 NonMutatingUseContext::RawBorrow
712 ),
713 RawPtrKind::FakeForPtrMetadata => PlaceContext::NonMutatingUse(
714 NonMutatingUseContext::Inspect
715 ),
716 };
717 self.visit_place(path, ctx, location);
718 }
719
720 Rvalue::Cast(_cast_kind, operand, ty) => {
721 self.visit_operand(operand, location);
722 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
723 }
724
725 Rvalue::BinaryOp(_bin_op, box(lhs, rhs)) => {
726 self.visit_operand(lhs, location);
727 self.visit_operand(rhs, location);
728 }
729
730 Rvalue::UnaryOp(_un_op, op) => {
731 self.visit_operand(op, location);
732 }
733
734 Rvalue::Discriminant(place) => {
735 self.visit_place(
736 place,
737 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
738 location
739 );
740 }
741
742 Rvalue::NullaryOp(_op, ty) => {
743 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
744 }
745
746 Rvalue::Aggregate(kind, operands) => {
747 let kind = &$($mutability)? **kind;
748 match kind {
749 AggregateKind::Array(ty) => {
750 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
751 }
752 AggregateKind::Tuple => {}
753 AggregateKind::Adt(
754 _adt_def,
755 _variant_index,
756 args,
757 _user_args,
758 _active_field_index
759 ) => {
760 self.visit_args(args, location);
761 }
762 AggregateKind::Closure(_, closure_args) => {
763 self.visit_args(closure_args, location);
764 }
765 AggregateKind::Coroutine(_, coroutine_args) => {
766 self.visit_args(coroutine_args, location);
767 }
768 AggregateKind::CoroutineClosure(_, coroutine_closure_args) => {
769 self.visit_args(coroutine_closure_args, location);
770 }
771 AggregateKind::RawPtr(ty, _) => {
772 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
773 }
774 }
775
776 for operand in operands {
777 self.visit_operand(operand, location);
778 }
779 }
780
781 Rvalue::ShallowInitBox(operand, ty) => {
782 self.visit_operand(operand, location);
783 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
784 }
785
786 Rvalue::WrapUnsafeBinder(op, ty) => {
787 self.visit_operand(op, location);
788 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
789 }
790 }
791 }
792
793 fn super_operand(
794 &mut self,
795 operand: & $($mutability)? Operand<'tcx>,
796 location: Location
797 ) {
798 match operand {
799 Operand::Copy(place) => {
800 self.visit_place(
801 place,
802 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
803 location
804 );
805 }
806 Operand::Move(place) => {
807 self.visit_place(
808 place,
809 PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
810 location
811 );
812 }
813 Operand::Constant(constant) => {
814 self.visit_const_operand(constant, location);
815 }
816 }
817 }
818
819 fn super_ascribe_user_ty(
820 &mut self,
821 place: & $($mutability)? Place<'tcx>,
822 variance: $(& $mutability)? ty::Variance,
823 user_ty: & $($mutability)? UserTypeProjection,
824 location: Location)
825 {
826 self.visit_place(
827 place,
828 PlaceContext::NonUse(
829 NonUseContext::AscribeUserTy($(* &$mutability *)? variance)
830 ),
831 location
832 );
833 self.visit_user_type_projection(user_ty);
834 }
835
836 fn super_coverage(
837 &mut self,
838 _kind: & $($mutability)? coverage::CoverageKind,
839 _location: Location
840 ) {
841 }
842
843 fn super_retag(
844 &mut self,
845 _kind: $(& $mutability)? RetagKind,
846 place: & $($mutability)? Place<'tcx>,
847 location: Location
848 ) {
849 self.visit_place(
850 place,
851 PlaceContext::MutatingUse(MutatingUseContext::Retag),
852 location,
853 );
854 }
855
856 fn super_local_decl(
857 &mut self,
858 local: Local,
859 local_decl: & $($mutability)? LocalDecl<'tcx>
860 ) {
861 let LocalDecl {
862 mutability: _,
863 ty,
864 user_ty,
865 source_info,
866 local_info: _,
867 } = local_decl;
868
869 self.visit_source_info(source_info);
870
871 self.visit_ty($(& $mutability)? *ty, TyContext::LocalDecl {
872 local,
873 source_info: *source_info,
874 });
875 if let Some(user_ty) = user_ty {
876 for user_ty in & $($mutability)? user_ty.contents {
877 self.visit_user_type_projection(user_ty);
878 }
879 }
880 }
881
882 fn super_local(
883 &mut self,
884 _local: $(& $mutability)? Local,
885 _context: PlaceContext,
886 _location: Location,
887 ) {
888 }
889
890 fn super_var_debug_info(
891 &mut self,
892 var_debug_info: & $($mutability)? VarDebugInfo<'tcx>
893 ) {
894 let VarDebugInfo {
895 name: _,
896 source_info,
897 composite,
898 value,
899 argument_index: _,
900 } = var_debug_info;
901
902 self.visit_source_info(source_info);
903 let location = Location::START;
904 if let Some(box VarDebugInfoFragment {
905 ty,
906 projection
907 }) = composite {
908 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
909 for elem in projection {
910 let ProjectionElem::Field(_, ty) = elem else { bug!() };
911 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
912 }
913 }
914 match value {
915 VarDebugInfoContents::Const(c) => self.visit_const_operand(c, location),
916 VarDebugInfoContents::Place(place) =>
917 self.visit_place(
918 place,
919 PlaceContext::NonUse(NonUseContext::VarDebugInfo),
920 location
921 ),
922 }
923 }
924
925 fn super_source_scope(&mut self, _scope: $(& $mutability)? SourceScope) {}
926
927 fn super_const_operand(
928 &mut self,
929 constant: & $($mutability)? ConstOperand<'tcx>,
930 location: Location
931 ) {
932 let ConstOperand {
933 span,
934 user_ty: _, const_,
936 } = constant;
937
938 self.visit_span($(& $mutability)? *span);
939 match const_ {
940 Const::Ty(_, ct) => self.visit_ty_const($(&$mutability)? *ct, location),
941 Const::Val(_, ty) => {
942 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
943 }
944 Const::Unevaluated(_, ty) => {
945 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
946 }
947 }
948 }
949
950 fn super_ty_const(
951 &mut self,
952 _ct: $(& $mutability)? ty::Const<'tcx>,
953 _location: Location,
954 ) {
955 }
956
957 fn super_span(&mut self, _span: $(& $mutability)? Span) {}
958
959 fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) {
960 let SourceInfo { span, scope } = source_info;
961
962 self.visit_span($(& $mutability)? *span);
963 self.visit_source_scope($(& $mutability)? *scope);
964 }
965
966 fn super_user_type_projection(&mut self, _ty: & $($mutability)? UserTypeProjection) {}
967
968 fn super_user_type_annotation(
969 &mut self,
970 _index: UserTypeAnnotationIndex,
971 ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
972 ) {
973 self.visit_span($(& $mutability)? ty.span);
974 self.visit_ty($(& $mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
975 }
976
977 fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {}
978
979 fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) {}
980
981 fn super_args(&mut self, _args: & $($mutability)? GenericArgsRef<'tcx>) {}
982
983 fn visit_location(
986 &mut self,
987 body: &$($mutability)? Body<'tcx>,
988 location: Location
989 ) {
990 let basic_block =
991 & $($mutability)? basic_blocks!(body, $($mutability, true)?)[location.block];
992 if basic_block.statements.len() == location.statement_index {
993 if let Some(ref $($mutability)? terminator) = basic_block.terminator {
994 self.visit_terminator(terminator, location)
995 }
996 } else {
997 let statement = & $($mutability)?
998 basic_block.statements[location.statement_index];
999 self.visit_statement(statement, location)
1000 }
1001 }
1002 }
1003 }
1004}
1005
1006macro_rules! basic_blocks {
1007 ($body:ident, mut, true) => {
1008 $body.basic_blocks.as_mut()
1009 };
1010 ($body:ident, mut, false) => {
1011 $body.basic_blocks.as_mut_preserves_cfg()
1012 };
1013 ($body:ident,) => {
1014 $body.basic_blocks
1015 };
1016}
1017
1018macro_rules! basic_blocks_iter {
1019 ($body:ident, mut, $invalidate:tt) => {
1020 basic_blocks!($body, mut, $invalidate).iter_enumerated_mut()
1021 };
1022 ($body:ident,) => {
1023 basic_blocks!($body,).iter_enumerated()
1024 };
1025}
1026
1027macro_rules! extra_body_methods {
1028 (mut) => {
1029 fn visit_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
1030 self.super_body_preserves_cfg(body);
1031 }
1032
1033 fn super_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
1034 super_body!(self, body, mut, false);
1035 }
1036 };
1037 () => {};
1038}
1039
1040macro_rules! super_body {
1041 ($self:ident, $body:ident, $($mutability:ident, $invalidate:tt)?) => {
1042 let span = $body.span;
1043 if let Some(coroutine) = &$($mutability)? $body.coroutine {
1044 if let Some(yield_ty) = $(& $mutability)? coroutine.yield_ty {
1045 $self.visit_ty(
1046 yield_ty,
1047 TyContext::YieldTy(SourceInfo::outermost(span))
1048 );
1049 }
1050 if let Some(resume_ty) = $(& $mutability)? coroutine.resume_ty {
1051 $self.visit_ty(
1052 resume_ty,
1053 TyContext::ResumeTy(SourceInfo::outermost(span))
1054 );
1055 }
1056 }
1057
1058 for (bb, data) in basic_blocks_iter!($body, $($mutability, $invalidate)?) {
1059 $self.visit_basic_block_data(bb, data);
1060 }
1061
1062 for scope in &$($mutability)? $body.source_scopes {
1063 $self.visit_source_scope_data(scope);
1064 }
1065
1066 $self.visit_ty(
1067 $(& $mutability)? $body.return_ty(),
1068 TyContext::ReturnTy(SourceInfo::outermost($body.span))
1069 );
1070
1071 for local in $body.local_decls.indices() {
1072 $self.visit_local_decl(local, & $($mutability)? $body.local_decls[local]);
1073 }
1074
1075 #[allow(unused_macro_rules)]
1076 macro_rules! type_annotations {
1077 (mut) => ($body.user_type_annotations.iter_enumerated_mut());
1078 () => ($body.user_type_annotations.iter_enumerated());
1079 }
1080
1081 for (index, annotation) in type_annotations!($($mutability)?) {
1082 $self.visit_user_type_annotation(
1083 index, annotation
1084 );
1085 }
1086
1087 for var_debug_info in &$($mutability)? $body.var_debug_info {
1088 $self.visit_var_debug_info(var_debug_info);
1089 }
1090
1091 $self.visit_span($(& $mutability)? $body.span);
1092
1093 if let Some(required_consts) = &$($mutability)? $body.required_consts {
1094 for const_ in required_consts {
1095 let location = Location::START;
1096 $self.visit_const_operand(const_, location);
1097 }
1098 }
1099 }
1100}
1101
1102macro_rules! visit_place_fns {
1103 (mut) => {
1104 fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
1105
1106 fn super_place(
1107 &mut self,
1108 place: &mut Place<'tcx>,
1109 context: PlaceContext,
1110 location: Location,
1111 ) {
1112 self.visit_local(&mut place.local, context, location);
1113
1114 if let Some(new_projection) = self.process_projection(&place.projection, location) {
1115 place.projection = self.tcx().mk_place_elems(&new_projection);
1116 }
1117 }
1118
1119 fn process_projection<'a>(
1120 &mut self,
1121 projection: &'a [PlaceElem<'tcx>],
1122 location: Location,
1123 ) -> Option<Vec<PlaceElem<'tcx>>> {
1124 let mut projection = Cow::Borrowed(projection);
1125
1126 for i in 0..projection.len() {
1127 if let Some(&elem) = projection.get(i) {
1128 if let Some(elem) = self.process_projection_elem(elem, location) {
1129 let vec = projection.to_mut();
1132 vec[i] = elem;
1133 }
1134 }
1135 }
1136
1137 match projection {
1138 Cow::Borrowed(_) => None,
1139 Cow::Owned(vec) => Some(vec),
1140 }
1141 }
1142
1143 fn process_projection_elem(
1144 &mut self,
1145 elem: PlaceElem<'tcx>,
1146 location: Location,
1147 ) -> Option<PlaceElem<'tcx>> {
1148 match elem {
1149 PlaceElem::Index(local) => {
1150 let mut new_local = local;
1151 self.visit_local(
1152 &mut new_local,
1153 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
1154 location,
1155 );
1156
1157 if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
1158 }
1159 PlaceElem::Field(field, ty) => {
1160 let mut new_ty = ty;
1161 self.visit_ty(&mut new_ty, TyContext::Location(location));
1162 if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
1163 }
1164 PlaceElem::OpaqueCast(ty) => {
1165 let mut new_ty = ty;
1166 self.visit_ty(&mut new_ty, TyContext::Location(location));
1167 if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None }
1168 }
1169 PlaceElem::Subtype(ty) => {
1170 let mut new_ty = ty;
1171 self.visit_ty(&mut new_ty, TyContext::Location(location));
1172 if ty != new_ty { Some(PlaceElem::Subtype(new_ty)) } else { None }
1173 }
1174 PlaceElem::UnwrapUnsafeBinder(ty) => {
1175 let mut new_ty = ty;
1176 self.visit_ty(&mut new_ty, TyContext::Location(location));
1177 if ty != new_ty { Some(PlaceElem::UnwrapUnsafeBinder(new_ty)) } else { None }
1178 }
1179 PlaceElem::Deref
1180 | PlaceElem::ConstantIndex { .. }
1181 | PlaceElem::Subslice { .. }
1182 | PlaceElem::Downcast(..) => None,
1183 }
1184 }
1185 };
1186
1187 () => {
1188 fn visit_projection(
1189 &mut self,
1190 place_ref: PlaceRef<'tcx>,
1191 context: PlaceContext,
1192 location: Location,
1193 ) {
1194 self.super_projection(place_ref, context, location);
1195 }
1196
1197 fn visit_projection_elem(
1198 &mut self,
1199 place_ref: PlaceRef<'tcx>,
1200 elem: PlaceElem<'tcx>,
1201 context: PlaceContext,
1202 location: Location,
1203 ) {
1204 self.super_projection_elem(place_ref, elem, context, location);
1205 }
1206
1207 fn super_place(
1208 &mut self,
1209 place: &Place<'tcx>,
1210 mut context: PlaceContext,
1211 location: Location,
1212 ) {
1213 if !place.projection.is_empty() && context.is_use() {
1214 context = if context.is_mutating_use() {
1216 PlaceContext::MutatingUse(MutatingUseContext::Projection)
1217 } else {
1218 PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
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 if context.is_use() {
1256 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy)
1258 } else {
1259 context
1260 },
1261 location,
1262 );
1263 }
1264 ProjectionElem::Deref
1265 | ProjectionElem::Subslice { from: _, to: _, from_end: _ }
1266 | ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ }
1267 | ProjectionElem::Downcast(_, _) => {}
1268 }
1269 }
1270 };
1271}
1272
1273make_mir_visitor!(Visitor,);
1274make_mir_visitor!(MutVisitor, mut);
1275
1276#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1279pub enum TyContext {
1280 LocalDecl {
1281 local: Local,
1283
1284 source_info: SourceInfo,
1286 },
1287
1288 UserTy(Span),
1290
1291 ReturnTy(SourceInfo),
1293
1294 YieldTy(SourceInfo),
1295
1296 ResumeTy(SourceInfo),
1297
1298 Location(Location),
1300}
1301
1302#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1303pub enum NonMutatingUseContext {
1304 Inspect,
1306 Copy,
1308 Move,
1310 SharedBorrow,
1312 FakeBorrow,
1316 RawBorrow,
1318 PlaceMention,
1323 Projection,
1330}
1331
1332#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1333pub enum MutatingUseContext {
1334 Store,
1336 SetDiscriminant,
1338 Deinit,
1340 AsmOutput,
1342 Call,
1344 Yield,
1346 Drop,
1348 Borrow,
1350 RawBorrow,
1352 Projection,
1359 Retag,
1361}
1362
1363#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1364pub enum NonUseContext {
1365 StorageLive,
1367 StorageDead,
1369 AscribeUserTy(ty::Variance),
1371 VarDebugInfo,
1373 BackwardIncompatibleDropHint,
1375}
1376
1377#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1378pub enum PlaceContext {
1379 NonMutatingUse(NonMutatingUseContext),
1380 MutatingUse(MutatingUseContext),
1381 NonUse(NonUseContext),
1382}
1383
1384impl PlaceContext {
1385 #[inline]
1387 pub fn is_drop(self) -> bool {
1388 matches!(self, PlaceContext::MutatingUse(MutatingUseContext::Drop))
1389 }
1390
1391 pub fn is_borrow(self) -> bool {
1394 matches!(
1395 self,
1396 PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
1397 | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
1398 )
1399 }
1400
1401 pub fn is_address_of(self) -> bool {
1403 matches!(
1404 self,
1405 PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow)
1406 | PlaceContext::MutatingUse(MutatingUseContext::RawBorrow)
1407 )
1408 }
1409
1410 #[inline]
1412 pub fn may_observe_address(self) -> bool {
1413 matches!(
1414 self,
1415 PlaceContext::NonMutatingUse(
1416 NonMutatingUseContext::SharedBorrow
1417 | NonMutatingUseContext::RawBorrow
1418 | NonMutatingUseContext::FakeBorrow
1419 ) | PlaceContext::MutatingUse(
1420 MutatingUseContext::Drop
1421 | MutatingUseContext::Borrow
1422 | MutatingUseContext::RawBorrow
1423 | MutatingUseContext::AsmOutput
1424 )
1425 )
1426 }
1427
1428 #[inline]
1430 pub fn is_storage_marker(self) -> bool {
1431 matches!(
1432 self,
1433 PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead)
1434 )
1435 }
1436
1437 #[inline]
1439 pub fn is_mutating_use(self) -> bool {
1440 matches!(self, PlaceContext::MutatingUse(..))
1441 }
1442
1443 #[inline]
1445 pub fn is_use(self) -> bool {
1446 !matches!(self, PlaceContext::NonUse(..))
1447 }
1448
1449 pub fn is_place_assignment(self) -> bool {
1451 matches!(
1452 self,
1453 PlaceContext::MutatingUse(
1454 MutatingUseContext::Store
1455 | MutatingUseContext::Call
1456 | MutatingUseContext::AsmOutput,
1457 )
1458 )
1459 }
1460
1461 pub fn ambient_variance(self) -> ty::Variance {
1463 use NonMutatingUseContext::*;
1464 use NonUseContext::*;
1465 match self {
1466 PlaceContext::MutatingUse(_) => ty::Invariant,
1467 PlaceContext::NonUse(
1468 StorageDead | StorageLive | VarDebugInfo | BackwardIncompatibleDropHint,
1469 ) => ty::Invariant,
1470 PlaceContext::NonMutatingUse(
1471 Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | RawBorrow
1472 | Projection,
1473 ) => ty::Covariant,
1474 PlaceContext::NonUse(AscribeUserTy(variance)) => variance,
1475 }
1476 }
1477}
1478
1479pub struct VisitPlacesWith<F>(pub F);
1481
1482impl<'tcx, F> Visitor<'tcx> for VisitPlacesWith<F>
1483where
1484 F: FnMut(Place<'tcx>, PlaceContext),
1485{
1486 fn visit_local(&mut self, local: Local, ctxt: PlaceContext, _: Location) {
1487 (self.0)(local.into(), ctxt);
1488 }
1489
1490 fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, location: Location) {
1491 (self.0)(*place, ctxt);
1492 self.visit_projection(place.as_ref(), ctxt, location);
1493 }
1494}