-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Tracking issue for member constraints in region inference #61997
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Labels
A-impl-trait
Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.
A-inference
Area: Type inference
A-lifetimes
Area: Lifetimes / regions
A-member-constraints
`#[feature(member_constraints)]`
B-unstable
Blocker: Implemented in the nightly compiler and unstable.
C-tracking-issue
Category: An issue tracking the progress of sth. like the implementation of an RFC
T-lang
Relevant to the language team, which will review and decide on the PR/issue.
Comments
Triage: The first two boxes can be checked and the rustc-guide PR has landed, so this:
is inaccurate now, which is a good thing. :) |
I am beginning work towards stabilizing this. @rustbot claim |
JohnTitor
added a commit
to JohnTitor/rust
that referenced
this issue
May 25, 2021
…raints-61997, r=jackh726 stabilize member constraints Stabilizes the use of "member constraints" in solving `impl Trait` bindings. This is a step towards stabilizing a "MVP" of "named impl Trait". # Member constraint stabilization report | Info | | | --- | --- | | Tracking issue | [rust-lang#61997](rust-lang#61997) | | Implementation history | [rust-lang#61775] | | rustc-dev-guide coverage | [link](https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/member_constraints.html) | | Complications | [rust-lang#61773] | [rust-lang#61775]: rust-lang#61775 [rust-lang#61773]: rust-lang#61773 ## Background Member constraints are an extension to our region solver that was introduced to make async fn region solving tractable. There are used in situations like the following: ```rust fn foo<'a, 'b>(...) -> impl Trait<'a, 'b> { .. } ``` The problem here is that every region R in the hidden type must be equal to *either* `'a` *or* `'b` (or `'static`). This cannot be expressed simply via 'outlives constriants' like `R: 'a`. Therefore, we introduce a 'member constraint' `R member of ['a, 'b]`. These constraints were introduced in [rust-lang#61775]. At the time, we kept them feature gated and used them only for `impl Trait` return types that are derived from `async fn`. The intention, however, was always to support them in other contexts once we had time to gain more experience with them. **In the time since their introduction, we have encountered no surprises or bugs due to these member constraints.** They are tested extensively as part of every async function that involves multiple unrelated lifetimes in its arguments. ## Tests The behavior of member constraints is covered by the following tests: * [`src/test/ui/async-await/multiple-lifetimes`](https://github.com/rust-lang/rust/tree/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/async-await/multiple-lifetimes) -- tests using the async await, which are mostly already stabilized * [`src/test/ui/impl-trait/multiple-lifetimes.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/impl-trait/multiple-lifetimes.rs) * [`src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs) * [`src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs) * [`src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs) These tests cover a number of scenarios: * `-> implTrait<'a, 'b>` with unrelated lifetimes `'a` and `'b`, as described above * `async fn` that returns an `impl Trait` like the previous case, which desugars to a kind of "nested" impl trait like `impl Future<Output = impl Trait<'a, 'b>>` ## Potential concerns There is a potential interaction with `impl Trait` on local variables, described in [rust-lang#61773]. The challenge is that if you have a program like: ```rust= trait Foo<'_> { } impl Foo<'_> for &u32 { } fn bar() { let x: impl Foo<'_> = &44; // let's call the region variable for `'_` `'1` } ``` then we would wind up with `'0 member of ['1, 'static]`, where `'0` is the region variable in the hidden type (`&'0 u32`) and `'1` is the region variable in the bounds `Foo<'1>`. This is tricky because both `'0` and `'1` are being inferred -- so making them equal may have other repercussions. That said, `impl Trait` in bindings are not stable, and the implementation is pretty far from stabilization. Moreover, the difficulty highlighted here is not due to the presence of member constraints -- it's inherent to the design of the language. In other words, stabilizing member constraints does not actually cause us to accept anything that would make this problem any harder. So I don't see this as a blocker to stabilization of member constraints; it is potentially a blocker to stablization of `impl trait` in let bindings.
Dylan-DPC-zz
pushed a commit
to Dylan-DPC-zz/rust
that referenced
this issue
May 26, 2021
…raints-61997, r=jackh726 stabilize member constraints Stabilizes the use of "member constraints" in solving `impl Trait` bindings. This is a step towards stabilizing a "MVP" of "named impl Trait". # Member constraint stabilization report | Info | | | --- | --- | | Tracking issue | [rust-lang#61997](rust-lang#61997) | | Implementation history | [rust-lang#61775] | | rustc-dev-guide coverage | [link](https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/member_constraints.html) | | Complications | [rust-lang#61773] | [rust-lang#61775]: rust-lang#61775 [rust-lang#61773]: rust-lang#61773 ## Background Member constraints are an extension to our region solver that was introduced to make async fn region solving tractable. There are used in situations like the following: ```rust fn foo<'a, 'b>(...) -> impl Trait<'a, 'b> { .. } ``` The problem here is that every region R in the hidden type must be equal to *either* `'a` *or* `'b` (or `'static`). This cannot be expressed simply via 'outlives constriants' like `R: 'a`. Therefore, we introduce a 'member constraint' `R member of ['a, 'b]`. These constraints were introduced in [rust-lang#61775]. At the time, we kept them feature gated and used them only for `impl Trait` return types that are derived from `async fn`. The intention, however, was always to support them in other contexts once we had time to gain more experience with them. **In the time since their introduction, we have encountered no surprises or bugs due to these member constraints.** They are tested extensively as part of every async function that involves multiple unrelated lifetimes in its arguments. ## Tests The behavior of member constraints is covered by the following tests: * [`src/test/ui/async-await/multiple-lifetimes`](https://github.com/rust-lang/rust/tree/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/async-await/multiple-lifetimes) -- tests using the async await, which are mostly already stabilized * [`src/test/ui/impl-trait/multiple-lifetimes.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/impl-trait/multiple-lifetimes.rs) * [`src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs) * [`src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs) * [`src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs) These tests cover a number of scenarios: * `-> implTrait<'a, 'b>` with unrelated lifetimes `'a` and `'b`, as described above * `async fn` that returns an `impl Trait` like the previous case, which desugars to a kind of "nested" impl trait like `impl Future<Output = impl Trait<'a, 'b>>` ## Potential concerns There is a potential interaction with `impl Trait` on local variables, described in [rust-lang#61773]. The challenge is that if you have a program like: ```rust= trait Foo<'_> { } impl Foo<'_> for &u32 { } fn bar() { let x: impl Foo<'_> = &44; // let's call the region variable for `'_` `'1` } ``` then we would wind up with `'0 member of ['1, 'static]`, where `'0` is the region variable in the hidden type (`&'0 u32`) and `'1` is the region variable in the bounds `Foo<'1>`. This is tricky because both `'0` and `'1` are being inferred -- so making them equal may have other repercussions. That said, `impl Trait` in bindings are not stable, and the implementation is pretty far from stabilization. Moreover, the difficulty highlighted here is not due to the presence of member constraints -- it's inherent to the design of the language. In other words, stabilizing member constraints does not actually cause us to accept anything that would make this problem any harder. So I don't see this as a blocker to stabilization of member constraints; it is potentially a blocker to stablization of `impl trait` in let bindings.
Dylan-DPC-zz
pushed a commit
to Dylan-DPC-zz/rust
that referenced
this issue
May 27, 2021
…raints-61997, r=jackh726 stabilize member constraints Stabilizes the use of "member constraints" in solving `impl Trait` bindings. This is a step towards stabilizing a "MVP" of "named impl Trait". # Member constraint stabilization report | Info | | | --- | --- | | Tracking issue | [rust-lang#61997](rust-lang#61997) | | Implementation history | [rust-lang#61775] | | rustc-dev-guide coverage | [link](https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/member_constraints.html) | | Complications | [rust-lang#61773] | [rust-lang#61775]: rust-lang#61775 [rust-lang#61773]: rust-lang#61773 ## Background Member constraints are an extension to our region solver that was introduced to make async fn region solving tractable. There are used in situations like the following: ```rust fn foo<'a, 'b>(...) -> impl Trait<'a, 'b> { .. } ``` The problem here is that every region R in the hidden type must be equal to *either* `'a` *or* `'b` (or `'static`). This cannot be expressed simply via 'outlives constriants' like `R: 'a`. Therefore, we introduce a 'member constraint' `R member of ['a, 'b]`. These constraints were introduced in [rust-lang#61775]. At the time, we kept them feature gated and used them only for `impl Trait` return types that are derived from `async fn`. The intention, however, was always to support them in other contexts once we had time to gain more experience with them. **In the time since their introduction, we have encountered no surprises or bugs due to these member constraints.** They are tested extensively as part of every async function that involves multiple unrelated lifetimes in its arguments. ## Tests The behavior of member constraints is covered by the following tests: * [`src/test/ui/async-await/multiple-lifetimes`](https://github.com/rust-lang/rust/tree/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/async-await/multiple-lifetimes) -- tests using the async await, which are mostly already stabilized * [`src/test/ui/impl-trait/multiple-lifetimes.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/impl-trait/multiple-lifetimes.rs) * [`src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs) * [`src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs) * [`src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs) These tests cover a number of scenarios: * `-> implTrait<'a, 'b>` with unrelated lifetimes `'a` and `'b`, as described above * `async fn` that returns an `impl Trait` like the previous case, which desugars to a kind of "nested" impl trait like `impl Future<Output = impl Trait<'a, 'b>>` ## Potential concerns There is a potential interaction with `impl Trait` on local variables, described in [rust-lang#61773]. The challenge is that if you have a program like: ```rust= trait Foo<'_> { } impl Foo<'_> for &u32 { } fn bar() { let x: impl Foo<'_> = &44; // let's call the region variable for `'_` `'1` } ``` then we would wind up with `'0 member of ['1, 'static]`, where `'0` is the region variable in the hidden type (`&'0 u32`) and `'1` is the region variable in the bounds `Foo<'1>`. This is tricky because both `'0` and `'1` are being inferred -- so making them equal may have other repercussions. That said, `impl Trait` in bindings are not stable, and the implementation is pretty far from stabilization. Moreover, the difficulty highlighted here is not due to the presence of member constraints -- it's inherent to the design of the language. In other words, stabilizing member constraints does not actually cause us to accept anything that would make this problem any harder. So I don't see this as a blocker to stabilization of member constraints; it is potentially a blocker to stablization of `impl trait` in let bindings.
Dylan-DPC-zz
pushed a commit
to Dylan-DPC-zz/rust
that referenced
this issue
May 27, 2021
…raints-61997, r=jackh726 stabilize member constraints Stabilizes the use of "member constraints" in solving `impl Trait` bindings. This is a step towards stabilizing a "MVP" of "named impl Trait". # Member constraint stabilization report | Info | | | --- | --- | | Tracking issue | [rust-lang#61997](rust-lang#61997) | | Implementation history | [rust-lang#61775] | | rustc-dev-guide coverage | [link](https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/member_constraints.html) | | Complications | [rust-lang#61773] | [rust-lang#61775]: rust-lang#61775 [rust-lang#61773]: rust-lang#61773 ## Background Member constraints are an extension to our region solver that was introduced to make async fn region solving tractable. There are used in situations like the following: ```rust fn foo<'a, 'b>(...) -> impl Trait<'a, 'b> { .. } ``` The problem here is that every region R in the hidden type must be equal to *either* `'a` *or* `'b` (or `'static`). This cannot be expressed simply via 'outlives constriants' like `R: 'a`. Therefore, we introduce a 'member constraint' `R member of ['a, 'b]`. These constraints were introduced in [rust-lang#61775]. At the time, we kept them feature gated and used them only for `impl Trait` return types that are derived from `async fn`. The intention, however, was always to support them in other contexts once we had time to gain more experience with them. **In the time since their introduction, we have encountered no surprises or bugs due to these member constraints.** They are tested extensively as part of every async function that involves multiple unrelated lifetimes in its arguments. ## Tests The behavior of member constraints is covered by the following tests: * [`src/test/ui/async-await/multiple-lifetimes`](https://github.com/rust-lang/rust/tree/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/async-await/multiple-lifetimes) -- tests using the async await, which are mostly already stabilized * [`src/test/ui/impl-trait/multiple-lifetimes.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/impl-trait/multiple-lifetimes.rs) * [`src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs) * [`src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs) * [`src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs`](https://github.com/rust-lang/rust/blob/20e032e65007ff1376e8480c1fbdb0a5068028fa/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs) These tests cover a number of scenarios: * `-> implTrait<'a, 'b>` with unrelated lifetimes `'a` and `'b`, as described above * `async fn` that returns an `impl Trait` like the previous case, which desugars to a kind of "nested" impl trait like `impl Future<Output = impl Trait<'a, 'b>>` ## Potential concerns There is a potential interaction with `impl Trait` on local variables, described in [rust-lang#61773]. The challenge is that if you have a program like: ```rust= trait Foo<'_> { } impl Foo<'_> for &u32 { } fn bar() { let x: impl Foo<'_> = &44; // let's call the region variable for `'_` `'1` } ``` then we would wind up with `'0 member of ['1, 'static]`, where `'0` is the region variable in the hidden type (`&'0 u32`) and `'1` is the region variable in the bounds `Foo<'1>`. This is tricky because both `'0` and `'1` are being inferred -- so making them equal may have other repercussions. That said, `impl Trait` in bindings are not stable, and the implementation is pretty far from stabilization. Moreover, the difficulty highlighted here is not due to the presence of member constraints -- it's inherent to the design of the language. In other words, stabilizing member constraints does not actually cause us to accept anything that would make this problem any harder. So I don't see this as a blocker to stabilization of member constraints; it is potentially a blocker to stablization of `impl trait` in let bindings.
This was completed in #84701 |
# for free
to join this conversation on GitHub.
Already have an account?
# to comment
Labels
A-impl-trait
Area: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.
A-inference
Area: Type inference
A-lifetimes
Area: Lifetimes / regions
A-member-constraints
`#[feature(member_constraints)]`
B-unstable
Blocker: Implemented in the nightly compiler and unstable.
C-tracking-issue
Category: An issue tracking the progress of sth. like the implementation of an RFC
T-lang
Relevant to the language team, which will review and decide on the PR/issue.
Uh oh!
There was an error while loading. Please reload this page.
Member constraints
#61775 introduced "member constraints" as part of stabilizing async functions. These extend region inference to accommodate
impl Trait
return types that contain multiple unrelated lifetimes (e.g.,impl Trait<'a, 'b>
where neither'a: 'b
nor'b: 'a
). We decided to introduce a feature gate for other cases until we have time to gain more experience.Learn more
The working of these constraints is described in the rustc-guide -- as of this writing, however, the PR has not yet landed.
Current status
Related issues
impl Trait
(RFC 1522, RFC 1951, RFC 2071) #34511)impl_trait_in_bindings
and pick-constraint region bounds #61773)The text was updated successfully, but these errors were encountered: