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