Check alias of p1 and p2 if they are from different fn. To avoid interproc analysis, we use heuristic assumption: p1 and p2 alias if: 1. they point to the same Constant or 2. they point to function parameters with the same type and field or 3. they point to upvars of closures and the upvars alias in the def func. Formally, if exists a1 in pts(p1) and a1 is Constant(c1) and exists a2 in pts(p2) and
(
&mut self,
instance1: &Instance<'tcx>,
node1: &ConstraintNode<'tcx>,
instance2: &Instance<'tcx>,
node2: &ConstraintNode<'tcx>,
)
| 937 | /// then return possible alias |
| 938 | /// return unlikely |
| 939 | fn interproc_alias( |
| 940 | &mut self, |
| 941 | instance1: &Instance<'tcx>, |
| 942 | node1: &ConstraintNode<'tcx>, |
| 943 | instance2: &Instance<'tcx>, |
| 944 | node2: &ConstraintNode<'tcx>, |
| 945 | ) -> Option<ApproximateAliasKind> { |
| 946 | let body1 = self.tcx.instance_mir(instance1.def); |
| 947 | let body2 = self.tcx.instance_mir(instance2.def); |
| 948 | let points_to_map1 = self.get_or_insert_pts(instance1.def_id(), body1).clone(); |
| 949 | let points_to_map2 = self.get_or_insert_pts(instance2.def_id(), body2).clone(); |
| 950 | let pts1 = points_to_map1.get(node1)?; |
| 951 | let pts2 = points_to_map2.get(node2)?; |
| 952 | // 1. Check if `node1` and `node2` points to the same Constant. |
| 953 | if point_to_same_constant(pts1, pts2) { |
| 954 | return Some(ApproximateAliasKind::Probably); |
| 955 | } |
| 956 | // 2. Check if `node1` and `node2` points to func parameters with the same local's type and projection. |
| 957 | if point_to_same_type_param(pts1, pts2, body1, body2) |
| 958 | || point_to_same_projected_param( |
| 959 | pts1, |
| 960 | pts2, |
| 961 | &points_to_map1, |
| 962 | &points_to_map2, |
| 963 | body1, |
| 964 | body2, |
| 965 | self.tcx, |
| 966 | ) |
| 967 | { |
| 968 | return Some(ApproximateAliasKind::Possibly); |
| 969 | } |
| 970 | // 3. Check if `node1` and `node2` point to upvars of closures and the upvars alias in the def func. |
| 971 | // 3.1 Get defsite upvars of `node1` then check if `node2` points to the upvar. |
| 972 | let mut defsite_upvars1 = Vec::new(); |
| 973 | if self.tcx.is_closure_like(instance1.def_id()) { |
| 974 | let pts_paths = points_to_paths_to_param(node1.clone(), body1, &points_to_map1); |
| 975 | for pts_path in pts_paths { |
| 976 | let Some(defsite_upvars) = self.closure_defsite_upvars(instance1, &pts_path) else { |
| 977 | continue; |
| 978 | }; |
| 979 | for (def_inst, upvar) in defsite_upvars.iter() { |
| 980 | if def_inst.def_id() == instance2.def_id() { |
| 981 | let alias_kind = self |
| 982 | .intraproc_points_to(def_inst, node2.clone(), upvar.clone()) |
| 983 | .unwrap_or(ApproximateAliasKind::Unknown); |
| 984 | if alias_kind > ApproximateAliasKind::Unlikely { |
| 985 | return Some(alias_kind); |
| 986 | } |
| 987 | } |
| 988 | } |
| 989 | defsite_upvars1.extend(defsite_upvars); |
| 990 | } |
| 991 | } |
| 992 | // 3.2 Get defsite upvars of `node2` then check if `node1` points to the upvar. |
| 993 | let mut defsite_upvars2 = Vec::new(); |
| 994 | if self.tcx.is_closure_like(instance2.def_id()) { |
| 995 | let pts_paths = points_to_paths_to_param(node2.clone(), body2, &points_to_map2); |
| 996 | for pts_path in pts_paths { |
no test coverage detected