rustc_borrowck/
member_constraints.rs
1use std::hash::Hash;
2use std::ops::Index;
3
4use rustc_data_structures::fx::FxIndexMap;
5use rustc_index::{IndexSlice, IndexVec};
6use rustc_middle::ty::{self, Ty};
7use rustc_span::Span;
8use tracing::instrument;
9
10#[derive(Debug)]
13pub(crate) struct MemberConstraintSet<'tcx, R>
14where
15 R: Copy + Eq,
16{
17 first_constraints: FxIndexMap<R, NllMemberConstraintIndex>,
20
21 constraints: IndexVec<NllMemberConstraintIndex, MemberConstraint<'tcx>>,
25
26 choice_regions: Vec<ty::RegionVid>,
30}
31
32#[derive(Debug)]
34pub(crate) struct MemberConstraint<'tcx> {
35 next_constraint: Option<NllMemberConstraintIndex>,
36
37 pub(crate) definition_span: Span,
39
40 pub(crate) hidden_ty: Ty<'tcx>,
42
43 pub(crate) key: ty::OpaqueTypeKey<'tcx>,
44
45 pub(crate) member_region_vid: ty::RegionVid,
47
48 start_index: usize,
50
51 end_index: usize,
53}
54
55rustc_index::newtype_index! {
56 #[debug_format = "MemberConstraintIndex({})"]
57 pub(crate) struct NllMemberConstraintIndex {}
58}
59
60impl Default for MemberConstraintSet<'_, ty::RegionVid> {
61 fn default() -> Self {
62 Self {
63 first_constraints: Default::default(),
64 constraints: Default::default(),
65 choice_regions: Default::default(),
66 }
67 }
68}
69
70impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> {
71 pub(crate) fn is_empty(&self) -> bool {
72 self.constraints.is_empty()
73 }
74
75 #[instrument(level = "debug", skip(self))]
77 pub(crate) fn add_member_constraint(
78 &mut self,
79 key: ty::OpaqueTypeKey<'tcx>,
80 hidden_ty: Ty<'tcx>,
81 definition_span: Span,
82 member_region_vid: ty::RegionVid,
83 choice_regions: &[ty::RegionVid],
84 ) {
85 let next_constraint = self.first_constraints.get(&member_region_vid).cloned();
86 let start_index = self.choice_regions.len();
87 self.choice_regions.extend(choice_regions);
88 let end_index = self.choice_regions.len();
89 let constraint_index = self.constraints.push(MemberConstraint {
90 next_constraint,
91 member_region_vid,
92 definition_span,
93 hidden_ty,
94 key,
95 start_index,
96 end_index,
97 });
98 self.first_constraints.insert(member_region_vid, constraint_index);
99 }
100}
101
102impl<'tcx, R1> MemberConstraintSet<'tcx, R1>
103where
104 R1: Copy + Hash + Eq,
105{
106 pub(crate) fn into_mapped<R2>(
112 self,
113 mut map_fn: impl FnMut(R1) -> R2,
114 ) -> MemberConstraintSet<'tcx, R2>
115 where
116 R2: Copy + Hash + Eq,
117 {
118 let MemberConstraintSet { first_constraints, mut constraints, choice_regions } = self;
129
130 let mut first_constraints2 = FxIndexMap::default();
131 first_constraints2.reserve(first_constraints.len());
132
133 for (r1, start1) in first_constraints {
134 let r2 = map_fn(r1);
135 if let Some(&start2) = first_constraints2.get(&r2) {
136 append_list(&mut constraints, start1, start2);
137 }
138 first_constraints2.insert(r2, start1);
139 }
140
141 MemberConstraintSet { first_constraints: first_constraints2, constraints, choice_regions }
142 }
143}
144
145impl<'tcx, R> MemberConstraintSet<'tcx, R>
146where
147 R: Copy + Hash + Eq,
148{
149 pub(crate) fn all_indices(&self) -> impl Iterator<Item = NllMemberConstraintIndex> {
150 self.constraints.indices()
151 }
152
153 pub(crate) fn indices(
157 &self,
158 member_region_vid: R,
159 ) -> impl Iterator<Item = NllMemberConstraintIndex> {
160 let mut next = self.first_constraints.get(&member_region_vid).cloned();
161 std::iter::from_fn(move || -> Option<NllMemberConstraintIndex> {
162 if let Some(current) = next {
163 next = self.constraints[current].next_constraint;
164 Some(current)
165 } else {
166 None
167 }
168 })
169 }
170
171 pub(crate) fn choice_regions(&self, pci: NllMemberConstraintIndex) -> &[ty::RegionVid] {
178 let MemberConstraint { start_index, end_index, .. } = &self.constraints[pci];
179 &self.choice_regions[*start_index..*end_index]
180 }
181}
182
183impl<'tcx, R> Index<NllMemberConstraintIndex> for MemberConstraintSet<'tcx, R>
184where
185 R: Copy + Eq,
186{
187 type Output = MemberConstraint<'tcx>;
188
189 fn index(&self, i: NllMemberConstraintIndex) -> &MemberConstraint<'tcx> {
190 &self.constraints[i]
191 }
192}
193
194fn append_list(
211 constraints: &mut IndexSlice<NllMemberConstraintIndex, MemberConstraint<'_>>,
212 target_list: NllMemberConstraintIndex,
213 source_list: NllMemberConstraintIndex,
214) {
215 let mut p = target_list;
216 loop {
217 let r = &mut constraints[p];
218 match r.next_constraint {
219 Some(q) => p = q,
220 None => {
221 r.next_constraint = Some(source_list);
222 return;
223 }
224 }
225 }
226}