Auto merge of #144446 - nnethercote:opt-region-constraints, r=lcnr

Optimize region constraints

r? `@lcnr`
This commit is contained in:
bors 2025-08-01 04:06:21 +00:00
commit 6c02dd4eae
11 changed files with 229 additions and 239 deletions

View file

@ -3,7 +3,7 @@ use std::rc::Rc;
use rustc_errors::Diag;
use rustc_hir::def_id::LocalDefId;
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
use rustc_infer::infer::region_constraints::{Constraint, ConstraintKind, RegionConstraintData};
use rustc_infer::infer::{
InferCtxt, RegionResolutionError, RegionVariableOrigin, SubregionOrigin, TyCtxtInferExt as _,
};
@ -454,25 +454,24 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>(
(RePlaceholder(a_p), RePlaceholder(b_p)) => a_p.bound == b_p.bound,
_ => a_region == b_region,
};
let mut check =
|constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match *constraint {
Constraint::RegSubReg(sub, sup)
if ((exact && sup == placeholder_region)
|| (!exact && regions_the_same(sup, placeholder_region)))
&& sup != sub =>
{
Some((sub, cause.clone()))
}
Constraint::VarSubReg(vid, sup)
if (exact
&& sup == placeholder_region
&& !universe_of_region(vid).can_name(placeholder_universe))
|| (!exact && regions_the_same(sup, placeholder_region)) =>
{
Some((ty::Region::new_var(infcx.tcx, vid), cause.clone()))
}
_ => None,
};
let mut check = |c: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match c.kind {
ConstraintKind::RegSubReg
if ((exact && c.sup == placeholder_region)
|| (!exact && regions_the_same(c.sup, placeholder_region)))
&& c.sup != c.sub =>
{
Some((c.sub, cause.clone()))
}
ConstraintKind::VarSubReg
if (exact
&& c.sup == placeholder_region
&& !universe_of_region(c.sub.as_var()).can_name(placeholder_universe))
|| (!exact && regions_the_same(c.sup, placeholder_region)) =>
{
Some((c.sub, cause.clone()))
}
_ => None,
};
let mut find_culprit = |exact_match: bool| {
region_constraints

View file

@ -21,7 +21,7 @@ use crate::infer::canonical::{
Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues,
QueryRegionConstraints, QueryResponse,
};
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::region_constraints::RegionConstraintData;
use crate::infer::{
DefineOpaqueTypes, InferCtxt, InferOk, InferResult, SubregionOrigin, TypeOutlivesConstraint,
};
@ -105,8 +105,6 @@ impl<'tcx> InferCtxt<'tcx> {
where
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
{
let tcx = self.tcx;
// Select everything, returning errors.
let errors = fulfill_cx.select_all_or_error(self);
@ -120,7 +118,6 @@ impl<'tcx> InferCtxt<'tcx> {
debug!(?region_obligations);
let region_constraints = self.with_region_constraints(|region_constraints| {
make_query_region_constraints(
tcx,
region_obligations,
region_constraints,
region_assumptions,
@ -587,7 +584,6 @@ impl<'tcx> InferCtxt<'tcx> {
/// Given the region obligations and constraints scraped from the infcx,
/// creates query region constraints.
pub fn make_query_region_constraints<'tcx>(
tcx: TyCtxt<'tcx>,
outlives_obligations: Vec<TypeOutlivesConstraint<'tcx>>,
region_constraints: &RegionConstraintData<'tcx>,
assumptions: Vec<ty::ArgOutlivesPredicate<'tcx>>,
@ -600,22 +596,9 @@ pub fn make_query_region_constraints<'tcx>(
let outlives: Vec<_> = constraints
.iter()
.map(|(k, origin)| {
let constraint = match *k {
// Swap regions because we are going from sub (<=) to outlives
// (>=).
Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
ty::Region::new_var(tcx, v2).into(),
ty::Region::new_var(tcx, v1),
),
Constraint::VarSubReg(v1, r2) => {
ty::OutlivesPredicate(r2.into(), ty::Region::new_var(tcx, v1))
}
Constraint::RegSubVar(r1, v2) => {
ty::OutlivesPredicate(ty::Region::new_var(tcx, v2).into(), r1)
}
Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
};
.map(|(c, origin)| {
// Swap regions because we are going from sub (<=) to outlives (>=).
let constraint = ty::OutlivesPredicate(c.sup.into(), c.sub);
(constraint, origin.to_constraint_category())
})
.chain(outlives_obligations.into_iter().map(|obl| {

View file

@ -19,7 +19,7 @@ use tracing::{debug, instrument};
use super::outlives::test_type_match;
use crate::infer::region_constraints::{
Constraint, GenericKind, RegionConstraintData, VarInfos, VerifyBound,
Constraint, ConstraintKind, GenericKind, RegionConstraintData, VarInfos, VerifyBound,
};
use crate::infer::{RegionRelations, RegionVariableOrigin, SubregionOrigin};
@ -187,91 +187,96 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
let mut constraints = IndexVec::from_elem(Vec::new(), &var_values.values);
// Tracks the changed region vids.
let mut changes = Vec::new();
for (constraint, _) in &self.data.constraints {
match *constraint {
Constraint::RegSubVar(a_region, b_vid) => {
let b_data = var_values.value_mut(b_vid);
for (c, _) in &self.data.constraints {
match c.kind {
ConstraintKind::RegSubVar => {
let sup_vid = c.sup.as_var();
let sup_data = var_values.value_mut(sup_vid);
if self.expand_node(a_region, b_vid, b_data) {
changes.push(b_vid);
if self.expand_node(c.sub, sup_vid, sup_data) {
changes.push(sup_vid);
}
}
Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
VarValue::ErrorValue => continue,
VarValue::Empty(a_universe) => {
let b_data = var_values.value_mut(b_vid);
ConstraintKind::VarSubVar => {
let sub_vid = c.sub.as_var();
let sup_vid = c.sup.as_var();
match *var_values.value(sub_vid) {
VarValue::ErrorValue => continue,
VarValue::Empty(sub_universe) => {
let sup_data = var_values.value_mut(sup_vid);
let changed = match *b_data {
VarValue::Empty(b_universe) => {
// Empty regions are ordered according to the universe
// they are associated with.
let ui = a_universe.min(b_universe);
let changed = match *sup_data {
VarValue::Empty(sup_universe) => {
// Empty regions are ordered according to the universe
// they are associated with.
let ui = sub_universe.min(sup_universe);
debug!(
"Expanding value of {:?} \
debug!(
"Expanding value of {:?} \
from empty lifetime with universe {:?} \
to empty lifetime with universe {:?}",
b_vid, b_universe, ui
);
sup_vid, sup_universe, ui
);
*b_data = VarValue::Empty(ui);
true
}
VarValue::Value(cur_region) => {
match cur_region.kind() {
// If this empty region is from a universe that can name the
// placeholder universe, then the LUB is the Placeholder region
// (which is the cur_region). Otherwise, the LUB is the Static
// lifetime.
RePlaceholder(placeholder)
if !a_universe.can_name(placeholder.universe) =>
{
let lub = self.tcx().lifetimes.re_static;
debug!(
"Expanding value of {:?} from {:?} to {:?}",
b_vid, cur_region, lub
);
*sup_data = VarValue::Empty(ui);
true
}
VarValue::Value(cur_region) => {
match cur_region.kind() {
// If this empty region is from a universe that can name
// the placeholder universe, then the LUB is the
// Placeholder region (which is the cur_region). Otherwise,
// the LUB is the Static lifetime.
RePlaceholder(placeholder)
if !sub_universe.can_name(placeholder.universe) =>
{
let lub = self.tcx().lifetimes.re_static;
debug!(
"Expanding value of {:?} from {:?} to {:?}",
sup_vid, cur_region, lub
);
*b_data = VarValue::Value(lub);
true
*sup_data = VarValue::Value(lub);
true
}
_ => false,
}
}
_ => false,
VarValue::ErrorValue => false,
};
if changed {
changes.push(sup_vid);
}
match sup_data {
VarValue::Value(Region(Interned(ReStatic, _)))
| VarValue::ErrorValue => (),
_ => {
constraints[sub_vid].push((sub_vid, sup_vid));
constraints[sup_vid].push((sub_vid, sup_vid));
}
}
VarValue::ErrorValue => false,
};
if changed {
changes.push(b_vid);
}
match b_data {
VarValue::Value(Region(Interned(ReStatic, _)))
| VarValue::ErrorValue => (),
_ => {
constraints[a_vid].push((a_vid, b_vid));
constraints[b_vid].push((a_vid, b_vid));
VarValue::Value(sub_region) => {
let sup_data = var_values.value_mut(sup_vid);
if self.expand_node(sub_region, sup_vid, sup_data) {
changes.push(sup_vid);
}
match sup_data {
VarValue::Value(Region(Interned(ReStatic, _)))
| VarValue::ErrorValue => (),
_ => {
constraints[sub_vid].push((sub_vid, sup_vid));
constraints[sup_vid].push((sub_vid, sup_vid));
}
}
}
}
VarValue::Value(a_region) => {
let b_data = var_values.value_mut(b_vid);
if self.expand_node(a_region, b_vid, b_data) {
changes.push(b_vid);
}
match b_data {
VarValue::Value(Region(Interned(ReStatic, _)))
| VarValue::ErrorValue => (),
_ => {
constraints[a_vid].push((a_vid, b_vid));
constraints[b_vid].push((a_vid, b_vid));
}
}
}
},
Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
}
ConstraintKind::RegSubReg | ConstraintKind::VarSubReg => {
// These constraints are checked after expansion
// is done, in `collect_errors`.
continue;
@ -528,49 +533,48 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
var_data: &mut LexicalRegionResolutions<'tcx>,
errors: &mut Vec<RegionResolutionError<'tcx>>,
) {
for (constraint, origin) in &self.data.constraints {
debug!(?constraint, ?origin);
match *constraint {
Constraint::RegSubVar(..) | Constraint::VarSubVar(..) => {
for (c, origin) in &self.data.constraints {
debug!(?c, ?origin);
match c.kind {
ConstraintKind::RegSubVar | ConstraintKind::VarSubVar => {
// Expansion will ensure that these constraints hold. Ignore.
}
Constraint::RegSubReg(sub, sup) => {
if self.sub_concrete_regions(sub, sup) {
ConstraintKind::RegSubReg => {
if self.sub_concrete_regions(c.sub, c.sup) {
continue;
}
debug!(
"region error at {:?}: \
cannot verify that {:?} <= {:?}",
origin, sub, sup
"region error at {:?}: cannot verify that {:?} <= {:?}",
origin, c.sub, c.sup
);
errors.push(RegionResolutionError::ConcreteFailure(
(*origin).clone(),
sub,
sup,
c.sub,
c.sup,
));
}
Constraint::VarSubReg(a_vid, b_region) => {
let a_data = var_data.value_mut(a_vid);
debug!("contraction: {:?} == {:?}, {:?}", a_vid, a_data, b_region);
ConstraintKind::VarSubReg => {
let sub_vid = c.sub.as_var();
let sub_data = var_data.value_mut(sub_vid);
debug!("contraction: {:?} == {:?}, {:?}", sub_vid, sub_data, c.sup);
let VarValue::Value(a_region) = *a_data else {
let VarValue::Value(sub_region) = *sub_data else {
continue;
};
// Do not report these errors immediately:
// instead, set the variable value to error and
// collect them later.
if !self.sub_concrete_regions(a_region, b_region) {
if !self.sub_concrete_regions(sub_region, c.sup) {
debug!(
"region error at {:?}: \
cannot verify that {:?}={:?} <= {:?}",
origin, a_vid, a_region, b_region
"region error at {:?}: cannot verify that {:?}={:?} <= {:?}",
origin, sub_vid, sub_region, c.sup
);
*a_data = VarValue::ErrorValue;
*sub_data = VarValue::ErrorValue;
}
}
}
@ -682,18 +686,20 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
let dummy_source = graph.add_node(());
let dummy_sink = graph.add_node(());
for (constraint, _) in &self.data.constraints {
match *constraint {
Constraint::VarSubVar(a_id, b_id) => {
graph.add_edge(NodeIndex(a_id.index()), NodeIndex(b_id.index()), *constraint);
for (c, _) in &self.data.constraints {
match c.kind {
ConstraintKind::VarSubVar => {
let sub_vid = c.sub.as_var();
let sup_vid = c.sup.as_var();
graph.add_edge(NodeIndex(sub_vid.index()), NodeIndex(sup_vid.index()), *c);
}
Constraint::RegSubVar(_, b_id) => {
graph.add_edge(dummy_source, NodeIndex(b_id.index()), *constraint);
ConstraintKind::RegSubVar => {
graph.add_edge(dummy_source, NodeIndex(c.sup.as_var().index()), *c);
}
Constraint::VarSubReg(a_id, _) => {
graph.add_edge(NodeIndex(a_id.index()), dummy_sink, *constraint);
ConstraintKind::VarSubReg => {
graph.add_edge(NodeIndex(c.sub.as_var().index()), dummy_sink, *c);
}
Constraint::RegSubReg(..) => {
ConstraintKind::RegSubReg => {
// this would be an edge from `dummy_source` to
// `dummy_sink`; just ignore it.
}
@ -878,26 +884,30 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
let source_node_index = NodeIndex(source_vid.index());
for (_, edge) in graph.adjacent_edges(source_node_index, dir) {
match edge.data {
Constraint::VarSubVar(from_vid, to_vid) => {
let get_origin =
|| this.constraints.iter().find(|(c, _)| *c == edge.data).unwrap().1.clone();
match edge.data.kind {
ConstraintKind::VarSubVar => {
let from_vid = edge.data.sub.as_var();
let to_vid = edge.data.sup.as_var();
let opp_vid = if from_vid == source_vid { to_vid } else { from_vid };
if state.set.insert(opp_vid) {
state.stack.push(opp_vid);
}
}
Constraint::RegSubVar(region, _) | Constraint::VarSubReg(_, region) => {
let origin = this
.constraints
.iter()
.find(|(c, _)| *c == edge.data)
.unwrap()
.1
.clone();
state.result.push(RegionAndOrigin { region, origin });
ConstraintKind::RegSubVar => {
let origin = get_origin();
state.result.push(RegionAndOrigin { region: edge.data.sub, origin });
}
Constraint::RegSubReg(..) => panic!(
ConstraintKind::VarSubReg => {
let origin = get_origin();
state.result.push(RegionAndOrigin { region: edge.data.sup, origin });
}
ConstraintKind::RegSubReg => panic!(
"cannot reach reg-sub-reg edge in region inference \
post-processing"
),

View file

@ -10,7 +10,7 @@ use super::region_constraints::{RegionConstraintData, UndoLog};
use super::{InferCtxt, RegionResolutionError, SubregionOrigin};
use crate::infer::free_regions::RegionRelations;
use crate::infer::lexical_region_resolve;
use crate::infer::region_constraints::Constraint;
use crate::infer::region_constraints::ConstraintKind;
pub mod env;
pub mod for_liveness;
@ -70,10 +70,10 @@ impl<'tcx> InferCtxt<'tcx> {
// Filter out any region-region outlives assumptions that are implied by
// coroutine well-formedness.
if self.tcx.sess.opts.unstable_opts.higher_ranked_assumptions {
storage.data.constraints.retain(|(constraint, _)| match *constraint {
Constraint::RegSubReg(r1, r2) => !outlives_env
storage.data.constraints.retain(|(c, _)| match c.kind {
ConstraintKind::RegSubReg => !outlives_env
.higher_ranked_assumptions()
.contains(&ty::OutlivesPredicate(r2.into(), r1)),
.contains(&ty::OutlivesPredicate(c.sup.into(), c.sub)),
_ => true,
});
}

View file

@ -83,7 +83,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
return Ok(());
}
let mini_graph = MiniGraph::new(tcx, &self, only_consider_snapshot);
let mini_graph = MiniGraph::new(&self, only_consider_snapshot);
let mut leak_check = LeakCheck::new(tcx, outer_universe, max_universe, mini_graph, self);
leak_check.assign_placeholder_values()?;
@ -359,7 +359,6 @@ struct MiniGraph<'tcx> {
impl<'tcx> MiniGraph<'tcx> {
fn new(
tcx: TyCtxt<'tcx>,
region_constraints: &RegionConstraintCollector<'_, 'tcx>,
only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>,
) -> Self {
@ -368,7 +367,6 @@ impl<'tcx> MiniGraph<'tcx> {
// Note that if `R2: R1`, we get a callback `r1, r2`, so `target` is first parameter.
Self::iterate_region_constraints(
tcx,
region_constraints,
only_consider_snapshot,
|target, source| {
@ -384,33 +382,18 @@ impl<'tcx> MiniGraph<'tcx> {
/// Invokes `each_edge(R1, R2)` for each edge where `R2: R1`
fn iterate_region_constraints(
tcx: TyCtxt<'tcx>,
region_constraints: &RegionConstraintCollector<'_, 'tcx>,
only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>,
mut each_edge: impl FnMut(ty::Region<'tcx>, ty::Region<'tcx>),
) {
let mut each_constraint = |constraint| match constraint {
&Constraint::VarSubVar(a, b) => {
each_edge(ty::Region::new_var(tcx, a), ty::Region::new_var(tcx, b));
}
&Constraint::RegSubVar(a, b) => {
each_edge(a, ty::Region::new_var(tcx, b));
}
&Constraint::VarSubReg(a, b) => {
each_edge(ty::Region::new_var(tcx, a), b);
}
&Constraint::RegSubReg(a, b) => {
each_edge(a, b);
}
};
if let Some(snapshot) = only_consider_snapshot {
for undo_entry in
region_constraints.undo_log.region_constraints_in_snapshot(&snapshot.undo_snapshot)
{
match undo_entry {
&AddConstraint(i) => {
each_constraint(&region_constraints.data().constraints[i].0);
let c = region_constraints.data().constraints[i].0;
each_edge(c.sub, c.sup);
}
&AddVerify(i) => span_bug!(
region_constraints.data().verifys[i].origin.span(),
@ -420,11 +403,7 @@ impl<'tcx> MiniGraph<'tcx> {
}
}
} else {
region_constraints
.data()
.constraints
.iter()
.for_each(|(constraint, _)| each_constraint(constraint));
region_constraints.data().constraints.iter().for_each(|(c, _)| each_edge(c.sub, c.sup))
}
}

View file

@ -80,31 +80,37 @@ pub struct RegionConstraintData<'tcx> {
/// Represents a constraint that influences the inference process.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum Constraint<'tcx> {
pub enum ConstraintKind {
/// A region variable is a subregion of another.
VarSubVar(RegionVid, RegionVid),
VarSubVar,
/// A concrete region is a subregion of region variable.
RegSubVar(Region<'tcx>, RegionVid),
RegSubVar,
/// A region variable is a subregion of a concrete region. This does not
/// directly affect inference, but instead is checked after
/// inference is complete.
VarSubReg(RegionVid, Region<'tcx>),
VarSubReg,
/// A constraint where neither side is a variable. This does not
/// directly affect inference, but instead is checked after
/// inference is complete.
RegSubReg(Region<'tcx>, Region<'tcx>),
RegSubReg,
}
/// Represents a constraint that influences the inference process.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub struct Constraint<'tcx> {
pub kind: ConstraintKind,
// If `kind` is `VarSubVar` or `VarSubReg`, this must be a `ReVar`.
pub sub: Region<'tcx>,
// If `kind` is `VarSubVar` or `RegSubVar`, this must be a `ReVar`.
pub sup: Region<'tcx>,
}
impl Constraint<'_> {
pub fn involves_placeholders(&self) -> bool {
match self {
Constraint::VarSubVar(_, _) => false,
Constraint::VarSubReg(_, r) | Constraint::RegSubVar(r, _) => r.is_placeholder(),
Constraint::RegSubReg(r, s) => r.is_placeholder() || s.is_placeholder(),
}
self.sub.is_placeholder() || self.sup.is_placeholder()
}
}
@ -471,16 +477,24 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
// all regions are subregions of static, so we can ignore this
}
(ReVar(sub_id), ReVar(sup_id)) => {
self.add_constraint(Constraint::VarSubVar(sub_id, sup_id), origin);
}
(_, ReVar(sup_id)) => {
self.add_constraint(Constraint::RegSubVar(sub, sup_id), origin);
}
(ReVar(sub_id), _) => {
self.add_constraint(Constraint::VarSubReg(sub_id, sup), origin);
if sub_id != sup_id {
self.add_constraint(
Constraint { kind: ConstraintKind::VarSubVar, sub, sup },
origin,
);
}
}
(_, ReVar(_)) => self
.add_constraint(Constraint { kind: ConstraintKind::RegSubVar, sub, sup }, origin),
(ReVar(_), _) => self
.add_constraint(Constraint { kind: ConstraintKind::VarSubReg, sub, sup }, origin),
_ => {
self.add_constraint(Constraint::RegSubReg(sub, sup), origin);
if sub != sup {
self.add_constraint(
Constraint { kind: ConstraintKind::RegSubReg, sub, sup },
origin,
)
}
}
}
}

View file

@ -212,7 +212,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
let region_assumptions = self.0.inner.borrow().region_assumptions().to_owned();
let region_constraints = self.0.with_region_constraints(|region_constraints| {
make_query_region_constraints(
self.tcx,
region_obligations,
region_constraints,
region_assumptions,

View file

@ -13,7 +13,7 @@ use tracing::debug;
use super::*;
use crate::errors::UnableToConstructConstantValue;
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::region_constraints::{ConstraintKind, RegionConstraintData};
use crate::regions::OutlivesEnvironmentBuildExt;
use crate::traits::project::ProjectAndUnifyResult;
@ -452,37 +452,41 @@ impl<'tcx> AutoTraitFinder<'tcx> {
let mut vid_map = FxIndexMap::<RegionTarget<'cx>, RegionDeps<'cx>>::default();
let mut finished_map = FxIndexMap::default();
for (constraint, _) in &regions.constraints {
match constraint {
&Constraint::VarSubVar(r1, r2) => {
for (c, _) in &regions.constraints {
match c.kind {
ConstraintKind::VarSubVar => {
let sub_vid = c.sub.as_var();
let sup_vid = c.sup.as_var();
{
let deps1 = vid_map.entry(RegionTarget::RegionVid(r1)).or_default();
deps1.larger.insert(RegionTarget::RegionVid(r2));
let deps1 = vid_map.entry(RegionTarget::RegionVid(sub_vid)).or_default();
deps1.larger.insert(RegionTarget::RegionVid(sup_vid));
}
let deps2 = vid_map.entry(RegionTarget::RegionVid(r2)).or_default();
deps2.smaller.insert(RegionTarget::RegionVid(r1));
let deps2 = vid_map.entry(RegionTarget::RegionVid(sup_vid)).or_default();
deps2.smaller.insert(RegionTarget::RegionVid(sub_vid));
}
&Constraint::RegSubVar(region, vid) => {
ConstraintKind::RegSubVar => {
let sup_vid = c.sup.as_var();
{
let deps1 = vid_map.entry(RegionTarget::Region(region)).or_default();
deps1.larger.insert(RegionTarget::RegionVid(vid));
let deps1 = vid_map.entry(RegionTarget::Region(c.sub)).or_default();
deps1.larger.insert(RegionTarget::RegionVid(sup_vid));
}
let deps2 = vid_map.entry(RegionTarget::RegionVid(vid)).or_default();
deps2.smaller.insert(RegionTarget::Region(region));
let deps2 = vid_map.entry(RegionTarget::RegionVid(sup_vid)).or_default();
deps2.smaller.insert(RegionTarget::Region(c.sub));
}
&Constraint::VarSubReg(vid, region) => {
finished_map.insert(vid, region);
ConstraintKind::VarSubReg => {
let sub_vid = c.sub.as_var();
finished_map.insert(sub_vid, c.sup);
}
&Constraint::RegSubReg(r1, r2) => {
ConstraintKind::RegSubReg => {
{
let deps1 = vid_map.entry(RegionTarget::Region(r1)).or_default();
deps1.larger.insert(RegionTarget::Region(r2));
let deps1 = vid_map.entry(RegionTarget::Region(c.sub)).or_default();
deps1.larger.insert(RegionTarget::Region(c.sup));
}
let deps2 = vid_map.entry(RegionTarget::Region(r2)).or_default();
deps2.smaller.insert(RegionTarget::Region(r1));
let deps2 = vid_map.entry(RegionTarget::Region(c.sup)).or_default();
deps2.smaller.insert(RegionTarget::Region(c.sub));
}
}
}

View file

@ -108,7 +108,6 @@ where
let region_assumptions = infcx.take_registered_region_assumptions();
let region_constraint_data = infcx.take_and_reset_region_constraints();
let region_constraints = query_response::make_query_region_constraints(
infcx.tcx,
region_obligations,
&region_constraint_data,
region_assumptions,

View file

@ -70,7 +70,6 @@ fn compute_assumptions<'tcx>(
let region_constraints = infcx.take_and_reset_region_constraints();
let outlives = make_query_region_constraints(
tcx,
region_obligations,
&region_constraints,
region_assumptions,

View file

@ -1,6 +1,6 @@
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry};
use rustc_hir as hir;
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
use rustc_infer::infer::region_constraints::{ConstraintKind, RegionConstraintData};
use rustc_middle::bug;
use rustc_middle::ty::{self, Region, Ty, fold_regions};
use rustc_span::def_id::DefId;
@ -233,31 +233,35 @@ fn clean_region_outlives_constraints<'tcx>(
// Each `RegionTarget` (a `RegionVid` or a `Region`) maps to its smaller and larger regions.
// Note that "larger" regions correspond to sub regions in the surface language.
// E.g., in `'a: 'b`, `'a` is the larger region.
for (constraint, _) in &regions.constraints {
match *constraint {
Constraint::VarSubVar(vid1, vid2) => {
let deps1 = map.entry(RegionTarget::RegionVid(vid1)).or_default();
deps1.larger.insert(RegionTarget::RegionVid(vid2));
for (c, _) in &regions.constraints {
match c.kind {
ConstraintKind::VarSubVar => {
let sub_vid = c.sub.as_var();
let sup_vid = c.sup.as_var();
let deps1 = map.entry(RegionTarget::RegionVid(sub_vid)).or_default();
deps1.larger.insert(RegionTarget::RegionVid(sup_vid));
let deps2 = map.entry(RegionTarget::RegionVid(vid2)).or_default();
deps2.smaller.insert(RegionTarget::RegionVid(vid1));
let deps2 = map.entry(RegionTarget::RegionVid(sup_vid)).or_default();
deps2.smaller.insert(RegionTarget::RegionVid(sub_vid));
}
Constraint::RegSubVar(region, vid) => {
let deps = map.entry(RegionTarget::RegionVid(vid)).or_default();
deps.smaller.insert(RegionTarget::Region(region));
ConstraintKind::RegSubVar => {
let sup_vid = c.sup.as_var();
let deps = map.entry(RegionTarget::RegionVid(sup_vid)).or_default();
deps.smaller.insert(RegionTarget::Region(c.sub));
}
Constraint::VarSubReg(vid, region) => {
let deps = map.entry(RegionTarget::RegionVid(vid)).or_default();
deps.larger.insert(RegionTarget::Region(region));
ConstraintKind::VarSubReg => {
let sub_vid = c.sub.as_var();
let deps = map.entry(RegionTarget::RegionVid(sub_vid)).or_default();
deps.larger.insert(RegionTarget::Region(c.sup));
}
Constraint::RegSubReg(r1, r2) => {
ConstraintKind::RegSubReg => {
// The constraint is already in the form that we want, so we're done with it
// The desired order is [larger, smaller], so flip them.
if early_bound_region_name(r1) != early_bound_region_name(r2) {
if early_bound_region_name(c.sub) != early_bound_region_name(c.sup) {
outlives_predicates
.entry(early_bound_region_name(r2).expect("no region_name found"))
.entry(early_bound_region_name(c.sup).expect("no region_name found"))
.or_default()
.push(r1);
.push(c.sub);
}
}
}