rapx/analysis/core/heap_analysis.rs
1pub mod default;
2
3use rustc_abi::VariantIdx;
4use rustc_middle::ty::{Ty, TyCtxt, TyKind};
5use rustc_span::def_id::DefId;
6
7use std::{
8 collections::{HashMap, HashSet},
9 env, fmt,
10};
11
12use crate::{rap_info, Analysis};
13
14#[repr(u8)]
15#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
16pub enum RawTypeOwner {
17 Unowned = 0,
18 Owned = 1,
19 Unknown = 2,
20}
21
22impl Default for RawTypeOwner {
23 fn default() -> Self {
24 Self::Unknown
25 }
26}
27
28impl RawTypeOwner {
29 pub fn is_owned(&self) -> bool {
30 match self {
31 RawTypeOwner::Owned => true,
32 _ => false,
33 }
34 }
35}
36
37impl fmt::Display for RawTypeOwner {
38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 let name = match self {
40 RawTypeOwner::Unowned => "0",
41 RawTypeOwner::Owned => "1",
42 RawTypeOwner::Unknown => "2",
43 };
44 write!(f, "{}", name)
45 }
46}
47
48pub type HAResult = HashMap<DefId, Vec<(RawTypeOwner, Vec<bool>)>>;
49
50pub trait HeapAnalysis: Analysis {
51 fn get_all_items(&mut self) -> HAResult;
52}
53
54#[derive(Copy, Clone, Debug)]
55pub struct HeapItem;
56
57impl HeapItem {
58 /// This method is used to check if one adt-def is already a heap item.
59 /// It is a summary of one type which demonstrate that we will consider all the fields/variants,
60 /// although the analyzer will not traverse them (thus overhead is cheap).
61 ///
62 /// # Safety
63 /// If `ty` is not an adt, the result is `Err`.
64 ///
65 /// # Case `ty::Ty`
66 /// Given the adt `MyVec<T, A>` the result is `Ok(true)`.
67 /// ```rust
68 /// pub struct MyVec<T, A: Allocator = Global> {
69 /// buf: RawVec<T, A>, // this field is a heap item
70 /// len: usize,
71 /// }
72 /// ```
73 ///
74 /// # Example:
75 /// ```rust
76 /// use rap::analysis::core::heap_item::HeapItem;
77 /// let ans = HeapItem::is_adt(rcanary.rcx, vec.ty);
78 /// ```
79 pub fn is_adt<'tcx>(adt_owner: HAResult, ty: Ty<'tcx>) -> Result<bool, &'static str> {
80 match ty.kind() {
81 TyKind::Adt(adtdef, ..) => {
82 let ans = adt_owner.get(&adtdef.0 .0.did).unwrap();
83 for i in ans.iter() {
84 if i.0 == RawTypeOwner::Owned {
85 return Ok(true);
86 }
87 }
88 Ok(false)
89 }
90 _ => Err("The input is not an ADT"),
91 }
92 }
93
94 /// This method is used to check if one adt-def of the struct is already a heap item.
95 /// It is a summary of one type which demonstrate that we will consider all the fields,
96 /// although the analyzer will not traverse them (thus overhead is cheap).
97 ///
98 /// # Safety
99 /// If `ty` is not an adt, the result is `Err`.
100 /// If the input is the def of an enum type, the result is `Err`.
101 ///
102 /// # Case `ty::Ty`
103 /// Given the adt `MyVec<T, A>` the result is `Ok(true)`.
104 /// ```rust
105 /// pub struct MyVec<T, A: Allocator = Global> {
106 /// buf: RawVec<T, A>, // this field is a heap item
107 /// len: usize,
108 /// }
109 /// ```
110 ///
111 /// # Example:
112 /// ```rust
113 /// use rap::analysis::core::heap_item::HeapItem;
114 /// let ans = HeapItem::is_struct(rcanary.rcx, vec.ty);
115 /// ```
116 pub fn is_struct<'tcx>(adt_owner: HAResult, ty: Ty<'tcx>) -> Result<bool, &'static str> {
117 match ty.kind() {
118 TyKind::Adt(adtdef, ..) => {
119 if !adtdef.is_struct() && !adtdef.is_union() {
120 return Err("The input is not a struct");
121 }
122 let ans = adt_owner.get(&adtdef.0 .0.did).unwrap();
123 if ans[0].0 == RawTypeOwner::Owned {
124 return Ok(true);
125 }
126 Ok(false)
127 }
128 _ => Err("The input is not an ADT"),
129 }
130 }
131
132 /// This method is used to check if one adt-def of the enum is already a heap item.
133 /// It is a summary of one type which demonstrate that we will consider all the variants,
134 /// although the analyzer will not traverse them (thus overhead is cheap).
135 /// Note that, even for each variance, the result also analyze all its fields.
136 /// It can be referred to the enum with enum-type variance.
137 ///
138 /// # Safety
139 /// If `ty` is not an adt, the result is `Err`.
140 /// If the input is the def of a struct type, the result is `Err`.
141 ///
142 /// # Case `ty::Ty`
143 /// Given the adt `MyBuf<T>` the result is `Ok(true)`.
144 /// ```rust
145 /// pub enum MyBuf<T> {
146 /// Buf1(Vec<T>), // this variance is a heap item
147 /// Buf2(Vec<T>), // this variance is a heap item
148 /// }
149 /// ```
150 ///
151 /// # Example:
152 /// ```rust
153 /// use rap::analysis::core::heap_item::HeapItem;
154 /// let ans = HeapItem::is_enum(rcanary.rcx, vec.ty);
155 /// ```
156 pub fn is_enum<'tcx>(adt_owner: HAResult, ty: Ty<'tcx>) -> Result<bool, &'static str> {
157 match ty.kind() {
158 TyKind::Adt(adtdef, ..) => {
159 if !adtdef.is_enum() {
160 return Err("The input is not an enum");
161 }
162 let ans = adt_owner.get(&adtdef.0 .0.did).unwrap();
163 for i in ans.iter() {
164 if i.0 == RawTypeOwner::Owned {
165 return Ok(true);
166 }
167 }
168 Ok(false)
169 }
170 _ => Err("The input is not an ADT"),
171 }
172 }
173
174 /// This method is used to check if one variance of the enum is already a heap item.
175 /// It is a summary of one variance which demonstrate that we will consider all the fields of it,
176 /// although the analyzer will not traverse them (thus overhead is cheap).
177 /// It can be referred to the enum with enum-type variance.
178 ///
179 /// # Safety
180 /// If `ty` is not an adt, the result is `Err`.
181 /// If the input is the def of a struct type, the result is `Err`.
182 /// If the index `idx` is not valid (out of bound), the result is `Err`.
183 ///
184 /// # Case `ty::Ty`
185 /// Given the adt `MyBuf<T>` the result for idx: 0, 1 is `Ok(true)`; the result for idx: 3 is `Err`.
186 /// ```rust
187 /// pub enum MyBuf<T> {
188 /// Buf1(Vec<T>), // this variance is a heap item
189 /// Buf2(Vec<T>), // this variance is a heap item
190 /// }
191 /// ```
192 ///
193 /// # Example:
194 /// ```rust
195 /// use rap::analysis::core::heap_item::HeapItem;
196 /// let ans = HeapItem::is_enum_vidx(rcanary.rcx, vec.ty, 1);
197 /// ```
198 pub fn is_enum_vidx<'tcx>(
199 adt_owner: HAResult,
200 ty: Ty<'tcx>,
201 idx: usize,
202 ) -> Result<bool, &'static str> {
203 match ty.kind() {
204 TyKind::Adt(adtdef, ..) => {
205 if !adtdef.is_enum() {
206 return Err("The input is not an enum");
207 }
208 let ans = adt_owner.get(&adtdef.0 .0.did).unwrap();
209 if idx > ans.len() {
210 return Err("The index is not a valid variance");
211 }
212 if ans[idx].0 == RawTypeOwner::Owned {
213 return Ok(true);
214 }
215 Ok(false)
216 }
217 _ => Err("The input is not an ADT"),
218 }
219 }
220
221 /// This method is used to give the result of all the variances of the enum.
222 /// For each variance, it is a summary that we will consider all the fields of it,
223 /// although the analyzer will not traverse them (thus overhead is cheap).
224 /// It can be referred to the enum with enum-type variance.
225 ///
226 /// # Safety
227 /// If `ty` is not an adt, the result is `Err`.
228 /// If the input is the def of a struct type, the result is `Err`.
229 ///
230 /// # Case `ty::Ty`
231 /// Given the adt `MyBuf<T>` the result is `[true, false]`.
232 /// ```rust
233 /// pub enum MyBuf<T> {
234 /// Buf1(Vec<T>), // this variance is a heap item
235 /// Buf2(()), // this variance is a heap item
236 /// }
237 /// ```
238 ///
239 /// # Example:
240 /// ```rust
241 /// use rap::analysis::core::heap_item::HeapItem;
242 /// let ans = HeapItem::is_enum_flattened(rcanary.rcx, vec.ty);
243 /// ```
244 pub fn is_enum_flattened<'tcx>(
245 adt_owner: HAResult,
246 ty: Ty<'tcx>,
247 ) -> Result<Vec<bool>, &'static str> {
248 match ty.kind() {
249 TyKind::Adt(adtdef, ..) => {
250 if !adtdef.is_enum() {
251 return Err("The input is not an enum");
252 }
253 let ans = adt_owner.get(&adtdef.0 .0.did).unwrap();
254 let mut v = Vec::with_capacity(ans.len());
255 for i in ans.iter() {
256 if i.0 == RawTypeOwner::Owned {
257 v.push(true);
258 } else {
259 v.push(false);
260 }
261 }
262 Ok(v)
263 }
264 _ => Err("The input is not an ADT"),
265 }
266 }
267}
268
269pub struct IsolatedParameter;
270
271impl IsolatedParameter {
272 /// This method is used to check if one adt-def has at least one isolated parameter.
273 /// It is a summary of one type which demonstrate that we will consider all the generics.
274 /// Those generic parameters can be located in different fields/variants, and some of them can be
275 /// found in multiple fields/variants.
276 /// The analyzer will not traverse them to generate the result (thus overhead is cheap).
277 ///
278 /// # Safety
279 /// If `ty` is not an adt, the result is `Err`.
280 ///
281 /// # Case `ty::Ty`
282 /// Given the adt `MyVec<T, A>` the result is `Ok(true)`.
283 /// ```rust
284 /// pub struct MyVec<T, A: Allocator = Global> { // parameter A is an isolated parameter
285 /// buf: RawVec<T, A>, // parameter A inside in RawVec
286 /// len: usize,
287 /// }
288 /// ```
289 ///
290 /// # Example:
291 /// ```rust
292 /// use rap::analysis::core::heap_item::IsolatedParameter;
293 /// let ans = IsolatedParameter::is_adt(rcanary.rcx, vec.ty);
294 /// ```
295 pub fn is_adt<'tcx>(adt_owner: HAResult, ty: Ty<'tcx>) -> Result<bool, &'static str> {
296 match ty.kind() {
297 TyKind::Adt(adtdef, ..) => {
298 let ans = adt_owner.get(&adtdef.0 .0.did).unwrap();
299 for i in ans.iter() {
300 if i.1.iter().any(|&x| x == true) {
301 return Ok(true);
302 }
303 }
304 Ok(false)
305 }
306 _ => Err("The input is not an ADT"),
307 }
308 }
309
310 /// This method is used to check if one adt-def of the struct has at least one isolated parameter.
311 /// It is a summary of one type which demonstrate that we will consider all the generics.
312 /// Those generic parameters can be located in different fields, and some of them can be
313 /// found in multiple fields.
314 /// The analyzer will not traverse them to generate the result (thus overhead is cheap).
315 ///
316 /// # Safety
317 /// If `ty` is not an adt, the result is `Err`.
318 ///
319 /// # Case `ty::Ty`
320 /// Given the adt `MyVec<T, A>` the result is `Ok(true)`.
321 /// ```rust
322 /// pub struct MyVec<T, A: Allocator = Global> { // parameter A is an isolated parameter
323 /// buf: RawVec<T, A>, // parameter A inside in RawVec
324 /// len: usize,
325 /// }
326 /// ```
327 ///
328 /// # Example:
329 /// ```rust
330 /// use rap::analysis::core::heap_item::IsolatedParameter;
331 /// let ans = IsolatedParameter::is_adt(rcanary.rcx, vec.ty);
332 /// ```
333 pub fn is_struct<'tcx>(adt_owner: HAResult, ty: Ty<'tcx>) -> Result<bool, &'static str> {
334 match ty.kind() {
335 TyKind::Adt(adtdef, ..) => {
336 if !adtdef.is_struct() && !adtdef.is_union() {
337 return Err("The input is not a struct");
338 }
339 let ans = adt_owner.get(&adtdef.0 .0.did).unwrap();
340 if ans[0].1.iter().any(|&x| x == true) {
341 return Ok(true);
342 }
343 Ok(false)
344 }
345 _ => Err("The input is not an ADT"),
346 }
347 }
348
349 /// This method is used to check if one adt-def of the enum has at least one isolated parameter.
350 /// It is a summary of one type which demonstrate that we will consider all the generics in all the variants.
351 /// Those generic parameters can be located in different fields, and some of them can be
352 /// found in multiple fields.
353 /// Note that, even for each variance, the result also analyze all its fields.
354 /// It can be referred to the enum with enum-type variance.
355 ///
356 /// # Safety
357 /// If `ty` is not an adt, the result is `Err`.
358 /// If the input is the def of a struct type, the result is `Err`.
359 ///
360 /// # Case `ty::Ty`
361 /// Given the adt `MyBuf<T, S, F>` the result is `Ok(true)`.
362 /// ```rust
363 /// pub enum MyBuf<T, S, F> { // parameter S F are an isolated parameters
364 /// Buf1(Vec<T>),
365 /// Buf2(S), // this variance is an isolated parameter
366 /// Buf3((F,S)), // this variance has 2 isolated parameters
367 /// }
368 /// ```
369 ///
370 /// # Example:
371 /// ```rust
372 /// use rap::analysis::core::heap_item::IsolatedParameter;
373 /// let ans = IsolatedParameter::is_adt(rcanary.rcx, vec.ty);
374 /// ```
375 pub fn is_enum<'tcx>(adt_owner: HAResult, ty: Ty<'tcx>) -> Result<bool, &'static str> {
376 match ty.kind() {
377 TyKind::Adt(adtdef, ..) => {
378 if !adtdef.is_enum() {
379 return Err("The input is not an enum");
380 }
381 let ans = adt_owner.get(&adtdef.0 .0.did).unwrap();
382 for i in ans.iter() {
383 if i.1.iter().any(|&x| x == true) {
384 return Ok(true);
385 }
386 }
387 Ok(false)
388 }
389 _ => Err("The input is not an ADT"),
390 }
391 }
392
393 /// This method is used to check if one variance of the enum has at least one isolated parameter.
394 /// It is a summary of one type which demonstrate that we will consider all the generics in the given variance.
395 /// Note that, even for this variance, the result also analyze all its fields.
396 /// It can be referred to the enum with enum-type variance.
397 ///
398 /// # Safety
399 /// If `ty` is not an adt, the result is `Err`.
400 /// If the input is the def of a struct type, the result is `Err`.
401 /// If the index `idx` is not valid (out of bound), the result is `Err`.
402 ///
403 /// # Case `ty::Ty`
404 /// Given the adt `MyBuf<T, S, F>` the result for idx: 0 is `Ok(false)`; the result for idx: 1, 2 is `Ok(true)`; the result for idx: 3 is `Err`.
405 /// ```rust
406 /// pub enum MyBuf<T, S, F> { // parameter S F are an isolated parameters
407 /// Buf1(Vec<T>),
408 /// Buf2(S), // this variance is an isolated parameter
409 /// Buf3((F,S)), // this variance has 2 isolated parameters
410 /// }
411 /// ```
412 ///
413 /// # Example:
414 /// ```rust
415 /// use rap::analysis::core::heap_item::IsolatedParameter;
416 /// let ans = IsolatedParameter::is_enum_vidx(rcanary.rcx, vec.ty, 1);
417 /// ```
418 pub fn is_enum_vidx<'tcx>(
419 adt_owner: HAResult,
420 ty: Ty<'tcx>,
421 idx: usize,
422 ) -> Result<bool, &'static str> {
423 match ty.kind() {
424 TyKind::Adt(adtdef, ..) => {
425 if !adtdef.is_enum() {
426 return Err("The input is not an enum");
427 }
428 let ans = adt_owner.get(&adtdef.0 .0.did).unwrap();
429 if idx > ans.len() {
430 return Err("The index is not a valid variance");
431 }
432 if ans[idx].1.iter().any(|&x| x == true) {
433 return Ok(true);
434 }
435 Ok(false)
436 }
437 _ => Err("The input is not an ADT"),
438 }
439 }
440
441 /// This method is used to check if one adt-def of the enum has at least one isolated parameter.
442 /// It is a summary of one type which demonstrate that we will consider all the generics in all the variants.
443 /// Those generic parameters can be located in different fields, and some of them can be
444 /// found in multiple fields.
445 /// Note that, even for each variance, the result also analyze all its fields.
446 /// It can be referred to the enum with enum-type variance.
447 ///
448 /// # Safety
449 /// If `ty` is not an adt, the result is `Err`.
450 /// If the input is the def of a struct type, the result is `Err`.
451 ///
452 /// # Case `ty::Ty`
453 /// Given the adt `Vec<T, A>` the result is `Ok(true)`.
454 /// ```rust
455 /// pub enum MyBuf<T, S, F> { // parameter S F are an isolated parameters
456 /// Buf1(Vec<T>),
457 /// Buf2(S), // this variance is an isolated parameter
458 /// Buf3((F,S)), // this variance has 2 isolated parameters
459 /// }
460 /// ```
461 ///
462 /// # Example:
463 /// ```rust
464 /// use rap::analysis::core::heap_item::IsolatedParameter;
465 /// let ans = IsolatedParameter::is_enum_flattened(rcanary.rcx, vec.ty);
466 /// ```
467 pub fn is_enum_flattened<'tcx>(
468 adt_owner: HAResult,
469 ty: Ty<'tcx>,
470 ) -> Result<Vec<Vec<bool>>, &'static str> {
471 match ty.kind() {
472 TyKind::Adt(adtdef, ..) => {
473 if !adtdef.is_enum() {
474 return Err("The input is not an enum");
475 }
476 let ans = adt_owner.get(&adtdef.0 .0.did).unwrap();
477 let mut v: Vec<Vec<bool>> = Vec::default();
478 for i in ans.iter() {
479 v.push(i.1.clone());
480 }
481 Ok(v)
482 }
483 _ => Err("The input is not an ADT"),
484 }
485 }
486}
487
488#[derive(Clone)]
489struct IsolatedParam {
490 record: Vec<bool>,
491}
492
493impl IsolatedParam {
494 pub fn new(len: usize) -> Self {
495 Self {
496 record: vec![false; len],
497 }
498 }
499
500 pub fn record_mut(&mut self) -> &mut Vec<bool> {
501 &mut self.record
502 }
503}
504
505#[derive(Clone)]
506struct IsolatedParamFieldSubst {
507 parameters: HashSet<usize>,
508}
509
510impl<'tcx> IsolatedParamFieldSubst {
511 pub fn new() -> Self {
512 Self {
513 parameters: HashSet::new(),
514 }
515 }
516
517 pub fn parameters(&self) -> &HashSet<usize> {
518 &self.parameters
519 }
520
521 pub fn parameters_mut(&mut self) -> &mut HashSet<usize> {
522 &mut self.parameters
523 }
524
525 pub fn contains_param(&self) -> bool {
526 !self.parameters.is_empty()
527 }
528}
529
530#[derive(Clone)]
531struct IsolatedParamPropagation<'tcx, 'a> {
532 tcx: TyCtxt<'tcx>,
533 record: Vec<bool>,
534 unique: HashSet<DefId>,
535 source_enum: bool,
536 ref_adt_owner: &'a HAResult,
537}
538
539impl<'tcx, 'a> IsolatedParamPropagation<'tcx, 'a> {
540 pub fn new(
541 tcx: TyCtxt<'tcx>,
542 record: Vec<bool>,
543 source_enum: bool,
544 ref_adt_owner: &'a HAResult,
545 ) -> Self {
546 Self {
547 tcx,
548 record,
549 unique: HashSet::new(),
550 source_enum,
551 ref_adt_owner,
552 }
553 }
554
555 pub fn record_mut(&mut self) -> &mut Vec<bool> {
556 &mut self.record
557 }
558
559 pub fn unique_mut(&mut self) -> &mut HashSet<DefId> {
560 &mut self.unique
561 }
562
563 pub fn source_enum(&mut self) -> bool {
564 self.source_enum
565 }
566
567 pub fn owner(&self) -> &'a HAResult {
568 self.ref_adt_owner
569 }
570}
571
572#[derive(Clone)]
573struct OwnerPropagation<'tcx, 'a> {
574 tcx: TyCtxt<'tcx>,
575 ownership: RawTypeOwner,
576 unique: HashSet<DefId>,
577 ref_adt_owner: &'a HAResult,
578}
579
580impl<'tcx, 'a> OwnerPropagation<'tcx, 'a> {
581 pub fn new(tcx: TyCtxt<'tcx>, ownership: RawTypeOwner, ref_adt_owner: &'a HAResult) -> Self {
582 Self {
583 tcx,
584 ownership,
585 unique: HashSet::new(),
586 ref_adt_owner,
587 }
588 }
589
590 pub fn ownership(&self) -> RawTypeOwner {
591 self.ownership
592 }
593
594 pub fn unique_mut(&mut self) -> &mut HashSet<DefId> {
595 &mut self.unique
596 }
597
598 pub fn owner(&self) -> &'a HAResult {
599 self.ref_adt_owner
600 }
601}
602
603#[derive(Clone)]
604pub struct DefaultOwnership<'tcx, 'a> {
605 tcx: TyCtxt<'tcx>,
606 unique: HashSet<DefId>,
607 ref_adt_owner: &'a HAResult,
608 res: RawTypeOwner,
609 param: bool,
610 ptr: bool,
611}
612
613impl<'tcx, 'a> DefaultOwnership<'tcx, 'a> {
614 pub fn new(tcx: TyCtxt<'tcx>, ref_adt_owner: &'a HAResult) -> Self {
615 Self {
616 tcx,
617 unique: HashSet::new(),
618 ref_adt_owner,
619 res: RawTypeOwner::Unowned,
620 param: false,
621 ptr: false,
622 }
623 }
624
625 pub fn tcx(&self) -> TyCtxt<'tcx> {
626 self.tcx
627 }
628
629 pub fn unique(&self) -> &HashSet<DefId> {
630 &self.unique
631 }
632
633 pub fn unique_mut(&mut self) -> &mut HashSet<DefId> {
634 &mut self.unique
635 }
636
637 pub fn get_res(&self) -> RawTypeOwner {
638 self.res
639 }
640
641 pub fn set_res(&mut self, res: RawTypeOwner) {
642 self.res = res;
643 }
644
645 pub fn is_owning_true(&self) -> bool {
646 self.res == RawTypeOwner::Owned
647 }
648
649 pub fn get_param(&self) -> bool {
650 self.param
651 }
652
653 pub fn set_param(&mut self, p: bool) {
654 self.param = p;
655 }
656
657 pub fn is_param_true(&self) -> bool {
658 self.param == true
659 }
660
661 pub fn get_ptr(&self) -> bool {
662 self.ptr
663 }
664
665 pub fn set_ptr(&mut self, p: bool) {
666 self.ptr = p;
667 }
668
669 pub fn is_ptr_true(&self) -> bool {
670 self.ptr == true
671 }
672
673 pub fn owner(&self) -> &'a HAResult {
674 self.ref_adt_owner
675 }
676}
677
678#[derive(Clone)]
679pub struct FindPtr<'tcx> {
680 tcx: TyCtxt<'tcx>,
681 unique: HashSet<DefId>,
682 ptr: bool,
683}
684
685impl<'tcx> FindPtr<'tcx> {
686 pub fn new(tcx: TyCtxt<'tcx>) -> Self {
687 Self {
688 tcx,
689 unique: HashSet::<DefId>::default(),
690 ptr: false,
691 }
692 }
693
694 pub fn tcx(&self) -> TyCtxt<'tcx> {
695 self.tcx
696 }
697
698 pub fn unique(&self) -> &HashSet<DefId> {
699 &self.unique
700 }
701
702 pub fn unique_mut(&mut self) -> &mut HashSet<DefId> {
703 &mut self.unique
704 }
705
706 pub fn has_ptr(&self) -> bool {
707 self.ptr
708 }
709
710 pub fn set_ptr(&mut self, ptr: bool) {
711 self.ptr = ptr;
712 }
713}
714
715pub fn is_display_verbose() -> bool {
716 match env::var_os("ADT_DISPLAY") {
717 Some(_) => true,
718 _ => false,
719 }
720}
721
722#[derive(Debug, Clone, Hash, Eq, PartialEq, Default)]
723pub struct IndexedTy<'tcx>(pub Option<(usize, &'tcx TyKind<'tcx>, Option<usize>, bool)>);
724
725impl<'tcx> IndexedTy<'tcx> {
726 pub fn new(ty: Ty<'tcx>, vidx: Option<VariantIdx>) -> Self {
727 match &ty.kind() {
728 TyKind::Tuple(list) => IndexedTy(Some((list.len(), &ty.kind(), None, true))),
729 TyKind::Adt(adtdef, ..) => {
730 if adtdef.is_enum() {
731 if vidx.is_none() {
732 return IndexedTy(None);
733 }
734 let idx = vidx.unwrap();
735 let len = adtdef.variants()[idx].fields.len();
736 IndexedTy(Some((len, &ty.kind(), Some(idx.index()), true)))
737 } else {
738 let len = adtdef.variants()[VariantIdx::from_usize(0)].fields.len();
739 IndexedTy(Some((len, &ty.kind(), None, true)))
740 }
741 }
742 TyKind::Array(..) | TyKind::Param(..) | TyKind::RawPtr(..) | TyKind::Ref(..) => {
743 IndexedTy(Some((1, &ty.kind(), None, true)))
744 }
745 TyKind::Bool
746 | TyKind::Char
747 | TyKind::Int(..)
748 | TyKind::Uint(..)
749 | TyKind::Float(..)
750 | TyKind::Str
751 | TyKind::Slice(..) => IndexedTy(Some((1, &ty.kind(), None, false))),
752 _ => IndexedTy(None),
753 }
754 }
755
756 // 0->unsupported, 1->trivial, 2-> needed
757 pub fn get_priority(&self) -> usize {
758 if self.0.is_none() {
759 return 0;
760 }
761 match self.0.unwrap().0 {
762 0 => 1,
763 _ => match self.0.unwrap().3 {
764 true => 2,
765 false => 1,
766 },
767 }
768 }
769}
770
771
772
773#[derive(Clone, Debug)]
774pub struct OwnershipLayoutResult {
775 layout: Vec<RawTypeOwner>,
776 param: bool,
777 requirement: bool,
778 owned: bool,
779}
780
781impl OwnershipLayoutResult {
782 pub fn new() -> Self {
783 Self {
784 layout: Vec::new(),
785 param: false,
786 requirement: false,
787 owned: false,
788 }
789 }
790
791 pub fn layout(&self) -> &Vec<RawTypeOwner> {
792 &self.layout
793 }
794
795 pub fn layout_mut(&mut self) -> &mut Vec<RawTypeOwner> {
796 &mut self.layout
797 }
798
799 pub fn get_param(&self) -> bool {
800 self.param
801 }
802
803 pub fn set_param(&mut self, p: bool) {
804 self.param = p;
805 }
806
807 pub fn is_param_true(&self) -> bool {
808 self.param == true
809 }
810
811 pub fn get_requirement(&self) -> bool {
812 self.requirement
813 }
814
815 pub fn set_requirement(&mut self, r: bool) {
816 self.requirement = r;
817 }
818
819 pub fn is_requirement_true(&self) -> bool {
820 self.requirement == true
821 }
822
823 pub fn is_empty(&self) -> bool {
824 self.layout.is_empty()
825 }
826
827 pub fn is_owned(&self) -> bool {
828 self.owned == true
829 }
830
831 pub fn set_owned(&mut self, o: bool) {
832 self.owned = o;
833 }
834
835 pub fn update_from_default_ownership_visitor<'tcx, 'a>(
836 &mut self,
837 default_ownership: &mut DefaultOwnership<'tcx, 'a>,
838 ) {
839 if default_ownership.is_owning_true() || default_ownership.is_ptr_true() {
840 self.set_requirement(true);
841 }
842
843 if default_ownership.is_owning_true() {
844 self.set_owned(true);
845 }
846
847 self.layout_mut().push(default_ownership.get_res());
848
849 self.set_param(default_ownership.get_param());
850 }
851}