Skip to main content

rustc_infer/infer/lexical_region_resolve/
indexed_edges.rs

1use rustc_index::IndexVec;
2use rustc_middle::ty::RegionUtilitiesExt;
3use rustc_type_ir::RegionVid;
4
5use crate::infer::SubregionOrigin;
6use crate::infer::region_constraints::{Constraint, ConstraintKind, RegionConstraintData};
7
8/// Selects either out-edges or in-edges for [`IndexedConstraintEdges::adjacent_edges`].
9#[derive(#[automatically_derived]
impl ::core::clone::Clone for EdgeDirection {
    #[inline]
    fn clone(&self) -> EdgeDirection { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for EdgeDirection { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for EdgeDirection {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                EdgeDirection::Out => "Out",
                EdgeDirection::In => "In",
            })
    }
}Debug)]
10pub(super) enum EdgeDirection {
11    Out,
12    In,
13}
14
15/// Type alias for the pairs stored in [`RegionConstraintData::constraints`],
16/// which we are indexing.
17type ConstraintPair<'data, 'tcx> = (Constraint<'tcx>, &'data SubregionOrigin<'tcx>);
18
19/// An index from region variables to their corresponding constraint edges,
20/// used on some error paths.
21pub(super) struct IndexedConstraintEdges<'data, 'tcx> {
22    out_edges: IndexVec<RegionVid, Vec<ConstraintPair<'data, 'tcx>>>,
23    in_edges: IndexVec<RegionVid, Vec<ConstraintPair<'data, 'tcx>>>,
24}
25
26impl<'data, 'tcx> IndexedConstraintEdges<'data, 'tcx> {
27    pub(super) fn build_index(num_vars: usize, data: &'data RegionConstraintData<'tcx>) -> Self {
28        let mut out_edges = IndexVec::from_fn_n(|_| ::alloc::vec::Vec::new()vec![], num_vars);
29        let mut in_edges = IndexVec::from_fn_n(|_| ::alloc::vec::Vec::new()vec![], num_vars);
30
31        for pair @ (c, _) in data
32            .constraints
33            .iter()
34            .flat_map(|(c, origin)| c.iter_outlives().map(move |c| (c, origin)))
35        {
36            // Only push a var out-edge for `VarSub...` constraints.
37            match c.kind {
38                ConstraintKind::VarSubVar | ConstraintKind::VarSubReg => {
39                    out_edges[c.sub.as_var()].push(pair);
40                }
41
42                ConstraintKind::RegSubVar | ConstraintKind::RegSubReg => {}
43
44                ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => {
45                    ::core::panicking::panic("internal error: entered unreachable code");unreachable!();
46                }
47            }
48        }
49
50        // FIXME: We should merge this loop with the above one eventually.
51        // Index in-edges in reverse order, to match what current tests expect.
52        // (It's unclear whether this is important or not.)
53
54        for pair @ (c, _) in data
55            .constraints
56            .iter()
57            .rev()
58            .flat_map(|(c, origin)| c.iter_outlives().map(move |c| (c, origin)))
59        {
60            // Only push a var in-edge for `...SubVar` constraints.
61            match c.kind {
62                ConstraintKind::VarSubVar | ConstraintKind::RegSubVar => {
63                    in_edges[c.sup.as_var()].push(pair);
64                }
65
66                ConstraintKind::VarSubReg | ConstraintKind::RegSubReg => {}
67
68                ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => {
69                    ::core::panicking::panic("internal error: entered unreachable code");unreachable!();
70                }
71            }
72        }
73
74        IndexedConstraintEdges { out_edges, in_edges }
75    }
76
77    /// Returns either the out-edges or in-edges of the specified region var,
78    /// as selected by `dir`.
79    pub(super) fn adjacent_edges(
80        &self,
81        region_vid: RegionVid,
82        dir: EdgeDirection,
83    ) -> &[ConstraintPair<'data, 'tcx>] {
84        let edges = match dir {
85            EdgeDirection::Out => &self.out_edges,
86            EdgeDirection::In => &self.in_edges,
87        };
88        &edges[region_vid]
89    }
90}