Skip to content

Commit 4119383

Browse files
committed
Make region equality emits Eq constraints
1 parent 25a54d4 commit 4119383

32 files changed

Lines changed: 650 additions & 199 deletions

File tree

compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,8 @@ 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_inner = |c: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match c.kind
455+
{
455456
ConstraintKind::RegSubReg
456457
if ((exact && c.sup == placeholder_region)
457458
|| (!exact && regions_the_same(c.sup, placeholder_region)))
@@ -467,7 +468,56 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>(
467468
{
468469
Some((c.sub, cause.clone()))
469470
}
470-
_ => None,
471+
ConstraintKind::RegSubReg
472+
| ConstraintKind::VarSubReg
473+
| ConstraintKind::VarSubVar
474+
| ConstraintKind::RegSubVar => None,
475+
ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => {
476+
unreachable!();
477+
}
478+
};
479+
let mut check = |c: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| match c.kind {
480+
ConstraintKind::VarSubVar
481+
| ConstraintKind::RegSubVar
482+
| ConstraintKind::VarSubReg
483+
| ConstraintKind::RegSubReg => check_inner(c, cause, exact),
484+
485+
ConstraintKind::VarEqVar => check_inner(
486+
&Constraint { kind: ConstraintKind::VarSubVar, sub: c.sub, sup: c.sup },
487+
cause,
488+
exact,
489+
)
490+
.or_else(|| {
491+
check_inner(
492+
&Constraint { kind: ConstraintKind::VarSubVar, sub: c.sup, sup: c.sub },
493+
cause,
494+
exact,
495+
)
496+
}),
497+
ConstraintKind::VarEqReg => check_inner(
498+
&Constraint { kind: ConstraintKind::VarSubReg, sub: c.sub, sup: c.sup },
499+
cause,
500+
exact,
501+
)
502+
.or_else(|| {
503+
check_inner(
504+
&Constraint { kind: ConstraintKind::RegSubVar, sub: c.sup, sup: c.sub },
505+
cause,
506+
exact,
507+
)
508+
}),
509+
ConstraintKind::RegEqReg => check_inner(
510+
&Constraint { kind: ConstraintKind::RegSubReg, sub: c.sub, sup: c.sup },
511+
cause,
512+
exact,
513+
)
514+
.or_else(|| {
515+
check_inner(
516+
&Constraint { kind: ConstraintKind::RegSubReg, sub: c.sup, sup: c.sub },
517+
cause,
518+
exact,
519+
)
520+
}),
471521
};
472522

473523
let mut find_culprit = |exact_match: bool| {

compiler/rustc_borrowck/src/type_check/constraint_conversion.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_middle::ty::{
1212
};
1313
use rustc_span::Span;
1414
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
15+
use smallvec::{SmallVec, smallvec};
1516
use tracing::{debug, instrument};
1617

1718
use crate::constraints::OutlivesConstraint;
@@ -70,12 +71,21 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
7071

7172
#[instrument(skip(self), level = "debug")]
7273
pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
73-
let QueryRegionConstraints { outlives, assumptions } = query_constraints;
74+
let QueryRegionConstraints { constraints, assumptions } = query_constraints;
7475
let assumptions =
7576
elaborate::elaborate_outlives_assumptions(self.infcx.tcx, assumptions.iter().copied());
7677

77-
for &(predicate, constraint_category) in outlives {
78-
self.convert(predicate, constraint_category, &assumptions);
78+
for &(constraint, constraint_category) in constraints {
79+
match constraint {
80+
ty::RegionConstraint::Outlives(predicate) => {
81+
self.convert(predicate, constraint_category, &assumptions);
82+
}
83+
ty::RegionConstraint::Eq(predicate) => {
84+
let [predicate1, predicate2] = predicate.into_bidirectional_outlives();
85+
self.convert(predicate1, constraint_category, &assumptions);
86+
self.convert(predicate2, constraint_category, &assumptions);
87+
}
88+
}
7989
}
8090
}
8191

@@ -292,8 +302,24 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
292302
) {
293303
Ok(TypeOpOutput { output: ty, constraints, .. }) => {
294304
// 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());
305+
if let Some(QueryRegionConstraints { constraints, assumptions: _ }) = constraints {
306+
next_outlives_predicates.extend(
307+
constraints
308+
.iter()
309+
.map(|(constraint, category)| -> SmallVec<[_; 2]> {
310+
match *constraint {
311+
ty::RegionConstraint::Outlives(outlives) => {
312+
smallvec![(outlives, *category)]
313+
}
314+
ty::RegionConstraint::Eq(eq) => {
315+
let [outlives1, outlives2] =
316+
eq.into_bidirectional_outlives();
317+
smallvec![(outlives1, *category), (outlives2, *category)]
318+
}
319+
}
320+
})
321+
.flatten(),
322+
);
297323
}
298324
ty
299325
}

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

Lines changed: 38 additions & 24 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,17 @@ 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+
match constraint {
193+
ty::RegionConstraint::Outlives(predicate) => {
194+
let predicate = instantiate_value(self.tcx, &result_args, *predicate);
195+
self.register_outlives_constraint(predicate, cause);
196+
}
197+
ty::RegionConstraint::Eq(predicate) => {
198+
let predicate = instantiate_value(self.tcx, &result_args, *predicate);
199+
self.register_region_eq_constraint(predicate, cause);
200+
}
201+
}
194202
}
195203

196204
for assumption in &query_response.value.region_constraints.assumptions {
@@ -277,14 +285,11 @@ impl<'tcx> InferCtxt<'tcx> {
277285
}
278286

279287
(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`.
281288
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));
289+
output_query_region_constraints.constraints.push((
290+
ty::RegionEqPredicate(v_o.into(), v_r).into(),
291+
constraint_category,
292+
));
288293
}
289294
}
290295

@@ -311,13 +316,12 @@ impl<'tcx> InferCtxt<'tcx> {
311316
}
312317

313318
// ...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| {
319+
output_query_region_constraints.constraints.extend(
320+
query_response.value.region_constraints.constraints.iter().filter_map(|&r_c| {
316321
let r_c = instantiate_value(self.tcx, &result_args, r_c);
317322

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 }
323+
// Screen out `'a: 'a` or `'a == 'a` cases.
324+
if r_c.0.is_trivial() { None } else { Some(r_c) }
321325
}),
322326
);
323327

@@ -603,28 +607,38 @@ impl<'tcx> InferCtxt<'tcx> {
603607
pub fn make_query_region_constraints<'tcx>(
604608
outlives_obligations: Vec<TypeOutlivesConstraint<'tcx>>,
605609
region_constraints: &RegionConstraintData<'tcx>,
606-
assumptions: Vec<ty::ArgOutlivesPredicate<'tcx>>,
610+
assumptions: Vec<ty::RegionConstraint<'tcx>>,
607611
) -> QueryRegionConstraints<'tcx> {
608612
let RegionConstraintData { constraints, verifys } = region_constraints;
609613

610614
assert!(verifys.is_empty());
611615

612616
debug!(?constraints);
613617

614-
let outlives: Vec<_> = constraints
618+
let constraints: Vec<_> = constraints
615619
.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())
620+
.map(|(c, origin)| match c.kind {
621+
ConstraintKind::VarSubVar
622+
| ConstraintKind::RegSubVar
623+
| ConstraintKind::VarSubReg
624+
| ConstraintKind::RegSubReg => {
625+
// Swap regions because we are going from sub (<=) to outlives (>=).
626+
let constraint = ty::OutlivesPredicate(c.sup.into(), c.sub).into();
627+
(constraint, origin.to_constraint_category())
628+
}
629+
630+
ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => {
631+
let constraint = ty::RegionEqPredicate(c.sup, c.sub).into();
632+
(constraint, origin.to_constraint_category())
633+
}
620634
})
621635
.chain(outlives_obligations.into_iter().map(|obl| {
622636
(
623-
ty::OutlivesPredicate(obl.sup_type.into(), obl.sub_region),
637+
ty::OutlivesPredicate(obl.sup_type.into(), obl.sub_region).into(),
624638
obl.origin.to_constraint_category(),
625639
)
626640
}))
627641
.collect();
628642

629-
QueryRegionConstraints { outlives, assumptions }
643+
QueryRegionConstraints { constraints, assumptions }
630644
}

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

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,18 @@ impl<'data, 'tcx> IndexedConstraintEdges<'data, 'tcx> {
3030
for pair @ (c, _) in &data.constraints {
3131
// Only push a var out-edge for `VarSub...` constraints.
3232
match c.kind {
33-
ConstraintKind::VarSubVar | ConstraintKind::VarSubReg => {
34-
out_edges[c.sub.as_var()].push(pair)
33+
ConstraintKind::VarSubVar
34+
| ConstraintKind::VarSubReg
35+
| ConstraintKind::VarEqReg => {
36+
out_edges[c.sub.as_var()].push(pair);
3537
}
36-
ConstraintKind::RegSubVar | ConstraintKind::RegSubReg => {}
38+
ConstraintKind::VarEqVar => {
39+
out_edges[c.sub.as_var()].push(pair);
40+
out_edges[c.sup.as_var()].push(pair);
41+
}
42+
ConstraintKind::RegSubVar
43+
| ConstraintKind::RegSubReg
44+
| ConstraintKind::RegEqReg => {}
3745
}
3846
}
3947

@@ -43,9 +51,18 @@ impl<'data, 'tcx> IndexedConstraintEdges<'data, 'tcx> {
4351
// Only push a var in-edge for `...SubVar` constraints.
4452
match c.kind {
4553
ConstraintKind::VarSubVar | ConstraintKind::RegSubVar => {
46-
in_edges[c.sup.as_var()].push(pair)
54+
in_edges[c.sup.as_var()].push(pair);
55+
}
56+
ConstraintKind::VarEqReg => {
57+
in_edges[c.sub.as_var()].push(pair);
58+
}
59+
ConstraintKind::VarEqVar => {
60+
in_edges[c.sub.as_var()].push(pair);
61+
in_edges[c.sup.as_var()].push(pair);
4762
}
48-
ConstraintKind::VarSubReg | ConstraintKind::RegSubReg => {}
63+
ConstraintKind::VarSubReg
64+
| ConstraintKind::RegSubReg
65+
| ConstraintKind::RegEqReg => {}
4966
}
5067
}
5168

0 commit comments

Comments
 (0)