]>
Commit | Line | Data |
---|---|---|
487cf647 FG |
1 | #![deny(rustc::untranslatable_diagnostic)] |
2 | #![deny(rustc::diagnostic_outside_of_impl)] | |
3 | ||
8faf50e0 | 4 | use rustc_data_structures::graph::scc::Sccs; |
353b0b11 | 5 | use rustc_index::vec::{IndexSlice, IndexVec}; |
ba9703b0 | 6 | use rustc_middle::mir::ConstraintCategory; |
17df50a5 | 7 | use rustc_middle::ty::{RegionVid, VarianceDiagInfo}; |
04454e1e | 8 | use rustc_span::Span; |
8faf50e0 | 9 | use std::fmt; |
dc9dc135 | 10 | use std::ops::Index; |
8faf50e0 | 11 | |
c295e0f8 | 12 | use crate::type_check::Locations; |
60c5eb7d | 13 | |
923072b8 | 14 | pub(crate) mod graph; |
8faf50e0 | 15 | |
dc9dc135 XL |
16 | /// A set of NLL region constraints. These include "outlives" |
17 | /// constraints of the form `R1: R2`. Each constraint is identified by | |
18 | /// a unique `OutlivesConstraintIndex` and you can index into the set | |
19 | /// (`constraint_set[i]`) to access the constraint details. | |
9ffffee4 | 20 | #[derive(Clone, Debug, Default)] |
923072b8 | 21 | pub(crate) struct OutlivesConstraintSet<'tcx> { |
17df50a5 | 22 | outlives: IndexVec<OutlivesConstraintIndex, OutlivesConstraint<'tcx>>, |
8faf50e0 XL |
23 | } |
24 | ||
17df50a5 | 25 | impl<'tcx> OutlivesConstraintSet<'tcx> { |
923072b8 | 26 | pub(crate) fn push(&mut self, constraint: OutlivesConstraint<'tcx>) { |
f2b60f7d | 27 | debug!("OutlivesConstraintSet::push({:?})", constraint); |
8faf50e0 XL |
28 | if constraint.sup == constraint.sub { |
29 | // 'a: 'a is pretty uninteresting | |
30 | return; | |
31 | } | |
dc9dc135 | 32 | self.outlives.push(constraint); |
8faf50e0 XL |
33 | } |
34 | ||
b7449926 XL |
35 | /// Constructs a "normal" graph from the constraint set; the graph makes it |
36 | /// easy to find the constraints affecting a particular region. | |
37 | /// | |
0731742a | 38 | /// N.B., this graph contains a "frozen" view of the current |
dc9dc135 | 39 | /// constraints. Any new constraints added to the `OutlivesConstraintSet` |
b7449926 | 40 | /// after the graph is built will not be present in the graph. |
923072b8 | 41 | pub(crate) fn graph(&self, num_region_vars: usize) -> graph::NormalConstraintGraph { |
b7449926 XL |
42 | graph::ConstraintGraph::new(graph::Normal, self, num_region_vars) |
43 | } | |
44 | ||
45 | /// Like `graph`, but constraints a reverse graph where `R1: R2` | |
46 | /// represents an edge `R2 -> R1`. | |
923072b8 | 47 | pub(crate) fn reverse_graph(&self, num_region_vars: usize) -> graph::ReverseConstraintGraph { |
b7449926 | 48 | graph::ConstraintGraph::new(graph::Reverse, self, num_region_vars) |
8faf50e0 XL |
49 | } |
50 | ||
9fa01778 | 51 | /// Computes cycles (SCCs) in the graph of regions. In particular, |
8faf50e0 XL |
52 | /// find all regions R1, R2 such that R1: R2 and R2: R1 and group |
53 | /// them into an SCC, and find the relationships between SCCs. | |
923072b8 | 54 | pub(crate) fn compute_sccs( |
8faf50e0 | 55 | &self, |
b7449926 XL |
56 | constraint_graph: &graph::NormalConstraintGraph, |
57 | static_region: RegionVid, | |
8faf50e0 | 58 | ) -> Sccs<RegionVid, ConstraintSccIndex> { |
b7449926 | 59 | let region_graph = &constraint_graph.region_graph(self, static_region); |
8faf50e0 XL |
60 | Sccs::new(region_graph) |
61 | } | |
dc9dc135 | 62 | |
353b0b11 FG |
63 | pub(crate) fn outlives( |
64 | &self, | |
65 | ) -> &IndexSlice<OutlivesConstraintIndex, OutlivesConstraint<'tcx>> { | |
dc9dc135 XL |
66 | &self.outlives |
67 | } | |
8faf50e0 XL |
68 | } |
69 | ||
17df50a5 XL |
70 | impl<'tcx> Index<OutlivesConstraintIndex> for OutlivesConstraintSet<'tcx> { |
71 | type Output = OutlivesConstraint<'tcx>; | |
8faf50e0 | 72 | |
dc9dc135 XL |
73 | fn index(&self, i: OutlivesConstraintIndex) -> &Self::Output { |
74 | &self.outlives[i] | |
8faf50e0 XL |
75 | } |
76 | } | |
77 | ||
f2b60f7d | 78 | #[derive(Copy, Clone, PartialEq, Eq)] |
17df50a5 | 79 | pub struct OutlivesConstraint<'tcx> { |
8faf50e0 XL |
80 | // NB. The ordering here is not significant for correctness, but |
81 | // it is for convenience. Before we dump the constraints in the | |
82 | // debugging logs, we sort them, and we'd like the "super region" | |
83 | // to be first, etc. (In particular, span should remain last.) | |
84 | /// The region SUP must outlive SUB... | |
85 | pub sup: RegionVid, | |
86 | ||
87 | /// Region that must be outlived. | |
88 | pub sub: RegionVid, | |
89 | ||
90 | /// Where did this constraint arise? | |
91 | pub locations: Locations, | |
0bf4aa26 | 92 | |
04454e1e FG |
93 | /// The `Span` associated with the creation of this constraint. |
94 | /// This should be used in preference to obtaining the span from | |
95 | /// `locations`, since the `locations` may give a poor span | |
96 | /// in some cases (e.g. converting a constraint from a promoted). | |
97 | pub span: Span, | |
98 | ||
0bf4aa26 | 99 | /// What caused this constraint? |
923072b8 | 100 | pub category: ConstraintCategory<'tcx>, |
17df50a5 XL |
101 | |
102 | /// Variance diagnostic information | |
103 | pub variance_info: VarianceDiagInfo<'tcx>, | |
487cf647 FG |
104 | |
105 | /// If this constraint is promoted from closure requirements. | |
106 | pub from_closure: bool, | |
8faf50e0 XL |
107 | } |
108 | ||
17df50a5 | 109 | impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> { |
9fa01778 | 110 | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { |
17df50a5 XL |
111 | write!( |
112 | formatter, | |
f2b60f7d FG |
113 | "({:?}: {:?}) due to {:?} ({:?}) ({:?})", |
114 | self.sup, self.sub, self.locations, self.variance_info, self.category, | |
17df50a5 | 115 | ) |
8faf50e0 XL |
116 | } |
117 | } | |
118 | ||
e74abb32 | 119 | rustc_index::newtype_index! { |
9c376795 FG |
120 | #[debug_format = "OutlivesConstraintIndex({})"] |
121 | pub struct OutlivesConstraintIndex {} | |
b7449926 | 122 | } |
8faf50e0 | 123 | |
e74abb32 | 124 | rustc_index::newtype_index! { |
9c376795 FG |
125 | #[debug_format = "ConstraintSccIndex({})"] |
126 | pub struct ConstraintSccIndex {} | |
b7449926 | 127 | } |