|
1 |
| -use rustc_data_structures::graph::scc::Sccs; |
| 1 | +use crate::region_infer::RegionDefinition; |
| 2 | +use crate::type_check::Locations; |
| 3 | +use rustc_data_structures::graph::scc::{self, Sccs}; |
2 | 4 | use rustc_index::{IndexSlice, IndexVec};
|
3 | 5 | use rustc_middle::mir::ConstraintCategory;
|
4 |
| -use rustc_middle::ty::{RegionVid, VarianceDiagInfo}; |
| 6 | +use rustc_middle::ty::{RegionVid, UniverseIndex, VarianceDiagInfo}; |
5 | 7 | use rustc_span::Span;
|
6 | 8 | use std::fmt;
|
7 | 9 | use std::ops::Index;
|
8 | 10 |
|
9 |
| -use crate::type_check::Locations; |
10 |
| - |
11 | 11 | pub(crate) mod graph;
|
12 | 12 |
|
| 13 | +pub type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex, RegionTracker>; |
| 14 | + |
| 15 | +/// An annotation for region graph SCCs that tracks |
| 16 | +/// the values of its elements. |
| 17 | +#[derive(Copy, Debug, Clone)] |
| 18 | +pub struct RegionTracker { |
| 19 | + /// The largest universe of a placeholder reached from this SCC. |
| 20 | + /// This includes placeholders within this SCC. |
| 21 | + max_placeholder_universe_reached: UniverseIndex, |
| 22 | + |
| 23 | + /// The smallest universe index reachable form the nodes of this SCC. |
| 24 | + min_reachable_universe: UniverseIndex, |
| 25 | + |
| 26 | + /// The representative Region Variable Id for this SCC. We prefer |
| 27 | + /// placeholders over existentially quantified variables, otherwise |
| 28 | + /// it's the one with the smallest Region Variable ID. |
| 29 | + pub representative: RegionVid, |
| 30 | + |
| 31 | + /// Is the current representative a placeholder? |
| 32 | + representative_is_placeholder: bool, |
| 33 | + |
| 34 | + /// Is the current representative existentially quantified? |
| 35 | + representative_is_existential: bool, |
| 36 | +} |
| 37 | + |
| 38 | +impl scc::Annotation for RegionTracker { |
| 39 | + fn merge_scc(mut self, mut other: Self) -> Self { |
| 40 | + // Prefer any placeholder over any existential |
| 41 | + if other.representative_is_placeholder && self.representative_is_existential { |
| 42 | + other.merge_min_max_seen(&self); |
| 43 | + return other; |
| 44 | + } |
| 45 | + |
| 46 | + if self.representative_is_placeholder && other.representative_is_existential |
| 47 | + || (self.representative <= other.representative) |
| 48 | + { |
| 49 | + self.merge_min_max_seen(&other); |
| 50 | + return self; |
| 51 | + } |
| 52 | + other.merge_min_max_seen(&self); |
| 53 | + other |
| 54 | + } |
| 55 | + |
| 56 | + fn merge_reached(mut self, other: Self) -> Self { |
| 57 | + // No update to in-component values, only add seen values. |
| 58 | + self.merge_min_max_seen(&other); |
| 59 | + self |
| 60 | + } |
| 61 | +} |
| 62 | + |
| 63 | +impl RegionTracker { |
| 64 | + pub fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self { |
| 65 | + let (representative_is_placeholder, representative_is_existential) = match definition.origin |
| 66 | + { |
| 67 | + rustc_infer::infer::NllRegionVariableOrigin::FreeRegion => (false, false), |
| 68 | + rustc_infer::infer::NllRegionVariableOrigin::Placeholder(_) => (true, false), |
| 69 | + rustc_infer::infer::NllRegionVariableOrigin::Existential { .. } => (false, true), |
| 70 | + }; |
| 71 | + |
| 72 | + let placeholder_universe = |
| 73 | + if representative_is_placeholder { definition.universe } else { UniverseIndex::ROOT }; |
| 74 | + |
| 75 | + Self { |
| 76 | + max_placeholder_universe_reached: placeholder_universe, |
| 77 | + min_reachable_universe: definition.universe, |
| 78 | + representative: rvid, |
| 79 | + representative_is_placeholder, |
| 80 | + representative_is_existential, |
| 81 | + } |
| 82 | + } |
| 83 | + pub fn universe(self) -> UniverseIndex { |
| 84 | + self.min_reachable_universe |
| 85 | + } |
| 86 | + |
| 87 | + fn merge_min_max_seen(&mut self, other: &Self) { |
| 88 | + self.max_placeholder_universe_reached = std::cmp::max( |
| 89 | + self.max_placeholder_universe_reached, |
| 90 | + other.max_placeholder_universe_reached, |
| 91 | + ); |
| 92 | + |
| 93 | + self.min_reachable_universe = |
| 94 | + std::cmp::min(self.min_reachable_universe, other.min_reachable_universe); |
| 95 | + } |
| 96 | + |
| 97 | + /// Returns `true` if during the annotated SCC reaches a placeholder |
| 98 | + /// with a universe larger than the smallest reachable one, `false` otherwise. |
| 99 | + pub fn has_incompatible_universes(&self) -> bool { |
| 100 | + self.universe().cannot_name(self.max_placeholder_universe_reached) |
| 101 | + } |
| 102 | +} |
| 103 | + |
13 | 104 | /// A set of NLL region constraints. These include "outlives"
|
14 | 105 | /// constraints of the form `R1: R2`. Each constraint is identified by
|
15 | 106 | /// a unique `OutlivesConstraintIndex` and you can index into the set
|
@@ -45,18 +136,6 @@ impl<'tcx> OutlivesConstraintSet<'tcx> {
|
45 | 136 | graph::ConstraintGraph::new(graph::Reverse, self, num_region_vars)
|
46 | 137 | }
|
47 | 138 |
|
48 |
| - /// Computes cycles (SCCs) in the graph of regions. In particular, |
49 |
| - /// find all regions R1, R2 such that R1: R2 and R2: R1 and group |
50 |
| - /// them into an SCC, and find the relationships between SCCs. |
51 |
| - pub(crate) fn compute_sccs( |
52 |
| - &self, |
53 |
| - constraint_graph: &graph::NormalConstraintGraph, |
54 |
| - static_region: RegionVid, |
55 |
| - ) -> Sccs<RegionVid, ConstraintSccIndex> { |
56 |
| - let region_graph = &constraint_graph.region_graph(self, static_region); |
57 |
| - Sccs::new(region_graph) |
58 |
| - } |
59 |
| - |
60 | 139 | pub(crate) fn outlives(
|
61 | 140 | &self,
|
62 | 141 | ) -> &IndexSlice<OutlivesConstraintIndex, OutlivesConstraint<'tcx>> {
|
|
0 commit comments