Use an enum for SCC representatives, plus other code review
Co-authored-by: lcnr <rust@lcnr.de>
This commit is contained in:
parent
aca36fd12a
commit
f455c4fc39
7 changed files with 131 additions and 136 deletions
|
|
@ -1,14 +1,13 @@
|
|||
//! Logic for lowering higher-kinded outlives constraints
|
||||
//! (with placeholders and universes) and turn them into regular
|
||||
//! outlives constraints.
|
||||
//!
|
||||
//! This logic is provisional and should be removed once the trait
|
||||
//! solver can handle this kind of constraint.
|
||||
|
||||
use rustc_data_structures::frozen::Frozen;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::graph::scc;
|
||||
use rustc_data_structures::graph::scc::Sccs;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_infer::infer::RegionVariableOrigin;
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::{RegionVid, UniverseIndex};
|
||||
use tracing::debug;
|
||||
|
|
@ -18,7 +17,7 @@ use crate::consumers::OutlivesConstraint;
|
|||
use crate::diagnostics::UniverseInfo;
|
||||
use crate::member_constraints::MemberConstraintSet;
|
||||
use crate::region_infer::values::{LivenessValues, PlaceholderIndices};
|
||||
use crate::region_infer::{ConstraintSccs, RegionDefinition, TypeTest};
|
||||
use crate::region_infer::{ConstraintSccs, RegionDefinition, Representative, TypeTest};
|
||||
use crate::ty::VarianceDiagInfo;
|
||||
use crate::type_check::free_region_relations::UniversalRegionRelations;
|
||||
use crate::type_check::{Locations, MirTypeckRegionConstraints};
|
||||
|
|
@ -32,7 +31,7 @@ pub(crate) struct LoweredConstraints<'tcx> {
|
|||
pub(crate) definitions: Frozen<IndexVec<RegionVid, RegionDefinition<'tcx>>>,
|
||||
pub(crate) scc_annotations: IndexVec<ConstraintSccIndex, RegionTracker>,
|
||||
pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
|
||||
pub(crate) outlives_constraints: OutlivesConstraintSet<'tcx>,
|
||||
pub(crate) outlives_constraints: Frozen<OutlivesConstraintSet<'tcx>>,
|
||||
pub(crate) type_tests: Vec<TypeTest<'tcx>>,
|
||||
pub(crate) liveness_constraints: LivenessValues,
|
||||
pub(crate) universe_causes: FxIndexMap<UniverseIndex, UniverseInfo<'tcx>>,
|
||||
|
|
@ -73,45 +72,35 @@ pub(crate) struct RegionTracker {
|
|||
/// 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 largest universe nameable from this SCC.
|
||||
/// It is the smallest nameable universes of all
|
||||
/// existential regions reachable from it.
|
||||
max_nameable_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(crate) representative: RegionVid,
|
||||
|
||||
/// Is the current representative a placeholder?
|
||||
representative_is_placeholder: bool,
|
||||
|
||||
/// Is the current representative existentially quantified?
|
||||
representative_is_existential: bool,
|
||||
/// The representative Region Variable Id for this SCC.
|
||||
pub(crate) representative: Representative,
|
||||
}
|
||||
|
||||
impl RegionTracker {
|
||||
pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
|
||||
let (representative_is_placeholder, representative_is_existential) = match definition.origin
|
||||
{
|
||||
NllRegionVariableOrigin::FreeRegion => (false, false),
|
||||
NllRegionVariableOrigin::Placeholder(_) => (true, false),
|
||||
NllRegionVariableOrigin::Existential { .. } => (false, true),
|
||||
};
|
||||
|
||||
let placeholder_universe =
|
||||
if representative_is_placeholder { definition.universe } else { UniverseIndex::ROOT };
|
||||
if matches!(definition.origin, NllRegionVariableOrigin::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,
|
||||
max_nameable_universe: definition.universe,
|
||||
representative: Representative::new(rvid, definition),
|
||||
}
|
||||
}
|
||||
|
||||
/// The smallest-indexed universe reachable from and/or in this SCC.
|
||||
pub(crate) fn min_universe(self) -> UniverseIndex {
|
||||
self.min_reachable_universe
|
||||
/// The largest universe this SCC can name. It's the smallest
|
||||
/// largest nameable uninverse of any reachable region.
|
||||
pub(crate) fn max_nameable_universe(self) -> UniverseIndex {
|
||||
self.max_nameable_universe
|
||||
}
|
||||
|
||||
fn merge_min_max_seen(&mut self, other: &Self) {
|
||||
|
|
@ -120,40 +109,29 @@ impl RegionTracker {
|
|||
other.max_placeholder_universe_reached,
|
||||
);
|
||||
|
||||
self.min_reachable_universe =
|
||||
std::cmp::min(self.min_reachable_universe, other.min_reachable_universe);
|
||||
self.max_nameable_universe =
|
||||
std::cmp::min(self.max_nameable_universe, other.max_nameable_universe);
|
||||
}
|
||||
|
||||
/// Returns `true` if during the annotated SCC reaches a placeholder
|
||||
/// with a universe larger than the smallest reachable one, `false` otherwise.
|
||||
/// with a universe larger than the smallest nameable universe of any
|
||||
/// reachable existential region.
|
||||
pub(crate) fn has_incompatible_universes(&self) -> bool {
|
||||
self.min_universe().cannot_name(self.max_placeholder_universe_reached)
|
||||
self.max_nameable_universe().cannot_name(self.max_placeholder_universe_reached)
|
||||
}
|
||||
|
||||
/// Determine if the tracked universes of the two SCCs
|
||||
/// are compatible.
|
||||
/// Determine if the tracked universes of the two SCCs are compatible.
|
||||
pub(crate) fn universe_compatible_with(&self, other: Self) -> bool {
|
||||
self.min_universe().can_name(other.min_universe())
|
||||
|| self.min_universe().can_name(other.max_placeholder_universe_reached)
|
||||
self.max_nameable_universe().can_name(other.max_nameable_universe())
|
||||
|| self.max_nameable_universe().can_name(other.max_placeholder_universe_reached)
|
||||
}
|
||||
}
|
||||
|
||||
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_scc(mut self, other: Self) -> Self {
|
||||
self.representative = self.representative.merge_scc(other.representative);
|
||||
self.merge_min_max_seen(&other);
|
||||
self
|
||||
}
|
||||
|
||||
fn merge_reached(mut self, other: Self) -> Self {
|
||||
|
|
@ -164,7 +142,7 @@ impl scc::Annotation for RegionTracker {
|
|||
}
|
||||
|
||||
/// Determines if the region variable definitions contain
|
||||
/// placeholers, and compute them for later use.
|
||||
/// placeholders, and compute them for later use.
|
||||
fn region_definitions<'tcx>(
|
||||
universal_regions: &UniversalRegions<'tcx>,
|
||||
infcx: &BorrowckInferCtxt<'tcx>,
|
||||
|
|
@ -177,12 +155,19 @@ fn region_definitions<'tcx>(
|
|||
let mut has_placeholders = false;
|
||||
|
||||
for info in var_infos.iter() {
|
||||
let definition = RegionDefinition::new(info);
|
||||
has_placeholders |= matches!(definition.origin, NllRegionVariableOrigin::Placeholder(_));
|
||||
let origin = match info.origin {
|
||||
RegionVariableOrigin::Nll(origin) => origin,
|
||||
_ => NllRegionVariableOrigin::Existential { from_forall: false },
|
||||
};
|
||||
|
||||
let definition = RegionDefinition { origin, universe: info.universe, external_name: None };
|
||||
|
||||
has_placeholders |= matches!(origin, NllRegionVariableOrigin::Placeholder(_));
|
||||
definitions.push(definition);
|
||||
}
|
||||
|
||||
// Add external names from universal regions in fun function definitions.
|
||||
// FIXME: this two-step method is annoying, but I don't know how to avoid it.
|
||||
for (external_name, variable) in universal_regions.named_universal_regions_iter() {
|
||||
debug!("region {:?} has external name {:?}", variable, external_name);
|
||||
definitions[variable].external_name = Some(external_name);
|
||||
|
|
@ -190,29 +175,19 @@ fn region_definitions<'tcx>(
|
|||
(Frozen::freeze(definitions), has_placeholders)
|
||||
}
|
||||
|
||||
/// This method handles Universe errors by rewriting the constraint
|
||||
/// This method handles placeholders by rewriting the constraint
|
||||
/// graph. For each strongly connected component in the constraint
|
||||
/// graph such that there is a series of constraints
|
||||
/// A: B: C: ... : X where
|
||||
/// A's universe is smaller than X's and A is a placeholder,
|
||||
/// A contains a placeholder whose universe cannot be named by X,
|
||||
/// add a constraint that A: 'static. This is a safe upper bound
|
||||
/// in the face of borrow checker/trait solver limitations that will
|
||||
/// eventually go away.
|
||||
///
|
||||
/// For a more precise definition, see the documentation for
|
||||
/// [`RegionTracker`] and its methods!.
|
||||
///
|
||||
/// Since universes can also be involved in errors (if one placeholder
|
||||
/// transitively outlives another), this function also flags those.
|
||||
///
|
||||
/// Additionally, it similarly rewrites type-tests.
|
||||
///
|
||||
/// This edge case used to be handled during constraint propagation
|
||||
/// by iterating over the strongly connected components in the constraint
|
||||
/// graph while maintaining a set of bookkeeping mappings similar
|
||||
/// to what is stored in `RegionTracker` and manually adding 'sttaic as
|
||||
/// needed.
|
||||
/// [`RegionTracker`] and its methods!
|
||||
///
|
||||
/// This edge case used to be handled during constraint propagation.
|
||||
/// It was rewritten as part of the Polonius project with the goal of moving
|
||||
/// higher-kindedness concerns out of the path of the borrow checker,
|
||||
/// for two reasons:
|
||||
|
|
@ -228,7 +203,7 @@ fn region_definitions<'tcx>(
|
|||
/// This code is a stop-gap measure in preparation for the future trait solver.
|
||||
///
|
||||
/// Every constraint added by this method is an internal `IllegalUniverse` constraint.
|
||||
pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
|
||||
pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
|
||||
constraints: MirTypeckRegionConstraints<'tcx>,
|
||||
universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
|
||||
infcx: &BorrowckInferCtxt<'tcx>,
|
||||
|
|
@ -267,13 +242,14 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
|
|||
)
|
||||
};
|
||||
|
||||
let mut scc_annotations = SccAnnotations::init(&definitions);
|
||||
let constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
|
||||
|
||||
// This code structure is a bit convoluted because it allows for a planned
|
||||
// future change where the early return here has a different type of annotation
|
||||
// that does much less work.
|
||||
if !has_placeholders {
|
||||
debug!("No placeholder regions found; skipping rewriting logic!");
|
||||
let mut scc_annotations = SccAnnotations::init(&definitions);
|
||||
let constraint_sccs = compute_sccs(&outlives_constraints, &mut scc_annotations);
|
||||
|
||||
return LoweredConstraints {
|
||||
type_tests,
|
||||
|
|
@ -281,7 +257,7 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
|
|||
constraint_sccs,
|
||||
scc_annotations: scc_annotations.scc_to_annotation,
|
||||
definitions,
|
||||
outlives_constraints,
|
||||
outlives_constraints: Frozen::freeze(outlives_constraints),
|
||||
liveness_constraints,
|
||||
universe_causes,
|
||||
placeholder_indices,
|
||||
|
|
@ -289,14 +265,14 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
|
|||
}
|
||||
debug!("Placeholders present; activating placeholder handling logic!");
|
||||
|
||||
let mut annotations = SccAnnotations::init(&definitions);
|
||||
let sccs = compute_sccs(&outlives_constraints, &mut annotations);
|
||||
let added_constraints = rewrite_placeholder_outlives(
|
||||
&constraint_sccs,
|
||||
&scc_annotations,
|
||||
fr_static,
|
||||
&mut outlives_constraints,
|
||||
);
|
||||
|
||||
let outlives_static =
|
||||
rewrite_outlives(&sccs, &annotations, fr_static, &mut outlives_constraints);
|
||||
|
||||
let (sccs, scc_annotations) = if !outlives_static.is_empty() {
|
||||
debug!("The following SCCs had :'static constraints added: {:?}", outlives_static);
|
||||
let (constraint_sccs, scc_annotations) = if added_constraints {
|
||||
let mut annotations = SccAnnotations::init(&definitions);
|
||||
|
||||
// We changed the constraint set and so must recompute SCCs.
|
||||
|
|
@ -307,15 +283,15 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
|
|||
} else {
|
||||
// If we didn't add any back-edges; no more work needs doing
|
||||
debug!("No constraints rewritten!");
|
||||
(sccs, annotations.scc_to_annotation)
|
||||
(constraint_sccs, scc_annotations.scc_to_annotation)
|
||||
};
|
||||
|
||||
LoweredConstraints {
|
||||
constraint_sccs: sccs,
|
||||
constraint_sccs,
|
||||
definitions,
|
||||
scc_annotations,
|
||||
member_constraints,
|
||||
outlives_constraints,
|
||||
outlives_constraints: Frozen::freeze(outlives_constraints),
|
||||
type_tests,
|
||||
liveness_constraints,
|
||||
universe_causes,
|
||||
|
|
@ -323,15 +299,15 @@ pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
fn rewrite_outlives<'tcx>(
|
||||
fn rewrite_placeholder_outlives<'tcx>(
|
||||
sccs: &Sccs<RegionVid, ConstraintSccIndex>,
|
||||
annotations: &SccAnnotations<'_, '_, RegionTracker>,
|
||||
fr_static: RegionVid,
|
||||
outlives_constraints: &mut OutlivesConstraintSet<'tcx>,
|
||||
) -> FxHashSet<ConstraintSccIndex> {
|
||||
// Changed to `true` if we added any constraints to `self` and need to
|
||||
) -> bool {
|
||||
// Changed to `true` if we added any constraints and need to
|
||||
// recompute SCCs.
|
||||
let mut outlives_static = FxHashSet::default();
|
||||
let mut added_constraints = false;
|
||||
|
||||
let annotations = &annotations.scc_to_annotation;
|
||||
|
||||
|
|
@ -354,9 +330,8 @@ fn rewrite_outlives<'tcx>(
|
|||
// needed for correctness, since an SCC upstream of another with
|
||||
// a universe violation will "infect" its downstream SCCs to also
|
||||
// outlive static.
|
||||
outlives_static.insert(scc);
|
||||
let scc_representative_outlives_static = OutlivesConstraint {
|
||||
sup: annotation.representative,
|
||||
sup: annotation.representative.rvid(),
|
||||
sub: fr_static,
|
||||
category: ConstraintCategory::IllegalUniverse,
|
||||
locations: Locations::All(rustc_span::DUMMY_SP),
|
||||
|
|
@ -365,7 +340,9 @@ fn rewrite_outlives<'tcx>(
|
|||
from_closure: false,
|
||||
};
|
||||
outlives_constraints.push(scc_representative_outlives_static);
|
||||
added_constraints = true;
|
||||
debug!("Added {:?}: 'static!", annotation.representative.rvid());
|
||||
}
|
||||
}
|
||||
outlives_static
|
||||
added_constraints
|
||||
}
|
||||
|
|
@ -75,7 +75,7 @@ mod constraints;
|
|||
mod dataflow;
|
||||
mod def_use;
|
||||
mod diagnostics;
|
||||
mod eliminate_placeholders;
|
||||
mod handle_placeholders;
|
||||
mod member_constraints;
|
||||
mod nll;
|
||||
mod path_utils;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use tracing::{debug, instrument};
|
|||
use crate::borrow_set::BorrowSet;
|
||||
use crate::consumers::ConsumerOptions;
|
||||
use crate::diagnostics::RegionErrors;
|
||||
use crate::eliminate_placeholders::rewrite_higher_kinded_outlives_as_constraints;
|
||||
use crate::handle_placeholders::compute_sccs_applying_placeholder_outlives_constraints;
|
||||
use crate::polonius::PoloniusDiagnosticsContext;
|
||||
use crate::polonius::legacy::{
|
||||
PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput,
|
||||
|
|
@ -118,7 +118,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
|
|||
Rc::clone(&location_map),
|
||||
);
|
||||
|
||||
let lowered_constraints = rewrite_higher_kinded_outlives_as_constraints(
|
||||
let lowered_constraints = compute_sccs_applying_placeholder_outlives_constraints(
|
||||
constraints,
|
||||
&universal_region_relations,
|
||||
infcx,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use tracing::debug;
|
|||
|
||||
use crate::borrow_set::BorrowSet;
|
||||
use crate::constraints::OutlivesConstraint;
|
||||
use crate::eliminate_placeholders::LoweredConstraints;
|
||||
use crate::handle_placeholders::LoweredConstraints;
|
||||
use crate::type_check::free_region_relations::UniversalRegionRelations;
|
||||
use crate::universal_regions::UniversalRegions;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
"| {r:rw$?} | {ui:4?} | {v}",
|
||||
r = region,
|
||||
rw = REGION_WIDTH,
|
||||
ui = self.region_universe(region),
|
||||
ui = self.max_nameable_universe(self.constraint_sccs.scc(region)),
|
||||
v = self.region_value_str(region),
|
||||
)?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,15 +4,13 @@ use std::rc::Rc;
|
|||
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::Sccs;
|
||||
use rustc_data_structures::graph::scc::{self, Sccs};
|
||||
use rustc_errors::Diag;
|
||||
use rustc_hir::def_id::CRATE_DEF_ID;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_infer::infer::outlives::test_type_match;
|
||||
use rustc_infer::infer::region_constraints::{
|
||||
GenericKind, RegionVariableInfo, VerifyBound, VerifyIfEq,
|
||||
};
|
||||
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
|
||||
use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound, VerifyIfEq};
|
||||
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::{
|
||||
AnnotationSource, BasicBlock, Body, ConstraintCategory, Local, Location, ReturnConstraint,
|
||||
|
|
@ -29,7 +27,7 @@ use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph};
|
|||
use crate::constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet};
|
||||
use crate::dataflow::BorrowIndex;
|
||||
use crate::diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo};
|
||||
use crate::eliminate_placeholders::{LoweredConstraints, RegionTracker};
|
||||
use crate::handle_placeholders::{LoweredConstraints, RegionTracker};
|
||||
use crate::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex};
|
||||
use crate::polonius::LiveLoans;
|
||||
use crate::polonius::legacy::PoloniusOutput;
|
||||
|
|
@ -50,6 +48,47 @@ mod reverse_sccs;
|
|||
|
||||
pub(crate) mod values;
|
||||
|
||||
/// The representative region variable for an SCC, tagged by its origin.
|
||||
/// We prefer placeholders over existentially quantified variables, otherwise
|
||||
/// it's the one with the smallest Region Variable ID. In other words,
|
||||
/// the order of this enumeration really matters!
|
||||
#[derive(Copy, Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
|
||||
pub(crate) enum Representative {
|
||||
FreeRegion(RegionVid),
|
||||
Placeholder(RegionVid),
|
||||
Existential(RegionVid),
|
||||
}
|
||||
|
||||
impl Representative {
|
||||
pub(crate) fn rvid(self) -> RegionVid {
|
||||
match self {
|
||||
Representative::FreeRegion(region_vid)
|
||||
| Representative::Placeholder(region_vid)
|
||||
| Representative::Existential(region_vid) => region_vid,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new(r: RegionVid, definition: &RegionDefinition<'_>) -> Self {
|
||||
match definition.origin {
|
||||
NllRegionVariableOrigin::FreeRegion => Representative::FreeRegion(r),
|
||||
NllRegionVariableOrigin::Placeholder(_) => Representative::Placeholder(r),
|
||||
NllRegionVariableOrigin::Existential { .. } => Representative::Existential(r),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl scc::Annotation for Representative {
|
||||
fn merge_scc(self, other: Self) -> Self {
|
||||
// Just pick the smallest one. Note that we order by tag first!
|
||||
std::cmp::min(self, other)
|
||||
}
|
||||
|
||||
// For reachability, we do nothing since the representative doesn't change.
|
||||
fn merge_reached(self, _other: Self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex>;
|
||||
|
||||
pub struct RegionInferenceContext<'tcx> {
|
||||
|
|
@ -351,7 +390,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
let mut result = Self {
|
||||
definitions,
|
||||
liveness_constraints,
|
||||
constraints: Frozen::freeze(outlives_constraints),
|
||||
constraints: outlives_constraints,
|
||||
constraint_graph,
|
||||
constraint_sccs,
|
||||
scc_annotations,
|
||||
|
|
@ -510,11 +549,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
self.scc_values.placeholders_contained_in(scc)
|
||||
}
|
||||
|
||||
/// Returns access to the value of `r` for debugging purposes.
|
||||
pub(crate) fn region_universe(&self, r: RegionVid) -> ty::UniverseIndex {
|
||||
self.scc_universe(self.constraint_sccs.scc(r))
|
||||
}
|
||||
|
||||
/// Once region solving has completed, this function will return the member constraints that
|
||||
/// were applied to the value of a given SCC `scc`. See `AppliedMemberConstraint`.
|
||||
pub(crate) fn applied_member_constraints(
|
||||
|
|
@ -681,7 +715,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
|
||||
// If the member region lives in a higher universe, we currently choose
|
||||
// the most conservative option by leaving it unchanged.
|
||||
if !self.scc_universe(scc).is_root() {
|
||||
if !self.max_nameable_universe(scc).is_root() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -861,7 +895,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
"lower_bound = {:?} r_scc={:?} universe={:?}",
|
||||
lower_bound,
|
||||
r_scc,
|
||||
self.scc_universe(r_scc)
|
||||
self.max_nameable_universe(r_scc)
|
||||
);
|
||||
// If the type test requires that `T: 'a` where `'a` is a
|
||||
// placeholder from another universe, that effectively requires
|
||||
|
|
@ -1339,10 +1373,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// The minimum universe of any variable reachable from this
|
||||
/// SCC, inside or outside of it.
|
||||
fn scc_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex {
|
||||
self.scc_annotations[scc].min_universe()
|
||||
/// The largest universe of any region nameable from this SCC.
|
||||
fn max_nameable_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex {
|
||||
self.scc_annotations[scc].max_nameable_universe()
|
||||
}
|
||||
|
||||
/// Checks the final value for the free region `fr` to see if it
|
||||
|
|
@ -1364,7 +1397,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
|
||||
// Because this free region must be in the ROOT universe, we
|
||||
// know it cannot contain any bound universes.
|
||||
assert!(self.scc_universe(longer_fr_scc).is_root());
|
||||
assert!(self.max_nameable_universe(longer_fr_scc).is_root());
|
||||
|
||||
// Only check all of the relations for the main representative of each
|
||||
// SCC, otherwise just check that we outlive said representative. This
|
||||
|
|
@ -1755,7 +1788,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
#[instrument(skip(self), level = "trace", ret)]
|
||||
pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid {
|
||||
trace!(scc = ?self.constraint_sccs.scc(fr1));
|
||||
trace!(universe = ?self.region_universe(fr1));
|
||||
trace!(universe = ?self.max_nameable_universe(self.constraint_sccs.scc(fr1)));
|
||||
self.find_constraint_paths_between_regions(fr1, |r| {
|
||||
// First look for some `r` such that `fr1: r` and `r` is live at `location`
|
||||
trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r));
|
||||
|
|
@ -2086,7 +2119,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
/// they *must* be equal (though not having the same repr does not
|
||||
/// mean they are unequal).
|
||||
fn scc_representative(&self, scc: ConstraintSccIndex) -> RegionVid {
|
||||
self.scc_annotations[scc].representative
|
||||
self.scc_annotations[scc].representative.rvid()
|
||||
}
|
||||
|
||||
pub(crate) fn liveness_constraints(&self) -> &LivenessValues {
|
||||
|
|
@ -2108,21 +2141,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionDefinition<'tcx> {
|
||||
pub(crate) fn new(rv_info: &RegionVariableInfo) -> Self {
|
||||
// Create a new region definition. Note that, for free
|
||||
// regions, the `external_name` field gets updated later in
|
||||
// [[crate::eliminate_placeholders]].
|
||||
|
||||
let origin = match rv_info.origin {
|
||||
RegionVariableOrigin::Nll(origin) => origin,
|
||||
_ => NllRegionVariableOrigin::Existential { from_forall: false },
|
||||
};
|
||||
|
||||
Self { origin, universe: rv_info.universe, external_name: None }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct BlameConstraint<'tcx> {
|
||||
pub category: ConstraintCategory<'tcx>,
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
let scc = self.constraint_sccs.scc(vid);
|
||||
|
||||
// Special handling of higher-ranked regions.
|
||||
if !self.scc_universe(scc).is_root() {
|
||||
if !self.max_nameable_universe(scc).is_root() {
|
||||
match self.scc_values.placeholders_contained_in(scc).enumerate().last() {
|
||||
// If the region contains a single placeholder then they're equal.
|
||||
Some((0, placeholder)) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue