Skip to content

Commit cd7cbe8

Browse files
committed
Auto merge of rust-lang#142071 - lcnr:revealing-use, r=compiler-errors
`apply_member_constraints`: fix placeholder check Checking whether the member region is *an existential region from a higher universe* is just wrong and I am pretty sure we've added that check by accident as the naming was just horribly confusing before rust-lang#140466. I've encountered this issue separately while working on rust-lang#139587, but feel like it's probably easier to separately FCP this change. This allows the following code to compile ```rust trait Proj<'a> { type Assoc; } impl<'a, 'b, F: FnOnce() -> &'b ()> Proj<'a> for F { type Assoc = (); } fn is_proj<F: for<'a> Proj<'a>>(f: F) {} fn define<'a>() -> impl Sized + use<'a> { // This adds a use of `opaque::<'a>` with hidden type `&'unconstrained_b ()`. // 'unconstrained_b is an inference variable from a higher universe as it gets // created inside of the binder of `F: for<'a> Proj<'a>`. This previously // caused us to not apply member constraints. We now do, constraining // it to `'a`. is_proj(define::<'a>); &() } fn main() {} ``` This should not be breaking change, even in theory. Applying member constraints is incomplete in rare circumstances which means that applying them in more cases can cause spurious errors, cc rust-lang#140569/rust-lang#142073. However, as we always skipped these member regions in `apply_member_constraints` the skipped region is guaranteed to cause an error in `check_member_constraints` later on.
2 parents 8b1889c + cde14e6 commit cd7cbe8

File tree

4 files changed

+72
-1
lines changed

4 files changed

+72
-1
lines changed

compiler/rustc_borrowck/src/handle_placeholders.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ impl RegionTracker {
103103
self.max_nameable_universe
104104
}
105105

106+
pub(crate) fn max_placeholder_universe_reached(self) -> UniverseIndex {
107+
self.max_placeholder_universe_reached
108+
}
109+
106110
fn merge_min_max_seen(&mut self, other: &Self) {
107111
self.max_placeholder_universe_reached = std::cmp::max(
108112
self.max_placeholder_universe_reached,

compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
713713

714714
// If the member region lives in a higher universe, we currently choose
715715
// the most conservative option by leaving it unchanged.
716-
if !self.max_nameable_universe(scc).is_root() {
716+
if !self.max_placeholder_universe_reached(scc).is_root() {
717717
return;
718718
}
719719

@@ -1376,6 +1376,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
13761376
self.scc_annotations[scc].max_nameable_universe()
13771377
}
13781378

1379+
pub(crate) fn max_placeholder_universe_reached(
1380+
&self,
1381+
scc: ConstraintSccIndex,
1382+
) -> UniverseIndex {
1383+
self.scc_annotations[scc].max_placeholder_universe_reached()
1384+
}
1385+
13791386
/// Checks the final value for the free region `fr` to see if it
13801387
/// grew too large. In particular, examine what `end(X)` points
13811388
/// wound up in `fr`'s final value; for each `end(X)` where `X !=
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//@ check-pass
2+
//@ revisions: current next
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
//@[next] compile-flags: -Znext-solver
5+
6+
trait Proj<'a> {
7+
type Assoc;
8+
}
9+
10+
impl<'a, 'b, F: FnOnce() -> &'b ()> Proj<'a> for F {
11+
type Assoc = ();
12+
}
13+
14+
fn is_proj<F: for<'a> Proj<'a>>(f: F) {}
15+
16+
fn define<'a>() -> impl Sized + use<'a> {
17+
// This defines the RPIT to `&'unconstrained_b ()`, an inference
18+
// variable which is in a higher universe as gets created inside
19+
// of the binder of `F: for<'a> Proj<'a>`. This previously caused
20+
// us to not apply member constraints.
21+
//
22+
// This was unnecessary. It is totally acceptable for member regions
23+
// to be able to name placeholders from higher universes, as long as
24+
// they don't actually do so.
25+
is_proj(define::<'a>);
26+
&()
27+
}
28+
29+
fn main() {}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//@ check-pass
2+
3+
// Unlike `non-root-universe-existential-1.rs` this previously
4+
// compiled as it simply didn't define the hidden type of
5+
// `impl Iterator` when projecting through it. We will do so
6+
// with the new solver. Further minimizing this is challenging.
7+
8+
struct Type(Vec<Type>);
9+
enum TypeTreeValueIter<'a, T> {
10+
Once(T),
11+
Ref(&'a ()),
12+
}
13+
14+
impl<'a, T> Iterator for TypeTreeValueIter<'a, T> {
15+
type Item = T;
16+
17+
fn next(&mut self) -> Option<Self::Item> {
18+
loop {}
19+
}
20+
}
21+
22+
fn item<I: Iterator<Item: Iterator>>(x: I) -> <I::Item as Iterator>::Item {
23+
loop {}
24+
}
25+
26+
fn get_type_tree_values<'a>(ty: &'a Type) -> impl Iterator<Item = &'a Type> {
27+
let _: &'a Type = item(std::iter::once(ty).map(get_type_tree_values));
28+
TypeTreeValueIter::<'a, &'a Type>::Once(ty)
29+
}
30+
31+
fn main() {}

0 commit comments

Comments
 (0)