rapx/analysis/core/heap_analysis/
default.rs

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, Ty, TyCtxt, TyKind, TypeSuperVisitable, TypeVisitable, TypeVisitor, 
9        InstanceKind::Item 
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_owner: 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_owner.clone()
41    }
42}
43
44// This function is aiming at resolving problems due to 'TyContext' not implementing 'Clone' trait,
45// thus we call function 'copy_ty_context' to simulate 'self.clone()'.
46#[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_owner: 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_owner(&self) -> &HAResult {
93        &self.adt_owner
94    }
95
96    pub fn adt_owner_mut(&mut self) -> &mut HAResult {
97        &mut self.adt_owner
98    }
99
100    pub fn format_owner_unit(unit: &(RawTypeOwner, Vec<bool>)) -> String {
101        let (owner, flags) = unit;
102        let vec_str = flags
103            .iter()
104            .map(|&b| if b { "1" } else { "0" })
105            .collect::<Vec<_>>()
106            .join(",");
107        format!("({}, [{}])", owner, vec_str)
108    }
109
110    pub fn output(&mut self) {
111        for elem in self.adt_owner() {
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_owner_unit)
117                .collect::<Vec<_>>()
118                .join(", ");
119            rap_info!("{} {}", name, owning);
120        }
121    }
122
123    // From the top-down method of our approach, this 'visitor' is the set of several sub-phases
124    // which means it contains multiple sub-visitors to make whole method 'self.visitor()' work.
125    //
126    // For example, given an adtef (like Vec<T>), the result of 'visitor' contains two parts:
127    //
128    //     pt1 Enum:  {Owned / UnOwned} indicates whether it will directly have a heap data
129    //     pt2 Array: [bool;N] indicates whether each generic parameter will have a raw param
130    //
131    // Those 2 parts can accelerate heap-ownership inference in the data-flow analysis.
132    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_owner(ref_type_analysis: &mut DefaultHeapAnalysis) {
145            for elem in ref_type_analysis.adt_owner() {
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        // Get the Global TyCtxt from rustc
156        // Grasp all mir Keys defined in current crate
157        let tcx = self.tcx;
158        let mir_keys = tcx.mir_keys(());
159
160        for each_mir in mir_keys {
161            // Get the defid of current crate and get mir Body through this id
162            let def_id = each_mir.to_def_id();
163            let body = tcx.instance_mir(Item(def_id));
164
165            // Insert the defid to hashset if is not existed and visit the body
166            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_owner_prop(did), &dids);
179
180        show_owner(self);
181    }
182
183    // Extract params in adt types, the 'param' means one generic parameter acting like 'T', 'A', etc...
184    // In the sub-visitor RawGeneric, it will visit the given type recursively, and extract all params.
185    //
186    // Note that RAP is only interested in 'raw' params ('T' not like '*mut T').
187    // It lies in 'one-entire field' | recursive in tuple | recursive in array | mixed before
188    //
189    // Given a struct Example<A, B, T, S>:
190    //
191    // struct Example<A, B, T, S> {
192    //     a: A,
193    //     b: (i32, (f64, B)),
194    //     c: [[(S) ; 1] ; 2],
195    //     d: Vec<T>,
196    // }
197    //
198    // the final result for <A, B, T, S> is <true, true, false, true>.
199    #[inline(always)]
200    fn extract_raw_generic(&mut self, did: DefId) {
201        // Get the definition and subset reference from adt did
202        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((RawTypeOwner::Unowned, raw_generic.record_mut().clone()));
218        }
219
220        self.adt_owner_mut().insert(did, v_res);
221    }
222
223    // Extract all params in the adt types like param 'T' and then propagate from the bottom to top.
224    // This procedural is the successor of `extract_raw_generic`, and the main idea of RawGenericPropagation
225    // is to propagate params from bottom adt to the top as well as updating Analysis Context.
226    //
227    // Note that it will thorough consider mono-morphization existed in adt-def.
228    // That means the type 'Vec<T>', 'Vec<Vec<T>>' and 'Vec<i32>' are totally different!!!!
229    //
230    // Given a struct Example<A, B, T, S>:
231    //
232    // struct X<A> {
233    //     a: A,
234    // }
235    // the final result for <A> is <true>.
236    //
237    // struct Y1<B> {
238    //     a: (i32, (f64, B)),
239    //     b: X<i32>,
240    // }
241    // the final result for <B> is <true>.
242    //
243    // struct Example<A, B, T, S> {
244    //     a: X<A>,
245    //     b: (i32, (f64, B)),
246    //     c: [[(S) ; 1] ; 2],
247    //     d: Vec<T>,
248    // }
249    //
250    // the final result for <A, B, T, S> is <true, true, false, true>.
251    #[inline(always)]
252    fn extract_raw_generic_prop(&mut self, did: DefId) {
253        // Get the definition and subset reference from adt did
254        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_owner_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_owner(),
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                (RawTypeOwner::Unowned, raw_generic_prop.record_mut().clone());
280        }
281
282        self.adt_owner_mut().insert(did, v_res);
283    }
284
285    // Extract all types that include PhantomData<T> which T must be a raw Param
286    // Consider these types as a unit to guide the traversal over adt types
287    #[inline(always)]
288    fn extract_phantom_unit(&mut self, did: DefId) {
289        // Get ty from defid and the ty is made up with generic type
290        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        // As for one heap-allocation unit, only struct will contains the information that we want
297        // Example:
298        // struct Foo<T> {
299        //     NonNull<T>,      // this indicates a pointer
300        //     PhantomData<T>,  // this indicates a ownership
301        // }
302        if adt_def.is_struct() {
303            let mut res = self.adt_owner_mut().get_mut(&did).unwrap()[0].clone();
304            // Extract all fields in one given struct
305            for field in adt_def.all_fields() {
306                let field_ty = field.ty(self.tcx, substs);
307                match field_ty.kind() {
308                    // Filter the field which is also a struct due to PhantomData<T> is struct
309                    TyKind::Adt(field_adt_def, field_substs) => {
310                        if field_adt_def.is_phantom_data() {
311                            // Extract all generic args in the type
312                            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                                                // To enhance the soundness of phantom unit, the struct should have a
321                                                // pointer to store T
322                                                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 = RawTypeOwner::Owned;
338                                            self.adt_owner_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_owner_prop(&mut self, did: DefId) {
360        // Get the definition and subset reference from adt did
361        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_owner_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 owner_prop = OwnerPropagation::new(self.tcx, res.0, self.adt_owner());
373
374            for field in &variant.fields {
375                let field_ty = field.ty(self.tcx, substs);
376                let _ = field_ty.visit_with(&mut owner_prop);
377            }
378            v_res[variant_index as usize].0 = owner_prop.ownership();
379        }
380
381        self.adt_owner_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    // #[inline(always)]
496    // fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
497    //     Some(self.tcx)
498    // }
499    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.owner().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 OwnerPropagation<'tcx, 'a> {
572    // #[inline(always)]
573    // fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
574    //     Some(self.tcx)
575    // }
576    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.owner().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                    RawTypeOwner::Owned => {
597                        self.ownership = RawTypeOwner::Owned;
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    // #[inline(always)]
654    // fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
655    //     Some(self.tcx)
656    // }
657    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.owner().get(&adtdef.did()).unwrap();
671
672                // handle the secene of Zero Sized Types
673                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                    RawTypeOwner::Owned => {
680                        self.set_res(RawTypeOwner::Owned);
681                        return ControlFlow::Break(());
682                    }
683                    RawTypeOwner::Unowned => {
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(RawTypeOwner::Owned);
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    // 0->unsupported, 1->trivial, 2-> needed
755    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_owner: HAResult,
777        variant: Option<VariantIdx>,
778    ) -> OwnershipLayoutResult {
779        match ty.kind() {
780            TyKind::Array(..) => {
781                let mut res = OwnershipLayoutResult::new();
782                let mut default_ownership = DefaultOwnership::new(tcx, &adt_owner);
783
784                let _ = ty.visit_with(&mut default_ownership);
785                res.update_from_default_ownership_visitor(&mut default_ownership);
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_ownership = DefaultOwnership::new(tcx, &adt_owner);
794
795                    let _ = tuple_ty.visit_with(&mut default_ownership);
796                    res.update_from_default_ownership_visitor(&mut default_ownership);
797                }
798
799                res
800            }
801            TyKind::Adt(adtdef, substs) => {
802                // check the ty is or is not an enum and the variant of this enum is or is not given
803                if adtdef.is_enum() && variant.is_none() {
804                    return OwnershipLayoutResult::new();
805                }
806
807                let mut res = OwnershipLayoutResult::new();
808
809                // check the ty if it is a struct or union
810                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_ownership = DefaultOwnership::new(tcx, &adt_owner);
815
816                        let _ = field_ty.visit_with(&mut default_ownership);
817                        res.update_from_default_ownership_visitor(&mut default_ownership);
818                    }
819                }
820                // check the ty which is an enum with a exact variant idx
821                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_ownership = DefaultOwnership::new(tcx, &adt_owner);
828
829                        let _ = field_ty.visit_with(&mut default_ownership);
830                        res.update_from_default_ownership_visitor(&mut default_ownership);
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(RawTypeOwner::Owned);
841                res
842            }
843            TyKind::RawPtr(..) => {
844                let mut res = OwnershipLayoutResult::new();
845                res.set_requirement(true);
846                res.layout_mut().push(RawTypeOwner::Unowned);
847                res
848            }
849            TyKind::Ref(..) => {
850                let mut res = OwnershipLayoutResult::new();
851                res.set_requirement(true);
852                res.layout_mut().push(RawTypeOwner::Unowned);
853                res
854            }
855            _ => OwnershipLayoutResult::new(),
856        }
857    }
858}