rapx/analysis/alias_analysis/default/
alias.rs

1use super::{MopAliasPair, MopFnAliasMap, graph::*, types::*, value::*};
2use crate::compat::{FxHashMap, FxHashSet};
3use crate::def_id::*;
4use rustc_hir::def_id::DefId;
5use rustc_middle::{
6    mir::{Local, Operand, Place, ProjectionElem, TerminatorKind},
7    ty,
8};
9use std::collections::HashSet;
10
11/// Maximum number of Value nodes allowed per path.
12/// Once exceeded, further field nodes are not created (precision trade-off).
13const MAX_VALUES_PER_PATH: usize = 1000;
14
15/// Maximum field-sync recursion depth.
16const MAX_FIELD_DEPTH: usize = 10;
17
18impl<'tcx> AliasGraph<'tcx> {
19    /* alias analysis for a single block */
20    pub fn alias_bb(&mut self, bb_index: usize) {
21        for constant in self.block_facts[bb_index].const_value.clone() {
22            self.constants.insert(constant.local, constant.value);
23        }
24        let block_facts = self.block_facts[bb_index].clone();
25        for assign in block_facts.assignments {
26            rap_debug!("assign: {:?}", assign);
27            let lv_idx = self.projection(assign.lv);
28            let rv_idx = self.projection(assign.rv);
29
30            self.assign_alias(lv_idx, rv_idx);
31            rap_debug!("Alias sets: {:?}", self.alias_sets)
32        }
33    }
34
35    /* Check the aliases introduced by the terminator of a basic block, i.e., a function call */
36    pub fn alias_bbcall(
37        &mut self,
38        bb_index: usize,
39        fn_map: &mut MopFnAliasMap,
40        recursion_set: &mut HashSet<DefId>,
41    ) {
42        if let Some(terminator) = self.terminator(bb_index).cloned() {
43            if let TerminatorKind::Call {
44                func: Operand::Constant(ref constant),
45                ref args,
46                ref destination,
47                target: _,
48                unwind: _,
49                call_source: _,
50                fn_span: _,
51            } = terminator.kind
52            {
53                let lv = self.projection(*destination);
54                let mut may_drop = false;
55                if self.values[lv].may_drop {
56                    may_drop = true;
57                }
58
59                let mut merge_vec = Vec::new();
60                merge_vec.push(lv);
61
62                for arg in args {
63                    match arg.node {
64                        Operand::Copy(ref p) | Operand::Move(ref p) => {
65                            let rv = self.projection(*p);
66                            merge_vec.push(rv);
67                            if self.values[rv].may_drop {
68                                may_drop = true;
69                            }
70                        }
71                        //
72                        Operand::Constant(_) => {
73                            merge_vec.push(0);
74                        }
75                        #[cfg(rapx_rustc_ge_196)]
76                        Operand::RuntimeChecks(_) => {}
77                    }
78                }
79                if let &ty::FnDef(target_id, _) = constant.const_.ty().kind() {
80                    if may_drop == false {
81                        return;
82                    }
83                    // This function does not introduce new aliases.
84                    if is_no_alias_intrinsic(target_id) {
85                        return;
86                    }
87                    if !self.tcx().is_mir_available(target_id) {
88                        return;
89                    }
90                    rap_debug!("Sync aliases for function call: {:?}", target_id);
91                    let fn_aliases = if fn_map.contains_key(&target_id) {
92                        rap_debug!("Aliases existed");
93                        fn_map.get(&target_id).unwrap()
94                    } else {
95                        /* Fixed-point iteration: this is not perfect */
96                        if recursion_set.contains(&target_id) {
97                            return;
98                        }
99                        recursion_set.insert(target_id);
100                        let mut alias_graph = AliasGraph::new(self.tcx(), target_id);
101                        alias_graph.find_scc();
102                        alias_graph.process_function_paths(fn_map, recursion_set);
103                        let ret_alias = alias_graph.ret_alias.clone();
104                        rap_debug!("Find aliases of {:?}: {:?}", target_id, ret_alias);
105                        fn_map.insert(target_id, ret_alias);
106                        recursion_set.remove(&target_id);
107                        fn_map.get(&target_id).unwrap()
108                    };
109                    if fn_aliases.aliases().is_empty() {
110                        if let Some(l_set_idx) = self.find_alias_set(lv) {
111                            self.alias_sets[l_set_idx].remove(&lv);
112                        }
113                    }
114                    for alias in fn_aliases.aliases().iter() {
115                        if !alias.valuable() {
116                            continue;
117                        }
118                        self.handle_fn_alias(alias, &merge_vec);
119                        rap_debug!("{:?}", self.alias_sets);
120                    }
121                } else if self.values[lv].may_drop {
122                    for rv in &merge_vec {
123                        if self.values[*rv].may_drop && lv != *rv && self.values[lv].is_ptr() {
124                            // We assume they are alias;
125                            // It is a function call and we should not distinguish left or right;
126                            // Merge the alias instead of assign.
127                            self.merge_alias(lv, *rv);
128                        }
129                    }
130                }
131            }
132        }
133    }
134
135    /*
136     * This is the function for field sensitivity
137     * If the projection is a deref, we directly return its local;
138     * If the projection is a field, we further make the id and its first element an alias.
139     */
140    pub fn projection(&mut self, place: Place<'tcx>) -> usize {
141        let local = place.local.as_usize();
142        rap_debug!("projection: place = {:?}, local = {:?}", place, local);
143        let mut value_idx = local;
144        // Projections are leveled
145        // Case 1: (*6).1 involves two projections: a Deref and a Field.
146        // Case 2: (6.0).1 involves two field projections.
147        // We should recursively parse the projection.
148        for proj in place.projection {
149            rap_debug!("proj: {:?}", proj);
150            let new_value_idx = self.values.len();
151            match proj {
152                ProjectionElem::Deref => {}
153                ProjectionElem::Field(field, ty) => {
154                    let field_idx = field.as_usize();
155                    if !self.values[value_idx].fields.contains_key(&field_idx) {
156                        if self.values.len() < MAX_VALUES_PER_PATH {
157                            let ty_env = ty::TypingEnv::post_analysis(self.tcx(), self.def_id());
158                            let need_drop = ty.needs_drop(self.tcx(), ty_env);
159                            let may_drop = !is_not_drop(self.tcx(), ty);
160                            let mut node =
161                                Value::new(new_value_idx, local, need_drop, need_drop || may_drop);
162                            node.kind = kind(ty);
163                            node.father = Some(FatherInfo::new(value_idx, field_idx));
164                            self.values[value_idx].fields.insert(field_idx, node.index);
165                            self.values.push(node);
166                        } else {
167                            break;
168                        }
169                    }
170                    value_idx = *self.values[value_idx].fields.get(&field_idx).unwrap();
171                }
172                _ => {}
173            }
174        }
175        value_idx
176    }
177
178    /// Used to assign alias for a statement.
179    /// Operation: dealiasing the left; aliasing the left with right.
180    /// Synchronize the fields and father nodes iteratively.
181    pub fn assign_alias(&mut self, lv_idx: usize, rv_idx: usize) {
182        rap_debug!("assign_alias: lv = {:?}. rv = {:?}", lv_idx, rv_idx);
183
184        let r_set_idx = if let Some(idx) = self.find_alias_set(rv_idx) {
185            idx
186        } else {
187            self.alias_sets
188                .push([rv_idx].into_iter().collect::<FxHashSet<usize>>());
189            self.alias_sets.len() - 1
190        };
191
192        if let Some(l_set_idx) = self.find_alias_set(lv_idx) {
193            if l_set_idx == r_set_idx {
194                return;
195            }
196            self.alias_sets[l_set_idx].remove(&lv_idx);
197        }
198        let new_l_set_idx = r_set_idx;
199        self.alias_sets[new_l_set_idx].insert(lv_idx);
200
201        if self.values[lv_idx].fields.len() > 0 || self.values[rv_idx].fields.len() > 0 {
202            self.sync_field_alias(lv_idx, rv_idx, 0, true);
203        }
204        if self.values[rv_idx].father != None {
205            self.sync_father_alias(lv_idx, rv_idx, new_l_set_idx);
206        }
207    }
208
209    // Update the aliases of fields.
210    // Case 1, lv = 1; rv = 2; field of rv: 1;
211    // Expected result: [1,2] [1.1,2.1];
212    // Case 2, lv = 0.0, rv = 7, field of rv: 0;
213    // Expected result: [0.0,7] [0.0.0,7.0]
214    pub fn sync_field_alias(&mut self, lv: usize, rv: usize, depth: usize, clear_left: bool) {
215        if depth > MAX_FIELD_DEPTH || self.values.len() >= MAX_VALUES_PER_PATH {
216            return;
217        }
218        rap_debug!("sync field aliases for lv:{} rv:{}", lv, rv);
219
220        // For the fields of lv; we should remove them from the alias sets;
221        if clear_left {
222            for lv_field in self.values[lv].fields.clone().into_iter() {
223                if let Some(alias_set_idx) = self.find_alias_set(lv_field.1) {
224                    self.alias_sets[alias_set_idx].remove(&lv_field.1);
225                }
226            }
227        }
228        for rv_field in self.values[rv].fields.clone().into_iter() {
229            rap_debug!("rv_field: {:?}", rv_field);
230            if !self.values[lv].fields.contains_key(&rv_field.0) {
231                if self.values.len() < MAX_VALUES_PER_PATH {
232                    let mut node = Value::new(
233                        self.values.len(),
234                        self.values[lv].local,
235                        self.values[rv_field.1].need_drop,
236                        self.values[rv_field.1].may_drop,
237                    );
238                    node.kind = self.values[rv_field.1].kind;
239                    node.father = Some(FatherInfo::new(lv, rv_field.0));
240                    self.values[lv].fields.insert(rv_field.0, node.index);
241                    self.values.push(node);
242                } else {
243                    continue;
244                }
245            }
246            let lv_field_value_idx = *(self.values[lv].fields.get(&rv_field.0).unwrap());
247
248            rap_debug!(
249                "alias_set_id of rv_field {:?}",
250                self.find_alias_set(rv_field.1)
251            );
252            if let Some(alias_set_idx) = self.find_alias_set(rv_field.1) {
253                self.alias_sets[alias_set_idx].insert(lv_field_value_idx);
254            }
255            rap_debug!("alias sets: {:?}", self.alias_sets);
256            self.sync_field_alias(lv_field_value_idx, rv_field.1, depth + 1, true);
257        }
258    }
259
260    // For example,
261    // Case 1: lv = 1; rv = 2.0; alias set [2, 3]
262    // Expected result: [1, 2.0, 3.0], [2, 3];
263    // Case 2: lv = 1.0; rv = 2; alias set [1, 3]
264    // Expected result: [1.0, 2], [1, 3]
265    pub fn sync_father_alias(&mut self, lv: usize, rv: usize, lv_alias_set_idx: usize) {
266        rap_debug!("sync father aliases for lv:{} rv:{}", lv, rv);
267        let mut father_id = rv;
268        let mut father = self.values[father_id].father.clone();
269        let mut iteration = 0usize;
270        while let Some(father_info) = father {
271            iteration += 1;
272            if iteration > 1000 {
273                rap_warn!(
274                    "sync_father_alias exceeded 1000 iterations: lv={} rv={} father_id={}",
275                    lv,
276                    rv,
277                    father_id
278                );
279                break;
280            }
281            father_id = father_info.father_value_id;
282            let field_id = father_info.field_id;
283            let father_value = self.values[father_id].clone();
284            if let Some(alias_set_idx) = self.find_alias_set(father_id) {
285                for value_idx in self.alias_sets[alias_set_idx].clone() {
286                    // create a new node if the node does not exist;
287                    let field_value_idx = if self.values[value_idx].fields.contains_key(&field_id) {
288                        *self.values[value_idx].fields.get(&field_id).unwrap()
289                    } else if self.values.len() < MAX_VALUES_PER_PATH {
290                        let mut node = Value::new(
291                            self.values.len(),
292                            self.values[value_idx].local,
293                            self.values[value_idx].need_drop,
294                            self.values[value_idx].may_drop,
295                        );
296                        node.kind = self.values[value_idx].kind;
297                        node.father = Some(FatherInfo::new(value_idx, field_id));
298                        self.values.push(node.clone());
299                        self.values[value_idx].fields.insert(field_id, node.index);
300                        node.index
301                    } else {
302                        continue;
303                    };
304                    // add the node to the alias_set of lv;
305                    self.alias_sets[lv_alias_set_idx].insert(field_value_idx);
306                }
307            }
308            father = father_value.father;
309        }
310    }
311
312    // Handle aliases introduced by function calls.
313    pub fn handle_fn_alias(&mut self, fn_alias: &MopAliasPair, arg_vec: &[usize]) {
314        rap_debug!(
315            "merge aliases returned by function calls, args: {:?}",
316            arg_vec
317        );
318        rap_debug!("fn alias: {:?}", fn_alias);
319        if fn_alias.left_local() >= arg_vec.len() || fn_alias.right_local() >= arg_vec.len() {
320            return;
321        }
322
323        let mut lv = arg_vec[fn_alias.left_local()];
324        let mut rv = arg_vec[fn_alias.right_local()];
325        let left_local = self.values[lv].local;
326        let right_local = self.values[rv].local;
327
328        for index in fn_alias.lhs_fields().iter() {
329            if !self.values[lv].fields.contains_key(index) {
330                if self.values.len() < MAX_VALUES_PER_PATH {
331                    let need_drop = fn_alias.lhs_need_drop;
332                    let may_drop = fn_alias.lhs_may_drop;
333                    let mut node = Value::new(self.values.len(), left_local, need_drop, may_drop);
334                    node.kind = ValueKind::RawPtr;
335                    node.father = Some(FatherInfo::new(lv, *index));
336                    self.values[lv].fields.insert(*index, node.index);
337                    self.values.push(node);
338                } else {
339                    break;
340                }
341            }
342            lv = *self.values[lv].fields.get(index).unwrap();
343        }
344        for index in fn_alias.rhs_fields().iter() {
345            if !self.values[rv].fields.contains_key(index) {
346                if self.values.len() < MAX_VALUES_PER_PATH {
347                    let need_drop = fn_alias.rhs_need_drop;
348                    let may_drop = fn_alias.rhs_may_drop;
349                    let mut node = Value::new(self.values.len(), right_local, need_drop, may_drop);
350                    node.kind = ValueKind::RawPtr;
351                    node.father = Some(FatherInfo::new(rv, *index));
352                    self.values[rv].fields.insert(*index, node.index);
353                    self.values.push(node);
354                } else {
355                    break;
356                }
357            }
358            rv = *self.values[rv].fields.get(index).unwrap();
359        }
360        // It is a function call and we should not distinguish left or right;
361        // Merge the alias instead of assign.
362        self.merge_alias(lv, rv);
363    }
364
365    pub fn get_field_seq(&self, value: &Value) -> Vec<usize> {
366        let mut field_id_seq = vec![];
367        let mut node_ref = value;
368        let mut iteration = 0usize;
369        while let Some(father) = &node_ref.father {
370            iteration += 1;
371            if iteration > 1000 {
372                rap_warn!("get_field_seq exceeded 1000 iterations: value={:?}", value);
373                break;
374            }
375            field_id_seq.push(father.field_id);
376            node_ref = &self.values[father.father_value_id];
377        }
378        field_id_seq
379    }
380
381    /// Checks whether a sequence of field projections on a local MIR variable is valid.
382    /// For example, if the type of a local (e.g., 0) has two fields, 0.2 or 0.3 are both invalid.
383    fn is_valid_field(&self, local: usize, field_seq: &[usize]) -> bool {
384        let body = self.tcx().optimized_mir(self.def_id());
385        let mut ty = body.local_decls[Local::from_usize(local)].ty;
386        for &fidx in field_seq {
387            while let ty::TyKind::Ref(_, inner, _) | ty::TyKind::RawPtr(inner, _) = ty.kind() {
388                ty = *inner;
389            }
390            if let ty::Adt(def, _) = ty.kind() {
391                let field_count = def.all_fields().count();
392                if fidx >= field_count {
393                    return false;
394                }
395            } else {
396                // Not an ADT (struct/tuple), cannot project field
397                return false;
398            }
399        }
400        true
401    }
402
403    //merge the result of current path to the final result.
404    pub fn merge_results(&mut self) {
405        rap_debug!("merge results");
406        let f_node: Vec<Option<FatherInfo>> =
407            self.values.iter().map(|v| v.father.clone()).collect();
408        let set_index = self.build_set_index();
409        // Pre-compute: for each alias set, which values have local <= arg_size
410        let mut set_arg_values: Vec<Vec<usize>> = vec![Vec::new(); self.alias_sets.len()];
411        for (set_idx, set) in self.alias_sets.iter().enumerate() {
412            for &v in set {
413                if self.values[v].local <= self.arg_size() {
414                    set_arg_values[set_idx].push(v);
415                }
416            }
417        }
418        for node in self.values.iter() {
419            if node.local > self.arg_size() {
420                continue;
421            }
422            // Skip expensive scan when values are huge
423            let scan_limit = MAX_VALUES_PER_PATH.min(self.values.len());
424            for idx in 1..scan_limit {
425                if !self.is_aliasing_indexed(idx, node.index, &set_index) {
426                    continue;
427                }
428
429                let mut replace = None;
430                if self.values[idx].local > self.arg_size() {
431                    for (i, fidx) in f_node.iter().enumerate() {
432                        if replace.is_some() {
433                            break;
434                        }
435                        if let Some(father_info) = fidx {
436                            if i != idx && i != node.index {
437                                if let Some(set_idx) = set_index.get(&father_info.father_value_id) {
438                                    for &j in &set_arg_values[*set_idx] {
439                                        if j != idx && j != node.index {
440                                            replace = Some(&self.values[j]);
441                                            break;
442                                        }
443                                    }
444                                }
445                            }
446                        }
447                    }
448                }
449
450                if (self.values[idx].local <= self.arg_size() || replace.is_some())
451                    && idx != node.index
452                    && node.local != self.values[idx].local
453                {
454                    let left_node;
455                    let right_node;
456                    match self.values[idx].local {
457                        0 => {
458                            left_node = match replace {
459                                Some(replace_node) => replace_node,
460                                None => &self.values[idx],
461                            };
462                            right_node = node;
463                        }
464                        _ => {
465                            left_node = node;
466                            right_node = match replace {
467                                Some(replace_node) => replace_node,
468                                None => &self.values[idx],
469                            };
470                        }
471                    }
472                    let mut new_alias = MopAliasPair::new(
473                        left_node.local,
474                        left_node.may_drop,
475                        left_node.need_drop,
476                        right_node.local,
477                        right_node.may_drop,
478                        right_node.need_drop,
479                    );
480                    new_alias.fact.lhs_fields = self.get_field_seq(left_node);
481                    new_alias.fact.rhs_fields = self.get_field_seq(right_node);
482                    if new_alias.left_local() == new_alias.right_local() {
483                        continue;
484                    }
485                    if !self.is_valid_field(left_node.local, &new_alias.fact.lhs_fields)
486                        || !self.is_valid_field(right_node.local, &new_alias.fact.rhs_fields)
487                    {
488                        rap_debug!("new_alias with invalid field: {:?}", new_alias);
489                        continue;
490                    }
491                    rap_debug!("new_alias: {:?}", new_alias);
492                    self.ret_alias.add_alias(new_alias);
493                }
494            }
495        }
496        self.compress_aliases();
497    }
498
499    /// Compresses the alias analysis results with a two-step procedure:
500    ///
501    /// 1. **Field Truncation:**
502    ///    For each alias fact, any `lhs_fields` or `rhs_fields` projection longer than one element
503    ///    is truncated to just its first element (e.g., `1.0.1` becomes `1.0`, `1.2.2.0.0` becomes `1.2`).
504    ///    This aggressively flattens all field projections to a single field level.
505    ///
506    /// 2. **Containment Merging:**
507    ///    For all pairs of alias facts with the same locals, if both the truncated `lhs_fields` and
508    ///    `rhs_fields` of one are a (strict) prefix of another, only the more general (shorter) alias
509    ///    is kept. For example:
510    ///      - Keep (0, 1), remove (0.0, 1.1)
511    ///      - But do **not** merge (0, 1.0) and (0, 1.1), since these have different non-prefix fields.
512    ///
513    /// Call this after constructing the alias set to minimize and canonicalize the result.
514    pub fn compress_aliases(&mut self) {
515        // Step 1: Truncate fields to only the first element if present
516        let mut truncated_facts = Vec::new();
517        for fact in self.ret_alias.alias_set.iter() {
518            let mut new_fact = fact.clone();
519            if !new_fact.fact.lhs_fields.is_empty() {
520                new_fact.fact.lhs_fields = vec![new_fact.fact.lhs_fields[0]];
521            }
522            if !new_fact.fact.rhs_fields.is_empty() {
523                new_fact.fact.rhs_fields = vec![new_fact.fact.rhs_fields[0]];
524            }
525            truncated_facts.push(new_fact);
526        }
527        // Clean up alias set and replace with truncated
528        self.ret_alias.alias_set.clear();
529        for fact in truncated_facts {
530            self.ret_alias.alias_set.insert(fact);
531        }
532
533        // Step 2: Containment merging
534        // For the same (left_local, rhs_local), if (a, b) is a prefix of (a', b'), keep only (a, b)
535        let aliases: Vec<MopAliasPair> = self.ret_alias.alias_set.iter().cloned().collect();
536        let n = aliases.len();
537        let mut to_remove: HashSet<MopAliasPair> = HashSet::new();
538
539        for i in 0..n {
540            for j in 0..n {
541                if i == j || to_remove.contains(&aliases[j]) {
542                    continue;
543                }
544                let a = &aliases[i].fact;
545                let b = &aliases[j].fact;
546                // Only merge if both lhs/rhs locals are equal and BOTH are strict prefixes
547                if a.left_local() == b.left_local() && a.right_local() == b.right_local() {
548                    if a.lhs_fields.len() <= b.lhs_fields.len()
549                    && a.lhs_fields == b.lhs_fields[..a.lhs_fields.len()]
550                    && a.rhs_fields.len() <= b.rhs_fields.len()
551                    && a.rhs_fields == b.rhs_fields[..a.rhs_fields.len()]
552                    // Exclude case where fields are exactly the same (avoid self-removal)
553                    && (a.lhs_fields.len() < b.lhs_fields.len() || a.rhs_fields.len() < b.rhs_fields.len())
554                    {
555                        to_remove.insert(aliases[j].clone());
556                    }
557                }
558            }
559        }
560        for alias in to_remove {
561            self.ret_alias.alias_set.remove(&alias);
562        }
563    }
564
565    #[inline(always)]
566    pub fn find_alias_set(&self, e: usize) -> Option<usize> {
567        self.alias_sets.iter().position(|set| set.contains(&e))
568    }
569
570    #[inline(always)]
571    pub fn is_aliasing(&self, e1: usize, e2: usize) -> bool {
572        let s1 = self.find_alias_set(e1);
573        let s2 = self.find_alias_set(e2);
574        s1.is_some() && s1 == s2
575    }
576
577    fn build_set_index(&self) -> FxHashMap<usize, usize> {
578        let mut map = FxHashMap::default();
579        for (set_idx, set) in self.alias_sets.iter().enumerate() {
580            for &v in set {
581                map.insert(v, set_idx);
582            }
583        }
584        map
585    }
586
587    #[inline(always)]
588    fn is_aliasing_indexed(&self, e1: usize, e2: usize, index: &FxHashMap<usize, usize>) -> bool {
589        match (index.get(&e1), index.get(&e2)) {
590            (Some(s1), Some(s2)) => s1 == s2,
591            _ => false,
592        }
593    }
594
595    pub fn merge_alias(&mut self, e1: usize, e2: usize) {
596        let mut s1 = self.find_alias_set(e1);
597        let mut s2 = self.find_alias_set(e2);
598
599        // Create set for e1 if needed
600        if s1.is_none() {
601            self.alias_sets
602                .push([e1].into_iter().collect::<FxHashSet<usize>>());
603            s1 = Some(self.alias_sets.len() - 1);
604        }
605
606        // Create set for e2 if needed
607        if s2.is_none() {
608            self.alias_sets
609                .push([e2].into_iter().collect::<FxHashSet<usize>>());
610            s2 = Some(self.alias_sets.len() - 1);
611        }
612
613        // After creation, fetch indices (unwrap OK)
614        let idx1 = s1.unwrap();
615        let idx2 = s2.unwrap();
616
617        if idx1 == idx2 {
618            return;
619        }
620
621        let set2 = self.alias_sets.remove(idx2);
622        // If idx2 < idx1, removing idx2 shifts idx1 down by one
623        let idx1 = if idx2 < idx1 { idx1 - 1 } else { idx1 };
624        self.alias_sets[idx1].extend(set2);
625
626        if self.values[e1].fields.len() > 0 {
627            self.sync_field_alias(e2, e1, 0, false);
628        }
629        if self.values[e2].fields.len() > 0 {
630            self.sync_field_alias(e1, e2, 0, false);
631        }
632        if self.values[e1].father != None {
633            self.sync_father_alias(e2, e1, idx1);
634        }
635        if self.values[e2].father != None {
636            self.sync_father_alias(e1, e2, idx1);
637        }
638    }
639
640    #[inline(always)]
641    pub fn get_alias_set(&mut self, e: usize) -> Option<FxHashSet<usize>> {
642        if let Some(idx) = self.find_alias_set(e) {
643            Some(self.alias_sets[idx].clone())
644        } else {
645            None
646        }
647    }
648}
649
650pub fn is_no_alias_intrinsic(def_id: DefId) -> bool {
651    let v = [call_mut_opt(), clone_opt(), take_opt()];
652    contains(&v, def_id)
653}