rust/compiler/rustc_borrowck/src/member_constraints.rs

231 lines
7.7 KiB
Rust
Raw Normal View History

2022-05-22 14:48:19 -05:00
use rustc_data_structures::captures::Captures;
2019-06-05 18:07:15 -05:00
use rustc_data_structures::fx::FxHashMap;
use rustc_index::vec::IndexVec;
2020-03-29 09:41:09 -05:00
use rustc_middle::infer::MemberConstraint;
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
2019-06-05 18:07:15 -05:00
use std::hash::Hash;
use std::ops::Index;
2019-06-18 07:52:23 -05:00
/// Compactly stores a set of `R0 member of [R1...Rn]` constraints,
2019-06-24 14:34:37 -05:00
/// indexed by the region `R0`.
pub(crate) struct MemberConstraintSet<'tcx, R>
2019-06-05 18:07:15 -05:00
where
R: Copy + Eq,
2019-06-05 18:07:15 -05:00
{
2019-06-24 14:34:37 -05:00
/// Stores the first "member" constraint for a given `R0`. This is an
2019-06-05 18:07:15 -05:00
/// index into the `constraints` vector below.
2019-06-18 07:52:23 -05:00
first_constraints: FxHashMap<R, NllMemberConstraintIndex>,
2019-06-05 18:07:15 -05:00
2019-06-18 07:52:23 -05:00
/// Stores the data about each `R0 member of [R1..Rn]` constraint.
2019-06-05 18:07:15 -05:00
/// These are organized into a linked list, so each constraint
2019-06-24 14:34:37 -05:00
/// contains the index of the next constraint with the same `R0`.
2019-06-18 07:52:23 -05:00
constraints: IndexVec<NllMemberConstraintIndex, NllMemberConstraint<'tcx>>,
2019-06-05 18:07:15 -05:00
/// Stores the `R1..Rn` regions for *all* sets. For any given
/// constraint, we keep two indices so that we can pull out a
/// slice.
2019-06-18 07:52:23 -05:00
choice_regions: Vec<ty::RegionVid>,
2019-06-05 18:07:15 -05:00
}
2019-06-18 07:52:23 -05:00
/// Represents a `R0 member of [R1..Rn]` constraint
pub(crate) struct NllMemberConstraint<'tcx> {
2019-06-18 07:52:23 -05:00
next_constraint: Option<NllMemberConstraintIndex>,
2019-06-05 18:07:15 -05:00
/// The span where the hidden type was instantiated.
pub(crate) definition_span: Span,
2019-06-24 14:34:37 -05:00
/// The hidden type in which `R0` appears. (Used in error reporting.)
pub(crate) hidden_ty: Ty<'tcx>,
2019-06-05 18:07:15 -05:00
pub(crate) key: ty::OpaqueTypeKey<'tcx>,
2019-06-24 14:34:37 -05:00
/// The region `R0`.
pub(crate) member_region_vid: ty::RegionVid,
2019-06-05 18:07:15 -05:00
2019-06-18 07:52:23 -05:00
/// Index of `R1` in `choice_regions` vector from `MemberConstraintSet`.
2019-06-05 18:07:15 -05:00
start_index: usize,
2019-06-18 07:52:23 -05:00
/// Index of `Rn` in `choice_regions` vector from `MemberConstraintSet`.
2019-06-05 18:07:15 -05:00
end_index: usize,
}
rustc_index::newtype_index! {
pub(crate) struct NllMemberConstraintIndex {
2019-06-18 07:52:23 -05:00
DEBUG_FORMAT = "MemberConstraintIndex({})"
2019-06-05 18:07:15 -05:00
}
}
2021-12-15 01:38:12 -06:00
impl Default for MemberConstraintSet<'_, ty::RegionVid> {
fn default() -> Self {
2019-06-05 18:07:15 -05:00
Self {
first_constraints: Default::default(),
constraints: Default::default(),
2019-06-18 07:52:23 -05:00
choice_regions: Default::default(),
2019-06-05 18:07:15 -05:00
}
}
}
2019-06-05 18:07:15 -05:00
2019-06-18 07:52:23 -05:00
impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> {
2019-06-24 14:34:37 -05:00
/// Pushes a member constraint into the set.
///
/// The input member constraint `m_c` is in the form produced by
2020-09-20 22:14:28 -05:00
/// the `rustc_middle::infer` code.
2019-06-24 14:34:37 -05:00
///
/// The `to_region_vid` callback fn is used to convert the regions
/// within into `RegionVid` format -- it typically consults the
/// `UniversalRegions` data structure that is known to the caller
/// (but which this code is unaware of).
pub(crate) fn push_constraint(
2019-06-05 18:07:15 -05:00
&mut self,
2019-06-18 07:52:23 -05:00
m_c: &MemberConstraint<'tcx>,
2019-06-05 18:07:15 -05:00
mut to_region_vid: impl FnMut(ty::Region<'tcx>) -> ty::RegionVid,
) {
2019-06-18 07:52:23 -05:00
debug!("push_constraint(m_c={:?})", m_c);
let member_region_vid: ty::RegionVid = to_region_vid(m_c.member_region);
let next_constraint = self.first_constraints.get(&member_region_vid).cloned();
let start_index = self.choice_regions.len();
let end_index = start_index + m_c.choice_regions.len();
debug!("push_constraint: member_region_vid={:?}", member_region_vid);
let constraint_index = self.constraints.push(NllMemberConstraint {
2019-06-05 18:07:15 -05:00
next_constraint,
2019-06-18 07:52:23 -05:00
member_region_vid,
definition_span: m_c.definition_span,
hidden_ty: m_c.hidden_ty,
key: m_c.key,
2019-06-05 18:07:15 -05:00
start_index,
end_index,
});
2019-06-18 07:52:23 -05:00
self.first_constraints.insert(member_region_vid, constraint_index);
self.choice_regions.extend(m_c.choice_regions.iter().map(|&r| to_region_vid(r)));
2019-06-05 18:07:15 -05:00
}
}
2021-12-15 01:38:12 -06:00
impl<'tcx, R1> MemberConstraintSet<'tcx, R1>
2019-06-05 18:07:15 -05:00
where
R1: Copy + Hash + Eq,
{
2019-06-18 07:52:23 -05:00
/// Remap the "member region" key using `map_fn`, producing a new
2019-06-24 14:34:37 -05:00
/// member constraint set. This is used in the NLL code to map from
2019-06-05 18:07:15 -05:00
/// the original `RegionVid` to an scc index. In some cases, we
2019-06-24 14:34:37 -05:00
/// may have multiple `R1` values mapping to the same `R2` key -- that
2019-06-05 18:07:15 -05:00
/// is ok, the two sets will be merged.
pub(crate) fn into_mapped<R2>(
2019-06-18 07:52:23 -05:00
self,
mut map_fn: impl FnMut(R1) -> R2,
) -> MemberConstraintSet<'tcx, R2>
2019-06-05 18:07:15 -05:00
where
R2: Copy + Hash + Eq,
{
// We can re-use most of the original data, just tweaking the
// linked list links a bit.
//
2019-06-24 14:34:37 -05:00
// For example if we had two keys `Ra` and `Rb` that both now
// wind up mapped to the same key `S`, we would append the
// linked list for `Ra` onto the end of the linked list for
// `Rb` (or vice versa) -- this basically just requires
2020-03-06 05:13:55 -06:00
// rewriting the final link from one list to point at the other
2019-06-24 14:34:37 -05:00
// other (see `append_list`).
2019-06-05 18:07:15 -05:00
2019-06-18 07:52:23 -05:00
let MemberConstraintSet { first_constraints, mut constraints, choice_regions } = self;
2019-06-05 18:07:15 -05:00
let mut first_constraints2 = FxHashMap::default();
first_constraints2.reserve(first_constraints.len());
for (r1, start1) in first_constraints {
let r2 = map_fn(r1);
if let Some(&start2) = first_constraints2.get(&r2) {
append_list(&mut constraints, start1, start2);
}
first_constraints2.insert(r2, start1);
}
2019-12-22 16:42:04 -06:00
MemberConstraintSet { first_constraints: first_constraints2, constraints, choice_regions }
2019-06-05 18:07:15 -05:00
}
}
2022-05-22 14:48:19 -05:00
impl<'tcx, R> MemberConstraintSet<'tcx, R>
2019-06-05 18:07:15 -05:00
where
R: Copy + Hash + Eq,
{
2022-05-22 14:48:19 -05:00
pub(crate) fn all_indices(
&self,
) -> impl Iterator<Item = NllMemberConstraintIndex> + Captures<'tcx> + '_ {
self.constraints.indices()
}
2019-06-05 18:07:15 -05:00
/// Iterate down the constraint indices associated with a given
2019-06-18 07:52:23 -05:00
/// peek-region. You can then use `choice_regions` and other
2019-06-05 18:07:15 -05:00
/// methods to access data.
pub(crate) fn indices(
2019-06-05 18:07:15 -05:00
&self,
2019-06-18 07:52:23 -05:00
member_region_vid: R,
2022-05-22 14:48:19 -05:00
) -> impl Iterator<Item = NllMemberConstraintIndex> + Captures<'tcx> + '_ {
2019-06-18 07:52:23 -05:00
let mut next = self.first_constraints.get(&member_region_vid).cloned();
std::iter::from_fn(move || -> Option<NllMemberConstraintIndex> {
2019-06-05 18:07:15 -05:00
if let Some(current) = next {
next = self.constraints[current].next_constraint;
Some(current)
} else {
None
}
})
}
2019-06-18 07:52:23 -05:00
/// Returns the "choice regions" for a given member
2019-06-24 14:34:37 -05:00
/// constraint. This is the `R1..Rn` from a constraint like:
2019-06-05 18:07:15 -05:00
///
2022-04-15 17:04:34 -05:00
/// ```text
2019-06-18 07:52:23 -05:00
/// R0 member of [R1..Rn]
2019-06-05 18:07:15 -05:00
/// ```
pub(crate) fn choice_regions(&self, pci: NllMemberConstraintIndex) -> &[ty::RegionVid] {
2019-06-18 07:52:23 -05:00
let NllMemberConstraint { start_index, end_index, .. } = &self.constraints[pci];
&self.choice_regions[*start_index..*end_index]
2019-06-05 18:07:15 -05:00
}
}
2019-06-18 07:52:23 -05:00
impl<'tcx, R> Index<NllMemberConstraintIndex> for MemberConstraintSet<'tcx, R>
2019-06-05 18:07:15 -05:00
where
R: Copy + Eq,
2019-06-05 18:07:15 -05:00
{
2019-06-18 07:52:23 -05:00
type Output = NllMemberConstraint<'tcx>;
2019-06-05 18:07:15 -05:00
2019-06-18 07:52:23 -05:00
fn index(&self, i: NllMemberConstraintIndex) -> &NllMemberConstraint<'tcx> {
2019-06-05 18:07:15 -05:00
&self.constraints[i]
}
}
/// Given a linked list starting at `source_list` and another linked
/// list starting at `target_list`, modify `target_list` so that it is
/// followed by `source_list`.
///
/// Before:
///
2022-04-15 17:04:34 -05:00
/// ```text
2019-06-05 18:07:15 -05:00
/// target_list: A -> B -> C -> (None)
/// source_list: D -> E -> F -> (None)
/// ```
///
/// After:
///
2022-04-15 17:04:34 -05:00
/// ```text
2019-06-05 18:07:15 -05:00
/// target_list: A -> B -> C -> D -> E -> F -> (None)
/// ```
fn append_list(
2019-06-18 07:52:23 -05:00
constraints: &mut IndexVec<NllMemberConstraintIndex, NllMemberConstraint<'_>>,
target_list: NllMemberConstraintIndex,
source_list: NllMemberConstraintIndex,
2019-06-05 18:07:15 -05:00
) {
let mut p = target_list;
loop {
let mut r = &mut constraints[p];
match r.next_constraint {
Some(q) => p = q,
None => {
r.next_constraint = Some(source_list);
return;
}
}
}
}