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