1 use crate::rustc::ty::{self, Ty};
2 use rustc::hir::def_id::DefId;
3 use rustc::infer::region_constraints::MemberConstraint;
4 use rustc_data_structures::fx::FxHashMap;
5 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
10 /// Compactly stores a set of `R0 member of [R1...Rn]` constraints,
11 /// indexed by the region R0.
12 crate struct MemberConstraintSet<'tcx, R>
16 /// Stores the first "member" constraint for a given R0. This is an
17 /// index into the `constraints` vector below.
18 first_constraints: FxHashMap<R, NllMemberConstraintIndex>,
20 /// Stores the data about each `R0 member of [R1..Rn]` constraint.
21 /// These are organized into a linked list, so each constraint
22 /// contains the index of the next constraint with the same R0.
23 constraints: IndexVec<NllMemberConstraintIndex, NllMemberConstraint<'tcx>>,
25 /// Stores the `R1..Rn` regions for *all* sets. For any given
26 /// constraint, we keep two indices so that we can pull out a
28 choice_regions: Vec<ty::RegionVid>,
31 /// Represents a `R0 member of [R1..Rn]` constraint
32 crate struct NllMemberConstraint<'tcx> {
33 next_constraint: Option<NllMemberConstraintIndex>,
35 /// The opaque type whose hidden type is being inferred. (Used in error reporting.)
36 crate opaque_type_def_id: DefId,
38 /// The span where the hidden type was instantiated.
39 crate definition_span: Span,
41 /// The hidden type in which R0 appears. (Used in error reporting.)
42 crate hidden_ty: Ty<'tcx>,
45 crate member_region_vid: ty::RegionVid,
47 /// Index of `R1` in `choice_regions` vector from `MemberConstraintSet`.
50 /// Index of `Rn` in `choice_regions` vector from `MemberConstraintSet`.
55 crate struct NllMemberConstraintIndex {
56 DEBUG_FORMAT = "MemberConstraintIndex({})"
60 impl Default for MemberConstraintSet<'tcx, ty::RegionVid> {
61 fn default() -> Self {
63 first_constraints: Default::default(),
64 constraints: Default::default(),
65 choice_regions: Default::default(),
70 impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> {
71 crate fn push_constraint(
73 m_c: &MemberConstraint<'tcx>,
74 mut to_region_vid: impl FnMut(ty::Region<'tcx>) -> ty::RegionVid,
76 debug!("push_constraint(m_c={:?})", m_c);
77 let member_region_vid: ty::RegionVid = to_region_vid(m_c.member_region);
78 let next_constraint = self.first_constraints.get(&member_region_vid).cloned();
79 let start_index = self.choice_regions.len();
80 let end_index = start_index + m_c.choice_regions.len();
81 debug!("push_constraint: member_region_vid={:?}", member_region_vid);
82 let constraint_index = self.constraints.push(NllMemberConstraint {
85 opaque_type_def_id: m_c.opaque_type_def_id,
86 definition_span: m_c.definition_span,
87 hidden_ty: m_c.hidden_ty,
91 self.first_constraints.insert(member_region_vid, constraint_index);
92 self.choice_regions.extend(m_c.choice_regions.iter().map(|&r| to_region_vid(r)));
96 impl<'tcx, R1> MemberConstraintSet<'tcx, R1>
100 /// Remap the "member region" key using `map_fn`, producing a new
101 /// pick-constraint set. This is used in the NLL code to map from
102 /// the original `RegionVid` to an scc index. In some cases, we
103 /// may have multiple R1 values mapping to the same R2 key -- that
104 /// is ok, the two sets will be merged.
105 crate fn into_mapped<R2>(
107 mut map_fn: impl FnMut(R1) -> R2,
108 ) -> MemberConstraintSet<'tcx, R2>
110 R2: Copy + Hash + Eq,
112 // We can re-use most of the original data, just tweaking the
113 // linked list links a bit.
115 // For example if we had two keys Ra and Rb that both now wind
116 // up mapped to the same key S, we would append the linked
117 // list for Ra onto the end of the linked list for Rb (or vice
118 // versa) -- this basically just requires rewriting the final
119 // link from one list to point at the othe other (see
122 let MemberConstraintSet { first_constraints, mut constraints, choice_regions } = self;
124 let mut first_constraints2 = FxHashMap::default();
125 first_constraints2.reserve(first_constraints.len());
127 for (r1, start1) in first_constraints {
129 if let Some(&start2) = first_constraints2.get(&r2) {
130 append_list(&mut constraints, start1, start2);
132 first_constraints2.insert(r2, start1);
135 MemberConstraintSet {
136 first_constraints: first_constraints2,
143 impl<'tcx, R> MemberConstraintSet<'tcx, R>
147 crate fn all_indices(
149 ) -> impl Iterator<Item = NllMemberConstraintIndex> {
150 self.constraints.indices()
153 /// Iterate down the constraint indices associated with a given
154 /// peek-region. You can then use `choice_regions` and other
155 /// methods to access data.
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;
171 /// Returns the "choice regions" for a given member
172 /// constraint. This is the R1..Rn from a constraint like:
175 /// R0 member of [R1..Rn]
177 crate fn choice_regions(&self, pci: NllMemberConstraintIndex) -> &[ty::RegionVid] {
178 let NllMemberConstraint { start_index, end_index, .. } = &self.constraints[pci];
179 &self.choice_regions[*start_index..*end_index]
183 impl<'tcx, R> Index<NllMemberConstraintIndex> for MemberConstraintSet<'tcx, R>
187 type Output = NllMemberConstraint<'tcx>;
189 fn index(&self, i: NllMemberConstraintIndex) -> &NllMemberConstraint<'tcx> {
194 /// Given a linked list starting at `source_list` and another linked
195 /// list starting at `target_list`, modify `target_list` so that it is
196 /// followed by `source_list`.
201 /// target_list: A -> B -> C -> (None)
202 /// source_list: D -> E -> F -> (None)
208 /// target_list: A -> B -> C -> D -> E -> F -> (None)
211 constraints: &mut IndexVec<NllMemberConstraintIndex, NllMemberConstraint<'_>>,
212 target_list: NllMemberConstraintIndex,
213 source_list: NllMemberConstraintIndex,
215 let mut p = target_list;
217 let mut r = &mut constraints[p];
218 match r.next_constraint {
221 r.next_constraint = Some(source_list);