Skip to content

Commit b2f1ccf

Browse files
committed
Auto merge of #155258 - ShoyuVanilla:eq-constraint, r=lcnr
Make region equality emits Eq constraints For context, see.. - The box named *coroutine witness Send lifetime requirements now considered by leakcheck* from [this roadmap](https://raw.githubusercontent.com/hexcatnl/roadmap/6f23e638f65249ef02af86a5454275103a71552d/next-solver.svg) - [#t-types/trait-system-refactor > A question on #251 @ 💬](https://rust-lang.zulipchat.com/#narrow/channel/364551-t-types.2Ftrait-system-refactor/topic/A.20question.20on.20.23251/near/584166935) - Comments on `rustc_type_ir::predicate::RegionEqPredicate`
2 parents 3142bea + ace3aa3 commit b2f1ccf

24 files changed

Lines changed: 361 additions & 99 deletions

File tree

compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>(
451451
(RePlaceholder(a_p), RePlaceholder(b_p)) => a_p.bound == b_p.bound,
452452
_ => a_region == b_region,
453453
};
454-
let mut check = |c: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match c.kind {
454+
let mut check = |c: Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match c.kind {
455455
ConstraintKind::RegSubReg
456456
if ((exact && c.sup == placeholder_region)
457457
|| (!exact && regions_the_same(c.sup, placeholder_region)))
@@ -467,13 +467,23 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>(
467467
{
468468
Some((c.sub, cause.clone()))
469469
}
470-
_ => None,
470+
ConstraintKind::VarSubVar
471+
| ConstraintKind::RegSubVar
472+
| ConstraintKind::VarSubReg
473+
| ConstraintKind::RegSubReg => None,
474+
475+
ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => {
476+
unreachable!()
477+
}
471478
};
472479

473480
let mut find_culprit = |exact_match: bool| {
474481
region_constraints
475482
.constraints
476483
.iter()
484+
.flat_map(|(constraint, cause)| {
485+
constraint.iter_outlives().map(move |constraint| (constraint, cause))
486+
})
477487
.find_map(|(constraint, cause)| check(constraint, cause, exact_match))
478488
};
479489

compiler/rustc_borrowck/src/type_check/constraint_conversion.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,14 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
7070

7171
#[instrument(skip(self), level = "debug")]
7272
pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
73-
let QueryRegionConstraints { outlives, assumptions } = query_constraints;
73+
let QueryRegionConstraints { constraints, assumptions } = query_constraints;
7474
let assumptions =
7575
elaborate::elaborate_outlives_assumptions(self.infcx.tcx, assumptions.iter().copied());
7676

77-
for &(predicate, constraint_category) in outlives {
78-
self.convert(predicate, constraint_category, &assumptions);
77+
for &(constraint, constraint_category) in constraints {
78+
constraint.iter_outlives().for_each(|predicate| {
79+
self.convert(predicate, constraint_category, &assumptions);
80+
});
7981
}
8082
}
8183

@@ -292,8 +294,12 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
292294
) {
293295
Ok(TypeOpOutput { output: ty, constraints, .. }) => {
294296
// FIXME(higher_ranked_auto): What should we do with the assumptions here?
295-
if let Some(QueryRegionConstraints { outlives, assumptions: _ }) = constraints {
296-
next_outlives_predicates.extend(outlives.iter().copied());
297+
if let Some(QueryRegionConstraints { constraints, assumptions: _ }) = constraints {
298+
next_outlives_predicates.extend(constraints.iter().flat_map(
299+
|(constraint, category)| {
300+
constraint.iter_outlives().map(|outlives| (outlives, *category))
301+
},
302+
));
297303
}
298304
ty
299305
}

compiler/rustc_infer/src/infer/canonical/query_response.rs

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::infer::canonical::{
2222
Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues,
2323
QueryRegionConstraints, QueryResponse,
2424
};
25-
use crate::infer::region_constraints::RegionConstraintData;
25+
use crate::infer::region_constraints::{ConstraintKind, RegionConstraintData};
2626
use crate::infer::{
2727
DefineOpaqueTypes, InferCtxt, InferOk, InferResult, OpaqueTypeStorageEntries, SubregionOrigin,
2828
TypeOutlivesConstraint,
@@ -188,9 +188,16 @@ impl<'tcx> InferCtxt<'tcx> {
188188
let InferOk { value: result_args, obligations } =
189189
self.query_response_instantiation(cause, param_env, original_values, query_response)?;
190190

191-
for (predicate, _category) in &query_response.value.region_constraints.outlives {
192-
let predicate = instantiate_value(self.tcx, &result_args, *predicate);
193-
self.register_outlives_constraint(predicate, cause);
191+
for (constraint, _category) in &query_response.value.region_constraints.constraints {
192+
let constraint = instantiate_value(self.tcx, &result_args, *constraint);
193+
match constraint {
194+
ty::RegionConstraint::Outlives(predicate) => {
195+
self.register_outlives_constraint(predicate, cause);
196+
}
197+
ty::RegionConstraint::Eq(predicate) => {
198+
self.register_region_eq_constraint(predicate, cause);
199+
}
200+
}
194201
}
195202

196203
for assumption in &query_response.value.region_constraints.assumptions {
@@ -277,14 +284,11 @@ impl<'tcx> InferCtxt<'tcx> {
277284
}
278285

279286
(GenericArgKind::Lifetime(v_o), GenericArgKind::Lifetime(v_r)) => {
280-
// To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`.
281287
if v_o != v_r {
282-
output_query_region_constraints
283-
.outlives
284-
.push((ty::OutlivesPredicate(v_o.into(), v_r), constraint_category));
285-
output_query_region_constraints
286-
.outlives
287-
.push((ty::OutlivesPredicate(v_r.into(), v_o), constraint_category));
288+
output_query_region_constraints.constraints.push((
289+
ty::RegionEqPredicate(v_o.into(), v_r).into(),
290+
constraint_category,
291+
));
288292
}
289293
}
290294

@@ -311,13 +315,12 @@ impl<'tcx> InferCtxt<'tcx> {
311315
}
312316

313317
// ...also include the other query region constraints from the query.
314-
output_query_region_constraints.outlives.extend(
315-
query_response.value.region_constraints.outlives.iter().filter_map(|&r_c| {
318+
output_query_region_constraints.constraints.extend(
319+
query_response.value.region_constraints.constraints.iter().filter_map(|&r_c| {
316320
let r_c = instantiate_value(self.tcx, &result_args, r_c);
317321

318-
// Screen out `'a: 'a` cases.
319-
let ty::OutlivesPredicate(k1, r2) = r_c.0;
320-
if k1 != r2.into() { Some(r_c) } else { None }
322+
// Screen out `'a: 'a` or `'a == 'a` cases.
323+
if r_c.0.is_trivial() { None } else { Some(r_c) }
321324
}),
322325
);
323326

@@ -611,20 +614,30 @@ pub fn make_query_region_constraints<'tcx>(
611614

612615
debug!(?constraints);
613616

614-
let outlives: Vec<_> = constraints
617+
let constraints: Vec<_> = constraints
615618
.iter()
616-
.map(|(c, origin)| {
617-
// Swap regions because we are going from sub (<=) to outlives (>=).
618-
let constraint = ty::OutlivesPredicate(c.sup.into(), c.sub);
619-
(constraint, origin.to_constraint_category())
619+
.map(|(c, origin)| match c.kind {
620+
ConstraintKind::VarSubVar
621+
| ConstraintKind::RegSubVar
622+
| ConstraintKind::VarSubReg
623+
| ConstraintKind::RegSubReg => {
624+
// Swap regions because we are going from sub (<=) to outlives (>=).
625+
let constraint = ty::OutlivesPredicate(c.sup.into(), c.sub).into();
626+
(constraint, origin.to_constraint_category())
627+
}
628+
629+
ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => {
630+
let constraint = ty::RegionEqPredicate(c.sup, c.sub).into();
631+
(constraint, origin.to_constraint_category())
632+
}
620633
})
621634
.chain(outlives_obligations.into_iter().map(|obl| {
622635
(
623-
ty::OutlivesPredicate(obl.sup_type.into(), obl.sub_region),
636+
ty::OutlivesPredicate(obl.sup_type.into(), obl.sub_region).into(),
624637
obl.origin.to_constraint_category(),
625638
)
626639
}))
627640
.collect();
628641

629-
QueryRegionConstraints { outlives, assumptions }
642+
QueryRegionConstraints { constraints, assumptions }
630643
}

compiler/rustc_infer/src/infer/lexical_region_resolve/indexed_edges.rs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,60 @@ pub(super) enum EdgeDirection {
1313

1414
/// Type alias for the pairs stored in [`RegionConstraintData::constraints`],
1515
/// which we are indexing.
16-
type ConstraintPair<'tcx> = (Constraint<'tcx>, SubregionOrigin<'tcx>);
16+
type ConstraintPair<'data, 'tcx> = (Constraint<'tcx>, &'data SubregionOrigin<'tcx>);
1717

1818
/// An index from region variables to their corresponding constraint edges,
1919
/// used on some error paths.
2020
pub(super) struct IndexedConstraintEdges<'data, 'tcx> {
21-
out_edges: IndexVec<RegionVid, Vec<&'data ConstraintPair<'tcx>>>,
22-
in_edges: IndexVec<RegionVid, Vec<&'data ConstraintPair<'tcx>>>,
21+
out_edges: IndexVec<RegionVid, Vec<ConstraintPair<'data, 'tcx>>>,
22+
in_edges: IndexVec<RegionVid, Vec<ConstraintPair<'data, 'tcx>>>,
2323
}
2424

2525
impl<'data, 'tcx> IndexedConstraintEdges<'data, 'tcx> {
2626
pub(super) fn build_index(num_vars: usize, data: &'data RegionConstraintData<'tcx>) -> Self {
2727
let mut out_edges = IndexVec::from_fn_n(|_| vec![], num_vars);
2828
let mut in_edges = IndexVec::from_fn_n(|_| vec![], num_vars);
2929

30-
for pair @ (c, _) in &data.constraints {
30+
for pair @ (c, _) in data
31+
.constraints
32+
.iter()
33+
.flat_map(|(c, origin)| c.iter_outlives().map(move |c| (c, origin)))
34+
{
3135
// Only push a var out-edge for `VarSub...` constraints.
3236
match c.kind {
3337
ConstraintKind::VarSubVar | ConstraintKind::VarSubReg => {
34-
out_edges[c.sub.as_var()].push(pair)
38+
out_edges[c.sub.as_var()].push(pair);
3539
}
40+
3641
ConstraintKind::RegSubVar | ConstraintKind::RegSubReg => {}
42+
43+
ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => {
44+
unreachable!();
45+
}
3746
}
3847
}
3948

49+
// FIXME: We should merge this loop with the above one eventually.
4050
// Index in-edges in reverse order, to match what current tests expect.
4151
// (It's unclear whether this is important or not.)
42-
for pair @ (c, _) in data.constraints.iter().rev() {
52+
53+
for pair @ (c, _) in data
54+
.constraints
55+
.iter()
56+
.rev()
57+
.flat_map(|(c, origin)| c.iter_outlives().map(move |c| (c, origin)))
58+
{
4359
// Only push a var in-edge for `...SubVar` constraints.
4460
match c.kind {
4561
ConstraintKind::VarSubVar | ConstraintKind::RegSubVar => {
46-
in_edges[c.sup.as_var()].push(pair)
62+
in_edges[c.sup.as_var()].push(pair);
4763
}
64+
4865
ConstraintKind::VarSubReg | ConstraintKind::RegSubReg => {}
66+
67+
ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => {
68+
unreachable!();
69+
}
4970
}
5071
}
5172

@@ -58,7 +79,7 @@ impl<'data, 'tcx> IndexedConstraintEdges<'data, 'tcx> {
5879
&self,
5980
region_vid: RegionVid,
6081
dir: EdgeDirection,
61-
) -> &[&'data ConstraintPair<'tcx>] {
82+
) -> &[ConstraintPair<'data, 'tcx>] {
6283
let edges = match dir {
6384
EdgeDirection::Out => &self.out_edges,
6485
EdgeDirection::In => &self.in_edges,

compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ pub(crate) fn resolve<'tcx>(
3434
var_infos: VarInfos<'tcx>,
3535
data: RegionConstraintData<'tcx>,
3636
) -> (LexicalRegionResolutions<'tcx>, Vec<RegionResolutionError<'tcx>>) {
37+
assert!(
38+
data.constraints.iter().all(|(c, _)| match c.kind {
39+
ConstraintKind::VarSubVar
40+
| ConstraintKind::RegSubVar
41+
| ConstraintKind::VarSubReg
42+
| ConstraintKind::RegSubReg => true,
43+
44+
ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => false,
45+
}),
46+
"Every constraint should be decomposed into outlives here"
47+
);
48+
3749
let mut errors = vec![];
3850
let mut resolver = LexicalResolver { region_rels, var_infos, data };
3951
let values = resolver.infer_variable_values(&mut errors);
@@ -279,6 +291,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
279291
// is done, in `collect_errors`.
280292
continue;
281293
}
294+
295+
ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => {
296+
unreachable!()
297+
}
282298
}
283299
}
284300

@@ -575,6 +591,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
575591
*sub_data = VarValue::ErrorValue;
576592
}
577593
}
594+
595+
ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => {
596+
unreachable!()
597+
}
578598
}
579599
}
580600

@@ -852,19 +872,23 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
852872
}
853873

854874
ConstraintKind::RegSubVar => {
855-
let origin = origin.clone();
875+
let origin = (*origin).clone();
856876
state.result.push(RegionAndOrigin { region: c.sub, origin });
857877
}
858878

859879
ConstraintKind::VarSubReg => {
860-
let origin = origin.clone();
880+
let origin = (*origin).clone();
861881
state.result.push(RegionAndOrigin { region: c.sup, origin });
862882
}
863883

864884
ConstraintKind::RegSubReg => panic!(
865885
"cannot reach reg-sub-reg edge in region inference \
866886
post-processing"
867887
),
888+
889+
ConstraintKind::VarEqVar
890+
| ConstraintKind::VarEqReg
891+
| ConstraintKind::RegEqReg => unreachable!(),
868892
}
869893
}
870894
}

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,16 @@ impl<'tcx> InferCtxt<'tcx> {
702702
self.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin, a, b);
703703
}
704704

705+
#[instrument(skip(self), level = "debug")]
706+
pub fn equate_regions(
707+
&self,
708+
origin: SubregionOrigin<'tcx>,
709+
a: ty::Region<'tcx>,
710+
b: ty::Region<'tcx>,
711+
) {
712+
self.inner.borrow_mut().unwrap_region_constraints().make_eqregion(origin, a, b);
713+
}
714+
705715
/// Processes a `Coerce` predicate from the fulfillment context.
706716
/// This is NOT the preferred way to handle coercion, which is to
707717
/// invoke `FnCtxt::coerce` or a similar method (see `coercion.rs`).

compiler/rustc_infer/src/infer/outlives/mod.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Various code related to computing outlives relations.
22
3+
use std::iter;
4+
35
use rustc_data_structures::undo_log::UndoLogs;
46
use rustc_middle::traits::query::{NoSolution, OutlivesBound};
57
use rustc_middle::ty;
@@ -67,14 +69,30 @@ impl<'tcx> InferCtxt<'tcx> {
6769
inner.region_constraint_storage.take().expect("regions already resolved")
6870
};
6971

72+
storage.data.constraints = storage
73+
.data
74+
.constraints
75+
.iter()
76+
.flat_map(|(constraint, origin)| {
77+
constraint.iter_outlives().zip(iter::repeat_with(|| origin.clone()))
78+
})
79+
.collect();
80+
7081
// Filter out any region-region outlives assumptions that are implied by
7182
// coroutine well-formedness.
7283
if self.tcx.sess.opts.unstable_opts.higher_ranked_assumptions {
7384
storage.data.constraints.retain(|(c, _)| match c.kind {
7485
ConstraintKind::RegSubReg => !outlives_env
7586
.higher_ranked_assumptions()
7687
.contains(&ty::OutlivesPredicate(c.sup.into(), c.sub)),
77-
_ => true,
88+
89+
ConstraintKind::VarSubVar
90+
| ConstraintKind::RegSubVar
91+
| ConstraintKind::VarSubReg => true,
92+
93+
ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => {
94+
unreachable!();
95+
}
7896
});
7997
}
8098

compiler/rustc_infer/src/infer/outlives/obligations.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,17 @@ impl<'tcx> InferCtxt<'tcx> {
9898
}
9999
}
100100

101+
pub fn register_region_eq_constraint(
102+
&self,
103+
ty::RegionEqPredicate(r_a, r_b): ty::RegionEqPredicate<'tcx>,
104+
cause: &ObligationCause<'tcx>,
105+
) {
106+
let origin = SubregionOrigin::from_obligation_cause(cause, || {
107+
SubregionOrigin::RelateRegionParamBound(cause.span, None)
108+
});
109+
self.equate_regions(origin, r_a, r_b);
110+
}
111+
101112
pub fn register_region_outlives_constraint(
102113
&self,
103114
ty::OutlivesPredicate(r_a, r_b): ty::RegionOutlivesPredicate<'tcx>,

0 commit comments

Comments
 (0)