Skip to content

Commit c935696

Browse files
committed
Auto merge of #155487 - ShoyuVanilla:canon-ph, r=lcnr
Canonicalize free regions from inputs as placeholders in root univ Context: The box named *coroutine witness Send lifetime requirements now considered by leakcheck* [this roadmap](https://raw.githubusercontent.com/hexcatnl/roadmap/e380fef94b47c02a056b4c8f05124a9db475b990/next-solver.svg) Fixes (only for the next-solver) #106569 Prerequisite of #155749
2 parents 0424cc1 + f2ae894 commit c935696

4 files changed

Lines changed: 60 additions & 15 deletions

File tree

compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -410,14 +410,22 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
410410
}
411411

412412
fn fold_region(&mut self, r: I::Region) -> I::Region {
413+
// We canonicalize free regions from the input into placeholder regions so that
414+
// region constraints created in nested contexts can be propagated back to the
415+
// caller, instead of unifying them.
416+
// See the following Zulip discussion for details:
417+
// https://rust-lang.zulipchat.com/#narrow/channel/364551-t-types.2Ftrait-system-refactor/topic/A.20question.20on.20.23251/near/579240238
413418
let kind = match r.kind() {
414419
ty::ReBound(..) => return r,
415420

416421
// We don't canonicalize `ReStatic` in the `param_env` as we use it
417422
// when checking whether a `ParamEnv` candidate is global.
418423
ty::ReStatic => match self.canonicalize_mode {
419424
CanonicalizeMode::Input(CanonicalizeInputKind::Predicate) => {
420-
CanonicalVarKind::Region(ty::UniverseIndex::ROOT)
425+
CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon(
426+
ty::UniverseIndex::ROOT,
427+
self.variables.len().into(),
428+
))
421429
}
422430
CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv)
423431
| CanonicalizeMode::Response { .. } => return r,
@@ -431,24 +439,41 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
431439
// `ReErased`. We may be able to short-circuit registering region
432440
// obligations if we encounter a `ReErased` on one side, for example.
433441
ty::ReErased | ty::ReError(_) => match self.canonicalize_mode {
434-
CanonicalizeMode::Input(_) => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
442+
CanonicalizeMode::Input(_) => {
443+
CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon(
444+
ty::UniverseIndex::ROOT,
445+
self.variables.len().into(),
446+
))
447+
}
435448
CanonicalizeMode::Response { .. } => return r,
436449
},
437450

438451
ty::ReEarlyParam(_) | ty::ReLateParam(_) => match self.canonicalize_mode {
439-
CanonicalizeMode::Input(_) => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
452+
CanonicalizeMode::Input(_) => {
453+
CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon(
454+
ty::UniverseIndex::ROOT,
455+
self.variables.len().into(),
456+
))
457+
}
440458
CanonicalizeMode::Response { .. } => {
441459
panic!("unexpected region in response: {r:?}")
442460
}
443461
},
444462

445463
ty::RePlaceholder(placeholder) => match self.canonicalize_mode {
446-
// We canonicalize placeholder regions as existentials in query inputs.
447-
CanonicalizeMode::Input(_) => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
464+
CanonicalizeMode::Input(_) => {
465+
CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon(
466+
ty::UniverseIndex::ROOT,
467+
self.variables.len().into(),
468+
))
469+
}
448470
CanonicalizeMode::Response { max_input_universe } => {
449471
// If we have a placeholder region inside of a query, it must be from
450-
// a new universe.
451-
if max_input_universe.can_name(placeholder.universe()) {
472+
// a new universe, unless from the root universe, which is used for
473+
// canonicalization of any free region from the input.
474+
if placeholder.universe() != ty::UniverseIndex::ROOT
475+
&& max_input_universe.can_name(placeholder.universe())
476+
{
452477
panic!("new placeholder in universe {max_input_universe:?}: {r:?}");
453478
}
454479
CanonicalVarKind::PlaceholderRegion(placeholder)
@@ -462,7 +487,12 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
462487
"region vid should have been resolved fully before canonicalization"
463488
);
464489
match self.canonicalize_mode {
465-
CanonicalizeMode::Input(_) => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
490+
CanonicalizeMode::Input(_) => {
491+
CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion::new_anon(
492+
ty::UniverseIndex::ROOT,
493+
self.variables.len().into(),
494+
))
495+
}
466496
CanonicalizeMode::Response { .. } => {
467497
CanonicalVarKind::Region(self.delegate.universe_of_lt(vid).unwrap())
468498
}

compiler/rustc_next_trait_solver/src/canonical/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,18 @@ where
211211
} else {
212212
// For placeholders which were already part of the input, we simply map this
213213
// universal bound variable back the placeholder of the input.
214+
//
215+
// For `CanonicalVarKind::PlaceholderRegion`, this differs slightly: we
216+
// canonicalize all free regions from the input into placeholders. This is
217+
// unlike types or consts, where only input placeholders remain placeholders
218+
// in the canonical form.
219+
//
220+
// We can still map these back to the original input regions, as we
221+
// just instantiate the canonical variable with its corresponding
222+
// `original_value`.
223+
//
224+
// For more information on why we canonicalize all input regions as
225+
// placeholders, see the comment in `Canonicalizer::fold_region`.
214226
original_values[kind.expect_placeholder_index()]
215227
}
216228
})

tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr renamed to tests/ui/implied-bounds/normalization-preserve-equality.borrowck_current.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: lifetime may not live long enough
2-
--> $DIR/normalization-preserve-equality.rs:24:1
2+
--> $DIR/normalization-preserve-equality.rs:27:1
33
|
44
LL | fn test_borrowck<'a, 'b>(_: (<Equal<'a, 'b> as Trait>::Ty, Equal<'a, 'b>)) {
55
| ^^^^^^^^^^^^^^^^^--^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -11,7 +11,7 @@ LL | fn test_borrowck<'a, 'b>(_: (<Equal<'a, 'b> as Trait>::Ty, Equal<'a, 'b>))
1111
= help: consider adding the following bound: `'a: 'b`
1212

1313
error: lifetime may not live long enough
14-
--> $DIR/normalization-preserve-equality.rs:24:1
14+
--> $DIR/normalization-preserve-equality.rs:27:1
1515
|
1616
LL | fn test_borrowck<'a, 'b>(_: (<Equal<'a, 'b> as Trait>::Ty, Equal<'a, 'b>)) {
1717
| ^^^^^^^^^^^^^^^^^--^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/ui/implied-bounds/normalization-preserve-equality.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
// Both revisions should pass. `borrowck` revision is a bug!
1+
// All the revisions should pass. `borrowck_current` revision is a bug!
22
//
3-
//@ revisions: wfcheck borrowck
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
//@ revisions: wfcheck borrowck_current borrowck_next
45
//@ [wfcheck] check-pass
5-
//@ [borrowck] check-fail
6-
//@ [borrowck] known-bug: #106569
6+
//@ [borrowck_current] check-fail
7+
//@ [borrowck_current] known-bug: #106569
8+
//@ [borrowck_next] compile-flags: -Znext-solver
9+
//@ [borrowck_next] check-pass
710

811
struct Equal<'a, 'b>(&'a &'b (), &'b &'a ()); // implies 'a == 'b
912

@@ -20,7 +23,7 @@ trait WfCheckTrait {}
2023
#[cfg(wfcheck)]
2124
impl<'a, 'b> WfCheckTrait for (<Equal<'a, 'b> as Trait>::Ty, Equal<'a, 'b>) {}
2225

23-
#[cfg(borrowck)]
26+
#[cfg(any(borrowck_current, borrowck_next))]
2427
fn test_borrowck<'a, 'b>(_: (<Equal<'a, 'b> as Trait>::Ty, Equal<'a, 'b>)) {
2528
let _ = None::<Equal<'a, 'b>>;
2629
}

0 commit comments

Comments
 (0)