Skip to main content

rustc_infer/infer/lexical_region_resolve/
indexed_edges.rs

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