diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index 111a62aa6af..b54e05b2b34 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -1,106 +1,13 @@ -use crate::region_infer::RegionDefinition; use crate::type_check::Locations; -use rustc_data_structures::graph::scc::{self, Sccs}; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::ConstraintCategory; -use rustc_middle::ty::{RegionVid, TyCtxt, UniverseIndex, VarianceDiagInfo}; +use rustc_middle::ty::{RegionVid, TyCtxt, VarianceDiagInfo}; use rustc_span::Span; use std::fmt; use std::ops::Index; pub(crate) mod graph; -pub type ConstraintSccs = Sccs; - -/// An annotation for region graph SCCs that tracks -/// the values of its elements. -#[derive(Copy, Debug, Clone)] -pub struct RegionTracker { - /// The largest universe of a placeholder reached from this SCC. - /// This includes placeholders within this SCC. - max_placeholder_universe_reached: UniverseIndex, - - /// The smallest universe index reachable form the nodes of this SCC. - min_reachable_universe: UniverseIndex, - - /// The representative Region Variable Id for this SCC. We prefer - /// placeholders over existentially quantified variables, otherwise - /// it's the one with the smallest Region Variable ID. - pub representative: RegionVid, - - /// Is the current representative a placeholder? - representative_is_placeholder: bool, - - /// Is the current representative existentially quantified? - representative_is_existential: bool, -} - -impl scc::Annotation for RegionTracker { - fn merge_scc(mut self, mut other: Self) -> Self { - // Prefer any placeholder over any existential - if other.representative_is_placeholder && self.representative_is_existential { - other.merge_min_max_seen(&self); - return other; - } - - if self.representative_is_placeholder && other.representative_is_existential - || (self.representative <= other.representative) - { - self.merge_min_max_seen(&other); - return self; - } - other.merge_min_max_seen(&self); - other - } - - fn merge_reached(mut self, other: Self) -> Self { - // No update to in-component values, only add seen values. - self.merge_min_max_seen(&other); - self - } -} - -impl RegionTracker { - pub fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self { - let (representative_is_placeholder, representative_is_existential) = match definition.origin - { - rustc_infer::infer::NllRegionVariableOrigin::FreeRegion => (false, false), - rustc_infer::infer::NllRegionVariableOrigin::Placeholder(_) => (true, false), - rustc_infer::infer::NllRegionVariableOrigin::Existential { .. } => (false, true), - }; - - let placeholder_universe = - if representative_is_placeholder { definition.universe } else { UniverseIndex::ROOT }; - - Self { - max_placeholder_universe_reached: placeholder_universe, - min_reachable_universe: definition.universe, - representative: rvid, - representative_is_placeholder, - representative_is_existential, - } - } - pub fn universe(self) -> UniverseIndex { - self.min_reachable_universe - } - - fn merge_min_max_seen(&mut self, other: &Self) { - self.max_placeholder_universe_reached = std::cmp::max( - self.max_placeholder_universe_reached, - other.max_placeholder_universe_reached, - ); - - self.min_reachable_universe = - std::cmp::min(self.min_reachable_universe, other.min_reachable_universe); - } - - /// Returns `true` if during the annotated SCC reaches a placeholder - /// with a universe larger than the smallest reachable one, `false` otherwise. - pub fn has_incompatible_universes(&self) -> bool { - self.universe().cannot_name(self.max_placeholder_universe_reached) - } -} - /// A set of NLL region constraints. These include "outlives" /// constraints of the form `R1: R2`. Each constraint is identified by /// a unique `OutlivesConstraintIndex` and you can index into the set diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 6f2fe8bddb2..971f5a2a7ec 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -4,6 +4,7 @@ use rustc_data_structures::binary_search_util; use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::graph::scc::{self, Sccs}; use rustc_errors::Diag; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_index::IndexVec; @@ -23,7 +24,6 @@ use rustc_span::Span; use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph}; -use crate::constraints::{ConstraintSccs, RegionTracker}; use crate::dataflow::BorrowIndex; use crate::{ constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet}, @@ -46,6 +46,97 @@ pub mod values; +pub type ConstraintSccs = Sccs; + +/// An annotation for region graph SCCs that tracks +/// the values of its elements. +#[derive(Copy, Debug, Clone)] +pub struct RegionTracker { + /// The largest universe of a placeholder reached from this SCC. + /// This includes placeholders within this SCC. + max_placeholder_universe_reached: UniverseIndex, + + /// The smallest universe index reachable form the nodes of this SCC. + min_reachable_universe: UniverseIndex, + + /// The representative Region Variable Id for this SCC. We prefer + /// placeholders over existentially quantified variables, otherwise + /// it's the one with the smallest Region Variable ID. + representative: RegionVid, + + /// Is the current representative a placeholder? + representative_is_placeholder: bool, + + /// Is the current representative existentially quantified? + representative_is_existential: bool, +} + +impl scc::Annotation for RegionTracker { + fn merge_scc(mut self, mut other: Self) -> Self { + // Prefer any placeholder over any existential + if other.representative_is_placeholder && self.representative_is_existential { + other.merge_min_max_seen(&self); + return other; + } + + if self.representative_is_placeholder && other.representative_is_existential + || (self.representative <= other.representative) + { + self.merge_min_max_seen(&other); + return self; + } + other.merge_min_max_seen(&self); + other + } + + fn merge_reached(mut self, other: Self) -> Self { + // No update to in-component values, only add seen values. + self.merge_min_max_seen(&other); + self + } +} + +impl RegionTracker { + fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self { + let (representative_is_placeholder, representative_is_existential) = match definition.origin + { + rustc_infer::infer::NllRegionVariableOrigin::FreeRegion => (false, false), + rustc_infer::infer::NllRegionVariableOrigin::Placeholder(_) => (true, false), + rustc_infer::infer::NllRegionVariableOrigin::Existential { .. } => (false, true), + }; + + let placeholder_universe = + if representative_is_placeholder { definition.universe } else { UniverseIndex::ROOT }; + + Self { + max_placeholder_universe_reached: placeholder_universe, + min_reachable_universe: definition.universe, + representative: rvid, + representative_is_placeholder, + representative_is_existential, + } + } + fn universe(self) -> UniverseIndex { + self.min_reachable_universe + } + + fn merge_min_max_seen(&mut self, other: &Self) { + self.max_placeholder_universe_reached = std::cmp::max( + self.max_placeholder_universe_reached, + other.max_placeholder_universe_reached, + ); + + self.min_reachable_universe = + std::cmp::min(self.min_reachable_universe, other.min_reachable_universe); + } + + /// Returns `true` if during the annotated SCC reaches a placeholder + /// with a universe larger than the smallest reachable one, `false` otherwise. + pub fn has_incompatible_universes(&self) -> bool { + self.universe().cannot_name(self.max_placeholder_universe_reached) + } +} + pub struct RegionInferenceContext<'tcx> { pub var_infos: VarInfos,