Skip to content

Commit 3a8fea6

Browse files
committed
member constraints: support existential regions from non-root universes
1 parent 6297f53 commit 3a8fea6

File tree

3 files changed

+64
-8
lines changed

3 files changed

+64
-8
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ fn apply_member_constraints<'tcx>(
311311
defining_use.hidden_type.ty.visit_with(&mut visitor);
312312
}
313313

314+
debug!(?member_constraints);
314315
for scc_a in rcx.constraint_sccs.all_sccs() {
315316
debug!(?scc_a);
316317
for &scc_b in rcx.constraint_sccs.successors(scc_a) {
@@ -324,18 +325,12 @@ fn apply_member_constraints<'tcx>(
324325
}
325326
}
326327

328+
#[instrument(level = "debug", skip(rcx))]
327329
fn apply_member_constraint<'tcx>(
328330
rcx: &mut RegionCtxt<'_, 'tcx>,
329331
member: ConstraintSccIndex,
330332
arg_regions: &[RegionVid],
331333
) {
332-
// If the member region lives in a higher universe, we currently choose
333-
// the most conservative option by leaving it unchanged.
334-
if !rcx.annotations[member].min_universe().is_root() {
335-
debug!("member not in root universe");
336-
return;
337-
}
338-
339334
// The existing value of `'member` is a lower-bound. If its is already larger than
340335
// some universal region, we cannot equate it with that region. Said differently, we
341336
// ignore choice regions which are smaller than this member region.
@@ -424,7 +419,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for CollectMemberConstraintsVisitor<'_, '_,
424419
//
425420
// If there's a unique minimum choice, we emit a `'member: 'min_choice` constraint.
426421
// Note that we do not require the two regions to be equal... TODO examples
427-
#[instrument(level = "debug", skip(self))]
428422
fn visit_region(&mut self, r: Region<'tcx>) {
429423
match r.kind() {
430424
ty::ReBound(..) => return,
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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() {}
30+
31+
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. We didn't attempt to define the hidden type of
5+
// `impl Iterator` when projecting through it. We now do. Further
6+
// 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)