Skip to content

add member constraints tests #145050

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//@ check-pass
// FIXME(-Znext-solver): enable this test

trait Id {
type This;
}
impl<T> Id for T {
type This = T;
}

// We have two member constraints here:
//
// - 'unconstrained member ['a, 'static]
// - 'unconstrained member ['static]
//
// Applying the first constraint results in `'unconstrained: 'a`
// while the second then adds `'unconstrained: 'static`. If applying
// member constraints were to require the member region equal to the
// choice region, applying the first constraint first and then the
// second would result in a `'a: 'static` requirement.
fn test<'a>() -> impl Id<This = impl Sized + use<>> + use<'a> {
&()
}
fn main() {}
21 changes: 21 additions & 0 deletions tests/ui/impl-trait/member-constraints/incomplete-constraint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//@ check-pass
// FIXME(-Znext-solver): enable this test

// These functions currently do not normalize the opaque type but will do
// so in the future. At this point we've got a new use of the opaque with fully
// universal arguments but for which lifetimes in the hidden type are unconstrained.
//
// Applying the member constraints would then incompletely infer `'unconstrained` to `'static`.
fn new_defining_use<F: FnOnce(T) -> R, T, R>(_: F) {}

fn rpit1<'a, 'b: 'b>(x: &'b ()) -> impl Sized + use<'a, 'b> {
new_defining_use(rpit1::<'a, 'b>);
x
}

struct Inv<'a, 'b>(*mut (&'a (), &'b ()));
fn rpit2<'a>(_: ()) -> impl Sized + use<'a> {
new_defining_use(rpit2::<'a>);
Inv::<'a, 'static>(std::ptr::null_mut())
}
fn main() {}
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
// Nested impl-traits can impose different member constraints on the same region variable.

//@ check-pass
// FIXME(-Znext-solver): enable this test

trait Cap<'a> {}
impl<T> Cap<'_> for T {}

// Assuming the hidden type is `[&'?15 u8; 1]`, we have two distinct member constraints:
// - '?15 member ['static, 'a, 'b] // from outer impl-trait
// - '?15 member ['static, 'a] // from inner impl-trait
// To satisfy both we can only choose 'a.
// To satisfy both we can only choose 'a. Concretely, first member constraint requires ?15
// to outlive at least 'b while the second requires ?15 to outlive 'a. As 'a outlives 'b we
// end up with 'a as the final member region.
fn pass_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a>> + Cap<'b>
where
's: 'a,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@ ignore-compare-mode-next-solver (explicit revisions)
//@ check-pass

// We've got `'0 member ['a, 'b, 'static]` and `'1 member ['a, 'b, 'static]`.
//
// As '0 gets outlived by 'a - its "upper bound" - the only applicable choice
// region is 'a.
//
// '1 has to outlive 'b so the only applicable choice regions are 'b and 'static.
// Considering this member constraint by itself would choose 'b as it is the
// smaller of the two regions.
//
// However, this is only the case when ignoring the member constraint on '0.
// After applying this constraint and requiring '0 to outlive 'a. As '1 outlives
// '0, the region 'b is no longer an applicable choice region for '1 as 'b does
// does not outlive 'a. We would therefore choose 'static.
//
// This means applying member constraints is order dependent. We handle this by
// first applying member constraints for regions 'x and then consider the resulting
// constraints when applying member constraints for regions 'y with 'y: 'x.
fn with_constraints<'r0, 'r1, 'a, 'b>() -> *mut (&'r0 (), &'r1 ())
where
'r1: 'r0,
'a: 'r0,
'r1: 'b,
{
loop {}
}
fn foo<'a, 'b>() -> impl Sized + use<'a, 'b> {
with_constraints::<'_, '_, 'a, 'b>()
}
fn main() {}
18 changes: 18 additions & 0 deletions tests/ui/impl-trait/no-anonymize-regions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//@ check-pass
// FIXME(-Znext-solver): enable this test

// A regression test for an error in `redis` while working on #139587.
//
// We check for structural equality when adding defining uses of opaques.
// In this test one defining use had anonymized regions while the other
// one did not, causing an error.
struct W<T>(T);
fn constrain<F: FnOnce(T) -> R, T, R>(f: F) -> R {
loop {}
}
fn foo<'a>(x: for<'b> fn(&'b ())) -> impl Sized + use<'a> {
let mut r = constrain(foo::<'_>);
r = W(x);
r
}
fn main() {}
Loading