Auto merge of #144446 - nnethercote:opt-region-constraints, r=lcnr
Optimize region constraints r? `@lcnr`
This commit is contained in:
commit
6c02dd4eae
11 changed files with 229 additions and 239 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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| {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(®ion_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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 ®ions.constraints {
|
||||
match constraint {
|
||||
&Constraint::VarSubVar(r1, r2) => {
|
||||
for (c, _) in ®ions.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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
®ion_constraint_data,
|
||||
region_assumptions,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
®ion_constraints,
|
||||
region_assumptions,
|
||||
|
|
|
|||
|
|
@ -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 ®ions.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 ®ions.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue