1use rustc_abi::VariantIdx;
2use rustc_middle::{
3 mir::{
4 visit::{TyContext, Visitor},
5 BasicBlock, BasicBlockData, Body, Local, LocalDecl, Operand, TerminatorKind,
6 },
7 ty::{
8 self, EarlyBinder, GenericArgKind, InstanceKind::Item, Ty, TyCtxt, TyKind,
9 TypeSuperVisitable, TypeVisitable, TypeVisitor,
10 },
11};
12use rustc_span::def_id::DefId;
13use std::{collections::HashMap, ops::ControlFlow};
14
15use super::*;
16use crate::rap_debug;
17
18pub struct DefaultHeapAnalysis<'tcx> {
19 tcx: TyCtxt<'tcx>,
20 adt_heap: HAResult,
21 fn_set: HashSet<DefId>,
22 ty_map: HashMap<Ty<'tcx>, String>,
23 adt_recorder: HashSet<DefId>,
24}
25
26impl<'tcx> Analysis for DefaultHeapAnalysis<'tcx> {
27 fn name(&self) -> &'static str {
28 "Default heap analysis."
29 }
30 fn run(&mut self) {
31 self.start();
32 }
33 fn reset(&mut self) {
34 todo!();
35 }
36}
37
38impl<'tcx> HeapAnalysis for DefaultHeapAnalysis<'tcx> {
39 fn get_all_items(&mut self) -> HAResult {
40 self.adt_heap.clone()
41 }
42}
43
44#[inline(always)]
47pub(crate) fn copy_ty_context(tc: &TyContext) -> TyContext {
48 match tc {
49 TyContext::LocalDecl { local, source_info } => TyContext::LocalDecl {
50 local: local.clone(),
51 source_info: source_info.clone(),
52 },
53 _ => unreachable!(),
54 }
55}
56
57impl<'tcx> DefaultHeapAnalysis<'tcx> {
58 pub fn new(tcx: TyCtxt<'tcx>) -> Self {
59 Self {
60 tcx,
61 adt_heap: HashMap::default(),
62 fn_set: HashSet::new(),
63 ty_map: HashMap::new(),
64 adt_recorder: HashSet::new(),
65 }
66 }
67
68 pub fn ty_map(&self) -> &HashMap<Ty<'tcx>, String> {
69 &self.ty_map
70 }
71
72 pub fn ty_map_mut(&mut self) -> &mut HashMap<Ty<'tcx>, String> {
73 &mut self.ty_map
74 }
75
76 pub fn fn_set(&self) -> &HashSet<DefId> {
77 &self.fn_set
78 }
79
80 pub fn fn_set_mut(&mut self) -> &mut HashSet<DefId> {
81 &mut self.fn_set
82 }
83
84 pub fn adt_recorder(&self) -> &HashSet<DefId> {
85 &self.adt_recorder
86 }
87
88 pub fn adt_recorder_mut(&mut self) -> &mut HashSet<DefId> {
89 &mut self.adt_recorder
90 }
91
92 pub fn adt_heap(&self) -> &HAResult {
93 &self.adt_heap
94 }
95
96 pub fn adt_heap_mut(&mut self) -> &mut HAResult {
97 &mut self.adt_heap
98 }
99
100 pub fn format_heap_unit(unit: &(HeapInfo, Vec<bool>)) -> String {
101 let (heap, flags) = unit;
102 let vec_str = flags
103 .iter()
104 .map(|&b| if b { "1" } else { "0" })
105 .collect::<Vec<_>>()
106 .join(",");
107 format!("({}, [{}])", heap, vec_str)
108 }
109
110 pub fn output(&mut self) {
111 for elem in self.adt_heap() {
112 let name = format!("{:?}", EarlyBinder::skip_binder(self.tcx.type_of(*elem.0)));
113 let owning = elem
114 .1
115 .iter()
116 .map(Self::format_heap_unit)
117 .collect::<Vec<_>>()
118 .join(", ");
119 rap_info!("{} {}", name, owning);
120 }
121 }
122
123 pub fn start(&mut self) {
133 #[inline(always)]
134 fn start_channel<M>(mut method: M, v_did: &Vec<DefId>)
135 where
136 M: FnMut(DefId) -> (),
137 {
138 for did in v_did {
139 method(*did);
140 }
141 }
142
143 #[inline(always)]
144 fn show_heap(ref_type_analysis: &mut DefaultHeapAnalysis) {
145 for elem in ref_type_analysis.adt_heap() {
146 let name = format!(
147 "{:?}",
148 EarlyBinder::skip_binder(ref_type_analysis.tcx.type_of(*elem.0))
149 );
150 let owning = format!("{:?}", elem.1);
151 rap_debug!("ADT analysis: {} {}", name, owning);
152 }
153 }
154
155 let tcx = self.tcx;
158 let mir_keys = tcx.mir_keys(());
159
160 for each_mir in mir_keys {
161 let def_id = each_mir.to_def_id();
163 let body = tcx.instance_mir(Item(def_id));
164
165 if self.fn_set_mut().insert(def_id) {
167 self.visit_body(body);
168 } else {
169 continue;
170 }
171 }
172
173 let dids: Vec<DefId> = self.adt_recorder.iter().map(|did| *did).collect();
174
175 start_channel(|did| self.extract_raw_generic(did), &dids);
176 start_channel(|did| self.extract_raw_generic_prop(did), &dids);
177 start_channel(|did| self.extract_phantom_unit(did), &dids);
178 start_channel(|did| self.extract_heap_prop(did), &dids);
179
180 show_heap(self);
181 }
182
183 #[inline(always)]
200 fn extract_raw_generic(&mut self, did: DefId) {
201 let ty = EarlyBinder::skip_binder(self.tcx.type_of(did));
203 let (adt_def, substs) = match ty.kind() {
204 TyKind::Adt(adt_def, substs) => (adt_def, substs),
205 _ => unreachable!(),
206 };
207
208 let mut v_res = Vec::new();
209
210 for variant in adt_def.variants().iter() {
211 let mut raw_generic = IsolatedParam::new(substs.len());
212
213 for field in &variant.fields {
214 let field_ty = field.ty(self.tcx, substs);
215 let _ = field_ty.visit_with(&mut raw_generic);
216 }
217 v_res.push((HeapInfo::False, raw_generic.record_mut().clone()));
218 }
219
220 self.adt_heap_mut().insert(did, v_res);
221 }
222
223 #[inline(always)]
252 fn extract_raw_generic_prop(&mut self, did: DefId) {
253 let ty = EarlyBinder::skip_binder(self.tcx.type_of(did));
255 let (adt_def, substs) = match ty.kind() {
256 TyKind::Adt(adt_def, substs) => (adt_def, substs),
257 _ => unreachable!(),
258 };
259
260 let source_enum = adt_def.is_enum();
261
262 let mut v_res = self.adt_heap_mut().get_mut(&did).unwrap().clone();
263
264 for (variant_index, variant) in adt_def.variants().iter().enumerate() {
265 let res = v_res[variant_index as usize].clone();
266
267 let mut raw_generic_prop = IsolatedParamPropagation::new(
268 self.tcx,
269 res.1.clone(),
270 source_enum,
271 self.adt_heap(),
272 );
273
274 for field in &variant.fields {
275 let field_ty = field.ty(self.tcx, substs);
276 let _ = field_ty.visit_with(&mut raw_generic_prop);
277 }
278 v_res[variant_index as usize] =
279 (HeapInfo::False, raw_generic_prop.record_mut().clone());
280 }
281
282 self.adt_heap_mut().insert(did, v_res);
283 }
284
285 #[inline(always)]
288 fn extract_phantom_unit(&mut self, did: DefId) {
289 let ty = EarlyBinder::skip_binder(self.tcx.type_of(did));
291 let (adt_def, substs) = match ty.kind() {
292 TyKind::Adt(adt_def, substs) => (adt_def, substs),
293 _ => unreachable!(),
294 };
295
296 if adt_def.is_struct() {
303 let mut res = self.adt_heap_mut().get_mut(&did).unwrap()[0].clone();
304 for field in adt_def.all_fields() {
306 let field_ty = field.ty(self.tcx, substs);
307 match field_ty.kind() {
308 TyKind::Adt(field_adt_def, field_substs) => {
310 if field_adt_def.is_phantom_data() {
311 for generic_arg in *field_substs {
313 match generic_arg.kind() {
314 GenericArgKind::Type(g_ty) => {
315 let mut raw_generic_field_subst =
316 IsolatedParamFieldSubst::new();
317 let _ = g_ty.visit_with(&mut raw_generic_field_subst);
318 if raw_generic_field_subst.contains_param() {
319 {
320 let mut has_ptr = false;
323 for field in adt_def.all_fields() {
324 let field_ty = field.ty(self.tcx, substs);
325 let mut find_ptr = FindPtr::new(self.tcx);
326 let _ = field_ty.visit_with(&mut find_ptr);
327 if find_ptr.has_ptr() {
328 has_ptr = true;
329 break;
330 }
331 }
332 if has_ptr == false {
333 return;
334 }
335 }
336
337 res.0 = HeapInfo::True;
338 self.adt_heap_mut().insert(did, vec![res.clone()]);
339 return;
340 }
341 }
342 GenericArgKind::Lifetime(..) => {
343 return;
344 }
345 GenericArgKind::Const(..) => {
346 return;
347 }
348 }
349 }
350 }
351 }
352 _ => continue,
353 }
354 }
355 }
356 }
357
358 #[inline(always)]
359 fn extract_heap_prop(&mut self, did: DefId) {
360 let ty = EarlyBinder::skip_binder(self.tcx.type_of(did));
362 let (adt_def, substs) = match ty.kind() {
363 TyKind::Adt(adt_def, substs) => (adt_def, substs),
364 _ => unreachable!(),
365 };
366
367 let mut v_res = self.adt_heap_mut().get_mut(&did).unwrap().clone();
368
369 for (variant_index, variant) in adt_def.variants().iter().enumerate() {
370 let res = v_res[variant_index as usize].clone();
371
372 let mut heap_prop = HeapPropagation::new(self.tcx, res.0, self.adt_heap());
373
374 for field in &variant.fields {
375 let field_ty = field.ty(self.tcx, substs);
376 let _ = field_ty.visit_with(&mut heap_prop);
377 }
378 v_res[variant_index as usize].0 = heap_prop.heap();
379 }
380
381 self.adt_heap_mut().insert(did, v_res);
382 }
383}
384
385impl<'tcx> Visitor<'tcx> for DefaultHeapAnalysis<'tcx> {
386 fn visit_body(&mut self, body: &Body<'tcx>) {
387 for (local, local_decl) in body.local_decls.iter().enumerate() {
388 self.visit_local_decl(Local::from(local), local_decl);
389 }
390
391 for (block, data) in body.basic_blocks.iter().enumerate() {
392 self.visit_basic_block_data(BasicBlock::from(block), data);
393 }
394 }
395
396 fn visit_basic_block_data(&mut self, _block: BasicBlock, data: &BasicBlockData<'tcx>) {
397 let term = data.terminator();
398 match &term.kind {
399 TerminatorKind::Call { func, .. } => match func {
400 Operand::Constant(constant) => match constant.ty().kind() {
401 ty::FnDef(def_id, ..) => {
402 if self.tcx.is_mir_available(*def_id) && self.fn_set_mut().insert(*def_id) {
403 let body = self.tcx.instance_mir(Item(*def_id));
404 self.visit_body(body);
405 }
406 }
407 _ => (),
408 },
409 _ => (),
410 },
411 _ => (),
412 }
413 }
414
415 fn visit_ty(&mut self, ty: Ty<'tcx>, ty_context: TyContext) {
416 match ty.kind() {
417 TyKind::Adt(adtdef, substs) => {
418 if self.ty_map().get(&ty).is_some() {
419 return;
420 }
421 self.ty_map_mut().insert(ty, format!("{:?}", ty));
422 self.adt_recorder_mut().insert(adtdef.did());
423
424 for field in adtdef.all_fields() {
425 self.visit_ty(field.ty(self.tcx, substs), copy_ty_context(&ty_context))
426 }
427
428 for ty in substs.types() {
429 self.visit_ty(ty, copy_ty_context(&ty_context));
430 }
431 }
432 TyKind::Array(ty, ..) => {
433 self.visit_ty(*ty, ty_context);
434 }
435 TyKind::Slice(ty) => {
436 self.visit_ty(*ty, ty_context);
437 }
438 TyKind::RawPtr(ty, _) => {
439 self.visit_ty(*ty, ty_context);
440 }
441 TyKind::Ref(_, ty, ..) => {
442 self.visit_ty(*ty, ty_context);
443 }
444 TyKind::Tuple(tuple_fields) => {
445 for field in tuple_fields.iter() {
446 self.visit_ty(field, copy_ty_context(&ty_context));
447 }
448 }
449 _ => return,
450 }
451 }
452
453 fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
454 let ty_context = TyContext::LocalDecl {
455 local,
456 source_info: local_decl.source_info,
457 };
458 self.visit_ty(local_decl.ty, ty_context);
459 }
460}
461
462impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsolatedParam {
463 type Result = ControlFlow<()>;
464 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
465 match ty.kind() {
466 TyKind::Array(..) => ty.super_visit_with(self),
467 TyKind::Tuple(..) => ty.super_visit_with(self),
468 TyKind::Param(param_ty) => {
469 self.record_mut()[param_ty.index as usize] = true;
470 ControlFlow::Continue(())
471 }
472 _ => ControlFlow::Continue(()),
473 }
474 }
475}
476
477impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsolatedParamFieldSubst {
478 type Result = ControlFlow<()>;
479 #[inline(always)]
480 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
481 match ty.kind() {
482 TyKind::Array(..) => ty.super_visit_with(self),
483 TyKind::Tuple(..) => ty.super_visit_with(self),
484 TyKind::Adt(..) => ty.super_visit_with(self),
485 TyKind::Param(param_ty) => {
486 self.parameters_mut().insert(param_ty.index as usize);
487 ControlFlow::Continue(())
488 }
489 _ => ControlFlow::Continue(()),
490 }
491 }
492}
493
494impl<'tcx, 'a> TypeVisitor<TyCtxt<'tcx>> for IsolatedParamPropagation<'tcx, 'a> {
495 type Result = ControlFlow<()>;
500
501 #[inline(always)]
502 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
503 match ty.kind() {
504 TyKind::Adt(adtdef, substs) => {
505 if substs.len() == 0 {
506 return ControlFlow::Break(());
507 }
508
509 if !self.source_enum() && adtdef.is_enum() {
510 return ControlFlow::Break(());
511 }
512
513 if !self.unique_mut().insert(adtdef.did()) {
514 return ControlFlow::Continue(());
515 }
516
517 let mut map_raw_generic_field_subst = HashMap::new();
518 for (index, subst) in substs.iter().enumerate() {
519 match subst.kind() {
520 GenericArgKind::Lifetime(..) => continue,
521 GenericArgKind::Const(..) => continue,
522 GenericArgKind::Type(g_ty) => {
523 let mut raw_generic_field_subst = IsolatedParamFieldSubst::new();
524 let _ = g_ty.visit_with(&mut raw_generic_field_subst);
525 if !raw_generic_field_subst.contains_param() {
526 continue;
527 }
528 map_raw_generic_field_subst
529 .insert(index as usize, raw_generic_field_subst);
530 }
531 }
532 }
533 if map_raw_generic_field_subst.is_empty() {
534 return ControlFlow::Break(());
535 }
536
537 let get_ans = self.heap().get(&adtdef.did()).unwrap();
538 if get_ans.len() == 0 {
539 return ControlFlow::Break(());
540 }
541 let get_ans = get_ans[0].clone();
542
543 for (index, flag) in get_ans.1.iter().enumerate() {
544 if *flag && map_raw_generic_field_subst.contains_key(&index) {
545 for elem in map_raw_generic_field_subst
546 .get(&index)
547 .unwrap()
548 .parameters()
549 {
550 self.record[*elem] = true;
551 }
552 }
553 }
554
555 for field in adtdef.all_fields() {
556 let field_ty = field.ty(self.tcx, substs);
557 let _ = field_ty.visit_with(self);
558 }
559
560 self.unique_mut().remove(&adtdef.did());
561
562 ty.super_visit_with(self)
563 }
564 TyKind::Array(..) => ty.super_visit_with(self),
565 TyKind::Tuple(..) => ty.super_visit_with(self),
566 _ => ControlFlow::Continue(()),
567 }
568 }
569}
570
571impl<'tcx, 'a> TypeVisitor<TyCtxt<'tcx>> for HeapPropagation<'tcx, 'a> {
572 type Result = ControlFlow<()>;
577 #[inline(always)]
578 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
579 match ty.kind() {
580 TyKind::Adt(adtdef, substs) => {
581 if !self.unique_mut().insert(adtdef.did()) {
582 return ControlFlow::Continue(());
583 }
584
585 if adtdef.is_enum() {
586 return ControlFlow::Break(());
587 }
588
589 let get_ans = self.heap_res().get(&adtdef.did()).unwrap();
590 if get_ans.len() == 0 {
591 return ControlFlow::Break(());
592 }
593 let get_ans = get_ans[0].clone();
594
595 match get_ans.0 {
596 HeapInfo::True => {
597 self.heap = HeapInfo::True;
598 return ControlFlow::Break(());
599 }
600 _ => (),
601 };
602
603 for field in adtdef.all_fields() {
604 let field_ty = field.ty(self.tcx, substs);
605 let _ = field_ty.visit_with(self);
606 }
607
608 self.unique_mut().remove(&adtdef.did());
609
610 ty.super_visit_with(self)
611 }
612 TyKind::Array(..) => ty.super_visit_with(self),
613 TyKind::Tuple(..) => ty.super_visit_with(self),
614 _ => ControlFlow::Continue(()),
615 }
616 }
617}
618
619impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindPtr<'tcx> {
620 type Result = ControlFlow<()>;
621 #[inline(always)]
622 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
623 match ty.kind() {
624 TyKind::Adt(adtdef, substs) => {
625 if adtdef.is_struct() {
626 if !self.unique_mut().insert(adtdef.did()) {
627 return ControlFlow::Continue(());
628 }
629
630 for field in adtdef.all_fields() {
631 let field_ty = field.ty(self.tcx, substs);
632 let _ = field_ty.visit_with(self);
633 }
634 self.unique_mut().remove(&adtdef.did());
635 }
636 ControlFlow::Continue(())
637 }
638 TyKind::Tuple(..) => ty.super_visit_with(self),
639 TyKind::RawPtr(..) => {
640 self.set_ptr(true);
641 ControlFlow::Break(())
642 }
643 TyKind::Ref(..) => {
644 self.set_ptr(true);
645 ControlFlow::Break(())
646 }
647 _ => ControlFlow::Continue(()),
648 }
649 }
650}
651
652impl<'tcx, 'a> TypeVisitor<TyCtxt<'tcx>> for DefaultOwnership<'tcx, 'a> {
653 type Result = ControlFlow<()>;
658 #[inline(always)]
659 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
660 match ty.kind() {
661 TyKind::Adt(adtdef, substs) => {
662 if adtdef.is_enum() {
663 return ControlFlow::Break(());
664 }
665
666 if !self.unique_mut().insert(adtdef.did()) {
667 return ControlFlow::Continue(());
668 }
669
670 let get_ans = self.heap().get(&adtdef.did()).unwrap();
671
672 if get_ans.len() == 0 {
674 return ControlFlow::Break(());
675 }
676 let (unit_res, generic_list) = get_ans[0].clone();
677
678 match unit_res {
679 HeapInfo::True => {
680 self.set_res(HeapInfo::True);
681 return ControlFlow::Break(());
682 }
683 HeapInfo::False => {
684 for (index, each_generic) in generic_list.iter().enumerate() {
685 if *each_generic == false {
686 continue;
687 } else {
688 let subset_ty = substs[index].expect_ty();
689 self.unique_mut().remove(&adtdef.did());
690 let _ = subset_ty.visit_with(self);
691 }
692 }
693 }
694 _ => {
695 unreachable!();
696 }
697 }
698 ControlFlow::Continue(())
699 }
700 TyKind::Array(..) => ty.super_visit_with(self),
701 TyKind::Tuple(..) => ty.super_visit_with(self),
702 TyKind::Param(..) => {
703 self.set_param(true);
704 self.set_res(HeapInfo::True);
705 ControlFlow::Break(())
706 }
707 TyKind::RawPtr(..) => {
708 self.set_ptr(true);
709 ControlFlow::Continue(())
710 }
711 TyKind::Ref(..) => {
712 self.set_ptr(true);
713 ControlFlow::Continue(())
714 }
715 _ => ControlFlow::Continue(()),
716 }
717 }
718}
719
720#[derive(Debug, Clone, Hash, Eq, PartialEq, Default)]
721pub struct TyWithIndex<'tcx>(pub Option<(usize, &'tcx TyKind<'tcx>, Option<usize>, bool)>);
722
723impl<'tcx> TyWithIndex<'tcx> {
724 pub fn new(ty: Ty<'tcx>, vidx: Option<VariantIdx>) -> Self {
725 match &ty.kind() {
726 TyKind::Tuple(list) => TyWithIndex(Some((list.len(), &ty.kind(), None, true))),
727 TyKind::Adt(adtdef, ..) => {
728 if adtdef.is_enum() {
729 if vidx.is_none() {
730 return TyWithIndex(None);
731 }
732 let idx = vidx.unwrap();
733 let len = adtdef.variants()[idx].fields.len();
734 TyWithIndex(Some((len, &ty.kind(), Some(idx.index()), true)))
735 } else {
736 let len = adtdef.variants()[VariantIdx::from_usize(0)].fields.len();
737 TyWithIndex(Some((len, &ty.kind(), None, true)))
738 }
739 }
740 TyKind::Array(..) | TyKind::Param(..) | TyKind::RawPtr(..) | TyKind::Ref(..) => {
741 TyWithIndex(Some((1, &ty.kind(), None, true)))
742 }
743 TyKind::Bool
744 | TyKind::Char
745 | TyKind::Int(..)
746 | TyKind::Uint(..)
747 | TyKind::Float(..)
748 | TyKind::Str
749 | TyKind::Slice(..) => TyWithIndex(Some((1, &ty.kind(), None, false))),
750 _ => TyWithIndex(None),
751 }
752 }
753
754 pub fn get_priority(&self) -> usize {
756 if self.0.is_none() {
757 return 0;
758 }
759 match self.0.unwrap().0 {
760 0 => 1,
761 _ => match self.0.unwrap().3 {
762 true => 2,
763 false => 1,
764 },
765 }
766 }
767}
768
769#[derive(Copy, Clone, Debug)]
770pub struct Encoder;
771
772impl<'tcx> Encoder {
773 pub fn encode(
774 tcx: TyCtxt<'tcx>,
775 ty: Ty<'tcx>,
776 adt_heap: HAResult,
777 variant: Option<VariantIdx>,
778 ) -> OwnershipLayoutResult {
779 match ty.kind() {
780 TyKind::Array(..) => {
781 let mut res = OwnershipLayoutResult::new();
782 let mut default_heap = DefaultOwnership::new(tcx, &adt_heap);
783
784 let _ = ty.visit_with(&mut default_heap);
785 res.update_from_default_heap_visitor(&mut default_heap);
786
787 res
788 }
789 TyKind::Tuple(tuple_ty_list) => {
790 let mut res = OwnershipLayoutResult::new();
791
792 for tuple_ty in tuple_ty_list.iter() {
793 let mut default_heap = DefaultOwnership::new(tcx, &adt_heap);
794
795 let _ = tuple_ty.visit_with(&mut default_heap);
796 res.update_from_default_heap_visitor(&mut default_heap);
797 }
798
799 res
800 }
801 TyKind::Adt(adtdef, substs) => {
802 if adtdef.is_enum() && variant.is_none() {
804 return OwnershipLayoutResult::new();
805 }
806
807 let mut res = OwnershipLayoutResult::new();
808
809 if adtdef.is_struct() || adtdef.is_union() {
811 for field in adtdef.all_fields() {
812 let field_ty = field.ty(tcx, substs);
813
814 let mut default_heap = DefaultOwnership::new(tcx, &adt_heap);
815
816 let _ = field_ty.visit_with(&mut default_heap);
817 res.update_from_default_heap_visitor(&mut default_heap);
818 }
819 }
820 else if adtdef.is_enum() {
822 let vidx = variant.unwrap();
823
824 for field in &adtdef.variants()[vidx].fields {
825 let field_ty = field.ty(tcx, substs);
826
827 let mut default_heap = DefaultOwnership::new(tcx, &adt_heap);
828
829 let _ = field_ty.visit_with(&mut default_heap);
830 res.update_from_default_heap_visitor(&mut default_heap);
831 }
832 }
833 res
834 }
835 TyKind::Param(..) => {
836 let mut res = OwnershipLayoutResult::new();
837 res.set_requirement(true);
838 res.set_param(true);
839 res.set_owned(true);
840 res.layout_mut().push(HeapInfo::True);
841 res
842 }
843 TyKind::RawPtr(..) => {
844 let mut res = OwnershipLayoutResult::new();
845 res.set_requirement(true);
846 res.layout_mut().push(HeapInfo::False);
847 res
848 }
849 TyKind::Ref(..) => {
850 let mut res = OwnershipLayoutResult::new();
851 res.set_requirement(true);
852 res.layout_mut().push(HeapInfo::False);
853 res
854 }
855 _ => OwnershipLayoutResult::new(),
856 }
857 }
858}
859
860#[derive(Clone)]
861struct IsolatedParamFieldSubst {
862 parameters: HashSet<usize>,
863}
864
865impl<'tcx> IsolatedParamFieldSubst {
866 pub fn new() -> Self {
867 Self {
868 parameters: HashSet::new(),
869 }
870 }
871
872 pub fn parameters(&self) -> &HashSet<usize> {
873 &self.parameters
874 }
875
876 pub fn parameters_mut(&mut self) -> &mut HashSet<usize> {
877 &mut self.parameters
878 }
879
880 pub fn contains_param(&self) -> bool {
881 !self.parameters.is_empty()
882 }
883}
884
885#[derive(Clone)]
886struct IsolatedParamPropagation<'tcx, 'a> {
887 tcx: TyCtxt<'tcx>,
888 record: Vec<bool>,
889 unique: HashSet<DefId>,
890 source_enum: bool,
891 ref_adt_heap: &'a HAResult,
892}
893
894impl<'tcx, 'a> IsolatedParamPropagation<'tcx, 'a> {
895 pub fn new(
896 tcx: TyCtxt<'tcx>,
897 record: Vec<bool>,
898 source_enum: bool,
899 ref_adt_heap: &'a HAResult,
900 ) -> Self {
901 Self {
902 tcx,
903 record,
904 unique: HashSet::new(),
905 source_enum,
906 ref_adt_heap,
907 }
908 }
909
910 pub fn record_mut(&mut self) -> &mut Vec<bool> {
911 &mut self.record
912 }
913
914 pub fn unique_mut(&mut self) -> &mut HashSet<DefId> {
915 &mut self.unique
916 }
917
918 pub fn source_enum(&mut self) -> bool {
919 self.source_enum
920 }
921
922 pub fn heap(&self) -> &'a HAResult {
923 self.ref_adt_heap
924 }
925}
926
927#[derive(Clone)]
928struct HeapPropagation<'tcx, 'a> {
929 tcx: TyCtxt<'tcx>,
930 heap: HeapInfo,
931 unique: HashSet<DefId>,
932 heap_res: &'a HAResult,
933}
934
935impl<'tcx, 'a> HeapPropagation<'tcx, 'a> {
936 pub fn new(tcx: TyCtxt<'tcx>, heap: HeapInfo, heap_res: &'a HAResult) -> Self {
937 Self {
938 tcx,
939 heap,
940 unique: HashSet::new(),
941 heap_res,
942 }
943 }
944
945 pub fn heap(&self) -> HeapInfo {
946 self.heap
947 }
948
949 pub fn unique_mut(&mut self) -> &mut HashSet<DefId> {
950 &mut self.unique
951 }
952
953 pub fn heap_res(&self) -> &'a HAResult {
954 self.heap_res
955 }
956}
957
958#[derive(Clone)]
959struct IsolatedParam {
960 record: Vec<bool>,
961}
962
963impl IsolatedParam {
964 pub fn new(len: usize) -> Self {
965 Self {
966 record: vec![false; len],
967 }
968 }
969
970 pub fn record_mut(&mut self) -> &mut Vec<bool> {
971 &mut self.record
972 }
973}
974
975#[derive(Clone)]
976pub struct DefaultOwnership<'tcx, 'a> {
977 tcx: TyCtxt<'tcx>,
978 unique: HashSet<DefId>,
979 ref_adt_heap: &'a HAResult,
980 res: HeapInfo,
981 param: bool,
982 ptr: bool,
983}
984
985impl<'tcx, 'a> DefaultOwnership<'tcx, 'a> {
986 pub fn new(tcx: TyCtxt<'tcx>, ref_adt_heap: &'a HAResult) -> Self {
987 Self {
988 tcx,
989 unique: HashSet::new(),
990 ref_adt_heap,
991 res: HeapInfo::False,
992 param: false,
993 ptr: false,
994 }
995 }
996
997 pub fn tcx(&self) -> TyCtxt<'tcx> {
998 self.tcx
999 }
1000
1001 pub fn unique(&self) -> &HashSet<DefId> {
1002 &self.unique
1003 }
1004
1005 pub fn unique_mut(&mut self) -> &mut HashSet<DefId> {
1006 &mut self.unique
1007 }
1008
1009 pub fn get_res(&self) -> HeapInfo {
1010 self.res
1011 }
1012
1013 pub fn set_res(&mut self, res: HeapInfo) {
1014 self.res = res;
1015 }
1016
1017 pub fn is_owning_true(&self) -> bool {
1018 self.res == HeapInfo::True
1019 }
1020
1021 pub fn get_param(&self) -> bool {
1022 self.param
1023 }
1024
1025 pub fn set_param(&mut self, p: bool) {
1026 self.param = p;
1027 }
1028
1029 pub fn is_param_true(&self) -> bool {
1030 self.param == true
1031 }
1032
1033 pub fn get_ptr(&self) -> bool {
1034 self.ptr
1035 }
1036
1037 pub fn set_ptr(&mut self, p: bool) {
1038 self.ptr = p;
1039 }
1040
1041 pub fn is_ptr_true(&self) -> bool {
1042 self.ptr == true
1043 }
1044
1045 pub fn heap(&self) -> &'a HAResult {
1046 self.ref_adt_heap
1047 }
1048}
1049
1050#[derive(Clone)]
1051pub struct FindPtr<'tcx> {
1052 tcx: TyCtxt<'tcx>,
1053 unique: HashSet<DefId>,
1054 ptr: bool,
1055}
1056
1057impl<'tcx> FindPtr<'tcx> {
1058 pub fn new(tcx: TyCtxt<'tcx>) -> Self {
1059 Self {
1060 tcx,
1061 unique: HashSet::<DefId>::default(),
1062 ptr: false,
1063 }
1064 }
1065
1066 pub fn tcx(&self) -> TyCtxt<'tcx> {
1067 self.tcx
1068 }
1069
1070 pub fn unique(&self) -> &HashSet<DefId> {
1071 &self.unique
1072 }
1073
1074 pub fn unique_mut(&mut self) -> &mut HashSet<DefId> {
1075 &mut self.unique
1076 }
1077
1078 pub fn has_ptr(&self) -> bool {
1079 self.ptr
1080 }
1081
1082 pub fn set_ptr(&mut self, ptr: bool) {
1083 self.ptr = ptr;
1084 }
1085}
1086
1087pub fn is_display_verbose() -> bool {
1088 match env::var_os("ADT_DISPLAY") {
1089 Some(_) => true,
1090 _ => false,
1091 }
1092}
1093
1094#[derive(Debug, Clone, Hash, Eq, PartialEq, Default)]
1095pub struct IndexedTy<'tcx>(pub Option<(usize, &'tcx TyKind<'tcx>, Option<usize>, bool)>);
1096
1097impl<'tcx> IndexedTy<'tcx> {
1098 pub fn new(ty: Ty<'tcx>, vidx: Option<VariantIdx>) -> Self {
1099 match &ty.kind() {
1100 TyKind::Tuple(list) => IndexedTy(Some((list.len(), &ty.kind(), None, true))),
1101 TyKind::Adt(adtdef, ..) => {
1102 if adtdef.is_enum() {
1103 if vidx.is_none() {
1104 return IndexedTy(None);
1105 }
1106 let idx = vidx.unwrap();
1107 let len = adtdef.variants()[idx].fields.len();
1108 IndexedTy(Some((len, &ty.kind(), Some(idx.index()), true)))
1109 } else {
1110 let len = adtdef.variants()[VariantIdx::from_usize(0)].fields.len();
1111 IndexedTy(Some((len, &ty.kind(), None, true)))
1112 }
1113 }
1114 TyKind::Array(..) | TyKind::Param(..) | TyKind::RawPtr(..) | TyKind::Ref(..) => {
1115 IndexedTy(Some((1, &ty.kind(), None, true)))
1116 }
1117 TyKind::Bool
1118 | TyKind::Char
1119 | TyKind::Int(..)
1120 | TyKind::Uint(..)
1121 | TyKind::Float(..)
1122 | TyKind::Str
1123 | TyKind::Slice(..) => IndexedTy(Some((1, &ty.kind(), None, false))),
1124 _ => IndexedTy(None),
1125 }
1126 }
1127
1128 pub fn get_priority(&self) -> usize {
1130 if self.0.is_none() {
1131 return 0;
1132 }
1133 match self.0.unwrap().0 {
1134 0 => 1,
1135 _ => match self.0.unwrap().3 {
1136 true => 2,
1137 false => 1,
1138 },
1139 }
1140 }
1141}
1142
1143#[derive(Clone, Debug)]
1144pub struct OwnershipLayoutResult {
1145 layout: Vec<HeapInfo>,
1146 param: bool,
1147 requirement: bool,
1148 owned: bool,
1149}
1150
1151impl OwnershipLayoutResult {
1152 pub fn new() -> Self {
1153 Self {
1154 layout: Vec::new(),
1155 param: false,
1156 requirement: false,
1157 owned: false,
1158 }
1159 }
1160
1161 pub fn layout(&self) -> &Vec<HeapInfo> {
1162 &self.layout
1163 }
1164
1165 pub fn layout_mut(&mut self) -> &mut Vec<HeapInfo> {
1166 &mut self.layout
1167 }
1168
1169 pub fn get_param(&self) -> bool {
1170 self.param
1171 }
1172
1173 pub fn set_param(&mut self, p: bool) {
1174 self.param = p;
1175 }
1176
1177 pub fn is_param_true(&self) -> bool {
1178 self.param == true
1179 }
1180
1181 pub fn get_requirement(&self) -> bool {
1182 self.requirement
1183 }
1184
1185 pub fn set_requirement(&mut self, r: bool) {
1186 self.requirement = r;
1187 }
1188
1189 pub fn is_requirement_true(&self) -> bool {
1190 self.requirement == true
1191 }
1192
1193 pub fn is_empty(&self) -> bool {
1194 self.layout.is_empty()
1195 }
1196
1197 pub fn is_owned(&self) -> bool {
1198 self.owned == true
1199 }
1200
1201 pub fn set_owned(&mut self, o: bool) {
1202 self.owned = o;
1203 }
1204
1205 pub fn update_from_default_heap_visitor<'tcx, 'a>(
1206 &mut self,
1207 default_heap: &mut DefaultOwnership<'tcx, 'a>,
1208 ) {
1209 if default_heap.is_owning_true() || default_heap.is_ptr_true() {
1210 self.set_requirement(true);
1211 }
1212
1213 if default_heap.is_owning_true() {
1214 self.set_owned(true);
1215 }
1216
1217 self.layout_mut().push(default_heap.get_res());
1218
1219 self.set_param(default_heap.get_param());
1220 }
1221}