]>
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; |
dfeec247 | 5 | use rustc_index::vec::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. | |
8faf50e0 | 20 | #[derive(Clone, 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 | |
923072b8 | 63 | pub(crate) fn outlives(&self) -> &IndexVec<OutlivesConstraintIndex, OutlivesConstraint<'tcx>> { |
dc9dc135 XL |
64 | &self.outlives |
65 | } | |
8faf50e0 XL |
66 | } |
67 | ||
17df50a5 XL |
68 | impl<'tcx> Index<OutlivesConstraintIndex> for OutlivesConstraintSet<'tcx> { |
69 | type Output = OutlivesConstraint<'tcx>; | |
8faf50e0 | 70 | |
dc9dc135 XL |
71 | fn index(&self, i: OutlivesConstraintIndex) -> &Self::Output { |
72 | &self.outlives[i] | |
8faf50e0 XL |
73 | } |
74 | } | |
75 | ||
f2b60f7d | 76 | #[derive(Copy, Clone, PartialEq, Eq)] |
17df50a5 | 77 | pub struct OutlivesConstraint<'tcx> { |
8faf50e0 XL |
78 | // NB. The ordering here is not significant for correctness, but |
79 | // it is for convenience. Before we dump the constraints in the | |
80 | // debugging logs, we sort them, and we'd like the "super region" | |
81 | // to be first, etc. (In particular, span should remain last.) | |
82 | /// The region SUP must outlive SUB... | |
83 | pub sup: RegionVid, | |
84 | ||
85 | /// Region that must be outlived. | |
86 | pub sub: RegionVid, | |
87 | ||
88 | /// Where did this constraint arise? | |
89 | pub locations: Locations, | |
0bf4aa26 | 90 | |
04454e1e FG |
91 | /// The `Span` associated with the creation of this constraint. |
92 | /// This should be used in preference to obtaining the span from | |
93 | /// `locations`, since the `locations` may give a poor span | |
94 | /// in some cases (e.g. converting a constraint from a promoted). | |
95 | pub span: Span, | |
96 | ||
0bf4aa26 | 97 | /// What caused this constraint? |
923072b8 | 98 | pub category: ConstraintCategory<'tcx>, |
17df50a5 XL |
99 | |
100 | /// Variance diagnostic information | |
101 | pub variance_info: VarianceDiagInfo<'tcx>, | |
487cf647 FG |
102 | |
103 | /// If this constraint is promoted from closure requirements. | |
104 | pub from_closure: bool, | |
8faf50e0 XL |
105 | } |
106 | ||
17df50a5 | 107 | impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> { |
9fa01778 | 108 | fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { |
17df50a5 XL |
109 | write!( |
110 | formatter, | |
f2b60f7d FG |
111 | "({:?}: {:?}) due to {:?} ({:?}) ({:?})", |
112 | self.sup, self.sub, self.locations, self.variance_info, self.category, | |
17df50a5 | 113 | ) |
8faf50e0 XL |
114 | } |
115 | } | |
116 | ||
e74abb32 | 117 | rustc_index::newtype_index! { |
dc9dc135 XL |
118 | pub struct OutlivesConstraintIndex { |
119 | DEBUG_FORMAT = "OutlivesConstraintIndex({})" | |
b7449926 XL |
120 | } |
121 | } | |
8faf50e0 | 122 | |
e74abb32 | 123 | rustc_index::newtype_index! { |
b7449926 XL |
124 | pub struct ConstraintSccIndex { |
125 | DEBUG_FORMAT = "ConstraintSccIndex({})" | |
126 | } | |
127 | } |