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::Len(path) => {
721 self.visit_place(
722 path,
723 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
724 location
725 );
726 }
727
728 Rvalue::Cast(_cast_kind, operand, ty) => {
729 self.visit_operand(operand, location);
730 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
731 }
732
733 Rvalue::BinaryOp(_bin_op, box(lhs, rhs)) => {
734 self.visit_operand(lhs, location);
735 self.visit_operand(rhs, location);
736 }
737
738 Rvalue::UnaryOp(_un_op, op) => {
739 self.visit_operand(op, location);
740 }
741
742 Rvalue::Discriminant(place) => {
743 self.visit_place(
744 place,
745 PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
746 location
747 );
748 }
749
750 Rvalue::NullaryOp(_op, ty) => {
751 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
752 }
753
754 Rvalue::Aggregate(kind, operands) => {
755 let kind = &$($mutability)? **kind;
756 match kind {
757 AggregateKind::Array(ty) => {
758 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
759 }
760 AggregateKind::Tuple => {}
761 AggregateKind::Adt(
762 _adt_def,
763 _variant_index,
764 args,
765 _user_args,
766 _active_field_index
767 ) => {
768 self.visit_args(args, location);
769 }
770 AggregateKind::Closure(_, closure_args) => {
771 self.visit_args(closure_args, location);
772 }
773 AggregateKind::Coroutine(_, coroutine_args) => {
774 self.visit_args(coroutine_args, location);
775 }
776 AggregateKind::CoroutineClosure(_, coroutine_closure_args) => {
777 self.visit_args(coroutine_closure_args, location);
778 }
779 AggregateKind::RawPtr(ty, _) => {
780 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
781 }
782 }
783
784 for operand in operands {
785 self.visit_operand(operand, location);
786 }
787 }
788
789 Rvalue::ShallowInitBox(operand, ty) => {
790 self.visit_operand(operand, location);
791 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
792 }
793
794 Rvalue::WrapUnsafeBinder(op, ty) => {
795 self.visit_operand(op, location);
796 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
797 }
798 }
799 }
800
801 fn super_operand(
802 &mut self,
803 operand: & $($mutability)? Operand<'tcx>,
804 location: Location
805 ) {
806 match operand {
807 Operand::Copy(place) => {
808 self.visit_place(
809 place,
810 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
811 location
812 );
813 }
814 Operand::Move(place) => {
815 self.visit_place(
816 place,
817 PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
818 location
819 );
820 }
821 Operand::Constant(constant) => {
822 self.visit_const_operand(constant, location);
823 }
824 }
825 }
826
827 fn super_ascribe_user_ty(
828 &mut self,
829 place: & $($mutability)? Place<'tcx>,
830 variance: $(& $mutability)? ty::Variance,
831 user_ty: & $($mutability)? UserTypeProjection,
832 location: Location)
833 {
834 self.visit_place(
835 place,
836 PlaceContext::NonUse(
837 NonUseContext::AscribeUserTy($(* &$mutability *)? variance)
838 ),
839 location
840 );
841 self.visit_user_type_projection(user_ty);
842 }
843
844 fn super_coverage(
845 &mut self,
846 _kind: & $($mutability)? coverage::CoverageKind,
847 _location: Location
848 ) {
849 }
850
851 fn super_retag(
852 &mut self,
853 _kind: $(& $mutability)? RetagKind,
854 place: & $($mutability)? Place<'tcx>,
855 location: Location
856 ) {
857 self.visit_place(
858 place,
859 PlaceContext::MutatingUse(MutatingUseContext::Retag),
860 location,
861 );
862 }
863
864 fn super_local_decl(
865 &mut self,
866 local: Local,
867 local_decl: & $($mutability)? LocalDecl<'tcx>
868 ) {
869 let LocalDecl {
870 mutability: _,
871 ty,
872 user_ty,
873 source_info,
874 local_info: _,
875 } = local_decl;
876
877 self.visit_source_info(source_info);
878
879 self.visit_ty($(& $mutability)? *ty, TyContext::LocalDecl {
880 local,
881 source_info: *source_info,
882 });
883 if let Some(user_ty) = user_ty {
884 for user_ty in & $($mutability)? user_ty.contents {
885 self.visit_user_type_projection(user_ty);
886 }
887 }
888 }
889
890 fn super_local(
891 &mut self,
892 _local: $(& $mutability)? Local,
893 _context: PlaceContext,
894 _location: Location,
895 ) {
896 }
897
898 fn super_var_debug_info(
899 &mut self,
900 var_debug_info: & $($mutability)? VarDebugInfo<'tcx>
901 ) {
902 let VarDebugInfo {
903 name: _,
904 source_info,
905 composite,
906 value,
907 argument_index: _,
908 } = var_debug_info;
909
910 self.visit_source_info(source_info);
911 let location = Location::START;
912 if let Some(box VarDebugInfoFragment {
913 ty,
914 projection
915 }) = composite {
916 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
917 for elem in projection {
918 let ProjectionElem::Field(_, ty) = elem else { bug!() };
919 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
920 }
921 }
922 match value {
923 VarDebugInfoContents::Const(c) => self.visit_const_operand(c, location),
924 VarDebugInfoContents::Place(place) =>
925 self.visit_place(
926 place,
927 PlaceContext::NonUse(NonUseContext::VarDebugInfo),
928 location
929 ),
930 }
931 }
932
933 fn super_source_scope(&mut self, _scope: $(& $mutability)? SourceScope) {}
934
935 fn super_const_operand(
936 &mut self,
937 constant: & $($mutability)? ConstOperand<'tcx>,
938 location: Location
939 ) {
940 let ConstOperand {
941 span,
942 user_ty: _, const_,
944 } = constant;
945
946 self.visit_span($(& $mutability)? *span);
947 match const_ {
948 Const::Ty(_, ct) => self.visit_ty_const($(&$mutability)? *ct, location),
949 Const::Val(_, ty) => {
950 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
951 }
952 Const::Unevaluated(_, ty) => {
953 self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
954 }
955 }
956 }
957
958 fn super_ty_const(
959 &mut self,
960 _ct: $(& $mutability)? ty::Const<'tcx>,
961 _location: Location,
962 ) {
963 }
964
965 fn super_span(&mut self, _span: $(& $mutability)? Span) {}
966
967 fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) {
968 let SourceInfo { span, scope } = source_info;
969
970 self.visit_span($(& $mutability)? *span);
971 self.visit_source_scope($(& $mutability)? *scope);
972 }
973
974 fn super_user_type_projection(&mut self, _ty: & $($mutability)? UserTypeProjection) {}
975
976 fn super_user_type_annotation(
977 &mut self,
978 _index: UserTypeAnnotationIndex,
979 ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
980 ) {
981 self.visit_span($(& $mutability)? ty.span);
982 self.visit_ty($(& $mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
983 }
984
985 fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {}
986
987 fn super_region(&mut self, _region: $(& $mutability)? ty::Region<'tcx>) {}
988
989 fn super_args(&mut self, _args: & $($mutability)? GenericArgsRef<'tcx>) {}
990
991 fn visit_location(
994 &mut self,
995 body: &$($mutability)? Body<'tcx>,
996 location: Location
997 ) {
998 let basic_block =
999 & $($mutability)? basic_blocks!(body, $($mutability, true)?)[location.block];
1000 if basic_block.statements.len() == location.statement_index {
1001 if let Some(ref $($mutability)? terminator) = basic_block.terminator {
1002 self.visit_terminator(terminator, location)
1003 }
1004 } else {
1005 let statement = & $($mutability)?
1006 basic_block.statements[location.statement_index];
1007 self.visit_statement(statement, location)
1008 }
1009 }
1010 }
1011 }
1012}
1013
1014macro_rules! basic_blocks {
1015 ($body:ident, mut, true) => {
1016 $body.basic_blocks.as_mut()
1017 };
1018 ($body:ident, mut, false) => {
1019 $body.basic_blocks.as_mut_preserves_cfg()
1020 };
1021 ($body:ident,) => {
1022 $body.basic_blocks
1023 };
1024}
1025
1026macro_rules! basic_blocks_iter {
1027 ($body:ident, mut, $invalidate:tt) => {
1028 basic_blocks!($body, mut, $invalidate).iter_enumerated_mut()
1029 };
1030 ($body:ident,) => {
1031 basic_blocks!($body,).iter_enumerated()
1032 };
1033}
1034
1035macro_rules! extra_body_methods {
1036 (mut) => {
1037 fn visit_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
1038 self.super_body_preserves_cfg(body);
1039 }
1040
1041 fn super_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {
1042 super_body!(self, body, mut, false);
1043 }
1044 };
1045 () => {};
1046}
1047
1048macro_rules! super_body {
1049 ($self:ident, $body:ident, $($mutability:ident, $invalidate:tt)?) => {
1050 let span = $body.span;
1051 if let Some(coroutine) = &$($mutability)? $body.coroutine {
1052 if let Some(yield_ty) = $(& $mutability)? coroutine.yield_ty {
1053 $self.visit_ty(
1054 yield_ty,
1055 TyContext::YieldTy(SourceInfo::outermost(span))
1056 );
1057 }
1058 if let Some(resume_ty) = $(& $mutability)? coroutine.resume_ty {
1059 $self.visit_ty(
1060 resume_ty,
1061 TyContext::ResumeTy(SourceInfo::outermost(span))
1062 );
1063 }
1064 }
1065
1066 for (bb, data) in basic_blocks_iter!($body, $($mutability, $invalidate)?) {
1067 $self.visit_basic_block_data(bb, data);
1068 }
1069
1070 for scope in &$($mutability)? $body.source_scopes {
1071 $self.visit_source_scope_data(scope);
1072 }
1073
1074 $self.visit_ty(
1075 $(& $mutability)? $body.return_ty(),
1076 TyContext::ReturnTy(SourceInfo::outermost($body.span))
1077 );
1078
1079 for local in $body.local_decls.indices() {
1080 $self.visit_local_decl(local, & $($mutability)? $body.local_decls[local]);
1081 }
1082
1083 #[allow(unused_macro_rules)]
1084 macro_rules! type_annotations {
1085 (mut) => ($body.user_type_annotations.iter_enumerated_mut());
1086 () => ($body.user_type_annotations.iter_enumerated());
1087 }
1088
1089 for (index, annotation) in type_annotations!($($mutability)?) {
1090 $self.visit_user_type_annotation(
1091 index, annotation
1092 );
1093 }
1094
1095 for var_debug_info in &$($mutability)? $body.var_debug_info {
1096 $self.visit_var_debug_info(var_debug_info);
1097 }
1098
1099 $self.visit_span($(& $mutability)? $body.span);
1100
1101 if let Some(required_consts) = &$($mutability)? $body.required_consts {
1102 for const_ in required_consts {
1103 let location = Location::START;
1104 $self.visit_const_operand(const_, location);
1105 }
1106 }
1107 }
1108}
1109
1110macro_rules! visit_place_fns {
1111 (mut) => {
1112 fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
1113
1114 fn super_place(
1115 &mut self,
1116 place: &mut Place<'tcx>,
1117 context: PlaceContext,
1118 location: Location,
1119 ) {
1120 self.visit_local(&mut place.local, context, location);
1121
1122 if let Some(new_projection) = self.process_projection(&place.projection, location) {
1123 place.projection = self.tcx().mk_place_elems(&new_projection);
1124 }
1125 }
1126
1127 fn process_projection<'a>(
1128 &mut self,
1129 projection: &'a [PlaceElem<'tcx>],
1130 location: Location,
1131 ) -> Option<Vec<PlaceElem<'tcx>>> {
1132 let mut projection = Cow::Borrowed(projection);
1133
1134 for i in 0..projection.len() {
1135 if let Some(&elem) = projection.get(i) {
1136 if let Some(elem) = self.process_projection_elem(elem, location) {
1137 let vec = projection.to_mut();
1140 vec[i] = elem;
1141 }
1142 }
1143 }
1144
1145 match projection {
1146 Cow::Borrowed(_) => None,
1147 Cow::Owned(vec) => Some(vec),
1148 }
1149 }
1150
1151 fn process_projection_elem(
1152 &mut self,
1153 elem: PlaceElem<'tcx>,
1154 location: Location,
1155 ) -> Option<PlaceElem<'tcx>> {
1156 match elem {
1157 PlaceElem::Index(local) => {
1158 let mut new_local = local;
1159 self.visit_local(
1160 &mut new_local,
1161 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
1162 location,
1163 );
1164
1165 if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
1166 }
1167 PlaceElem::Field(field, ty) => {
1168 let mut new_ty = ty;
1169 self.visit_ty(&mut new_ty, TyContext::Location(location));
1170 if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
1171 }
1172 PlaceElem::OpaqueCast(ty) => {
1173 let mut new_ty = ty;
1174 self.visit_ty(&mut new_ty, TyContext::Location(location));
1175 if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None }
1176 }
1177 PlaceElem::Subtype(ty) => {
1178 let mut new_ty = ty;
1179 self.visit_ty(&mut new_ty, TyContext::Location(location));
1180 if ty != new_ty { Some(PlaceElem::Subtype(new_ty)) } else { None }
1181 }
1182 PlaceElem::UnwrapUnsafeBinder(ty) => {
1183 let mut new_ty = ty;
1184 self.visit_ty(&mut new_ty, TyContext::Location(location));
1185 if ty != new_ty { Some(PlaceElem::UnwrapUnsafeBinder(new_ty)) } else { None }
1186 }
1187 PlaceElem::Deref
1188 | PlaceElem::ConstantIndex { .. }
1189 | PlaceElem::Subslice { .. }
1190 | PlaceElem::Downcast(..) => None,
1191 }
1192 }
1193 };
1194
1195 () => {
1196 fn visit_projection(
1197 &mut self,
1198 place_ref: PlaceRef<'tcx>,
1199 context: PlaceContext,
1200 location: Location,
1201 ) {
1202 self.super_projection(place_ref, context, location);
1203 }
1204
1205 fn visit_projection_elem(
1206 &mut self,
1207 place_ref: PlaceRef<'tcx>,
1208 elem: PlaceElem<'tcx>,
1209 context: PlaceContext,
1210 location: Location,
1211 ) {
1212 self.super_projection_elem(place_ref, elem, context, location);
1213 }
1214
1215 fn super_place(
1216 &mut self,
1217 place: &Place<'tcx>,
1218 mut context: PlaceContext,
1219 location: Location,
1220 ) {
1221 if !place.projection.is_empty() && context.is_use() {
1222 context = if context.is_mutating_use() {
1224 PlaceContext::MutatingUse(MutatingUseContext::Projection)
1225 } else {
1226 PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
1227 };
1228 }
1229
1230 self.visit_local(place.local, context, location);
1231
1232 self.visit_projection(place.as_ref(), context, location);
1233 }
1234
1235 fn super_projection(
1236 &mut self,
1237 place_ref: PlaceRef<'tcx>,
1238 context: PlaceContext,
1239 location: Location,
1240 ) {
1241 for (base, elem) in place_ref.iter_projections().rev() {
1242 self.visit_projection_elem(base, elem, context, location);
1243 }
1244 }
1245
1246 fn super_projection_elem(
1247 &mut self,
1248 _place_ref: PlaceRef<'tcx>,
1249 elem: PlaceElem<'tcx>,
1250 context: PlaceContext,
1251 location: Location,
1252 ) {
1253 match elem {
1254 ProjectionElem::OpaqueCast(ty)
1255 | ProjectionElem::Subtype(ty)
1256 | ProjectionElem::Field(_, ty)
1257 | ProjectionElem::UnwrapUnsafeBinder(ty) => {
1258 self.visit_ty(ty, TyContext::Location(location));
1259 }
1260 ProjectionElem::Index(local) => {
1261 self.visit_local(
1262 local,
1263 if context.is_use() {
1264 PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy)
1266 } else {
1267 context
1268 },
1269 location,
1270 );
1271 }
1272 ProjectionElem::Deref
1273 | ProjectionElem::Subslice { from: _, to: _, from_end: _ }
1274 | ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ }
1275 | ProjectionElem::Downcast(_, _) => {}
1276 }
1277 }
1278 };
1279}
1280
1281make_mir_visitor!(Visitor,);
1282make_mir_visitor!(MutVisitor, mut);
1283
1284#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1287pub enum TyContext {
1288 LocalDecl {
1289 local: Local,
1291
1292 source_info: SourceInfo,
1294 },
1295
1296 UserTy(Span),
1298
1299 ReturnTy(SourceInfo),
1301
1302 YieldTy(SourceInfo),
1303
1304 ResumeTy(SourceInfo),
1305
1306 Location(Location),
1308}
1309
1310#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1311pub enum NonMutatingUseContext {
1312 Inspect,
1314 Copy,
1316 Move,
1318 SharedBorrow,
1320 FakeBorrow,
1324 RawBorrow,
1326 PlaceMention,
1331 Projection,
1338}
1339
1340#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1341pub enum MutatingUseContext {
1342 Store,
1344 SetDiscriminant,
1346 Deinit,
1348 AsmOutput,
1350 Call,
1352 Yield,
1354 Drop,
1356 Borrow,
1358 RawBorrow,
1360 Projection,
1367 Retag,
1369}
1370
1371#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1372pub enum NonUseContext {
1373 StorageLive,
1375 StorageDead,
1377 AscribeUserTy(ty::Variance),
1379 VarDebugInfo,
1381 BackwardIncompatibleDropHint,
1383}
1384
1385#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1386pub enum PlaceContext {
1387 NonMutatingUse(NonMutatingUseContext),
1388 MutatingUse(MutatingUseContext),
1389 NonUse(NonUseContext),
1390}
1391
1392impl PlaceContext {
1393 #[inline]
1395 pub fn is_drop(self) -> bool {
1396 matches!(self, PlaceContext::MutatingUse(MutatingUseContext::Drop))
1397 }
1398
1399 pub fn is_borrow(self) -> bool {
1402 matches!(
1403 self,
1404 PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
1405 | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
1406 )
1407 }
1408
1409 pub fn is_address_of(self) -> bool {
1411 matches!(
1412 self,
1413 PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow)
1414 | PlaceContext::MutatingUse(MutatingUseContext::RawBorrow)
1415 )
1416 }
1417
1418 #[inline]
1420 pub fn is_storage_marker(self) -> bool {
1421 matches!(
1422 self,
1423 PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead)
1424 )
1425 }
1426
1427 #[inline]
1429 pub fn is_mutating_use(self) -> bool {
1430 matches!(self, PlaceContext::MutatingUse(..))
1431 }
1432
1433 #[inline]
1435 pub fn is_use(self) -> bool {
1436 !matches!(self, PlaceContext::NonUse(..))
1437 }
1438
1439 pub fn is_place_assignment(self) -> bool {
1441 matches!(
1442 self,
1443 PlaceContext::MutatingUse(
1444 MutatingUseContext::Store
1445 | MutatingUseContext::Call
1446 | MutatingUseContext::AsmOutput,
1447 )
1448 )
1449 }
1450
1451 pub fn ambient_variance(self) -> ty::Variance {
1453 use NonMutatingUseContext::*;
1454 use NonUseContext::*;
1455 match self {
1456 PlaceContext::MutatingUse(_) => ty::Invariant,
1457 PlaceContext::NonUse(
1458 StorageDead | StorageLive | VarDebugInfo | BackwardIncompatibleDropHint,
1459 ) => ty::Invariant,
1460 PlaceContext::NonMutatingUse(
1461 Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | RawBorrow
1462 | Projection,
1463 ) => ty::Covariant,
1464 PlaceContext::NonUse(AscribeUserTy(variance)) => variance,
1465 }
1466 }
1467}