-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
typeck: Prohibit RPIT types that inherit lifetimes #62849
typeck: Prohibit RPIT types that inherit lifetimes #62849
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
@bors try (for crater) |
typeck: Prohibit RPIT types that inherit lifetimes Part of #61949. This PR prohibits return position `impl Trait` types that "inherit lifetimes" from the parent scope. The intent is to forbid cases that are challenging until they can be addressed properly. cc @nikomatsakis
☀️ Try build successful - checks-azure |
@craterbot run mode=check-only |
@@ -0,0 +1,8 @@ | |||
error: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we should try to give some clue for how to workaround this -- this is basically a rustc bug.
In the case of Self
, the suggestion would be to write the Self
type explicitly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've dug around for a bit and I've not been able to find a way to determine if the return type was originally Self
from here. I'm happy to add a suggestion if anyone knows a way to determine this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At minimum we could just -- for this particular issue -- give it an error code and direct them to some chapter in the async book where we explain in more depth (in the extended explanation). But we'd need a link first. Maybe we can just file a follow-up issue on the matter to improve diagnostics.
@craterbot run mode=check-only |
🚨 Error: missing start toolchain 🆘 If you have any trouble with Crater please ping |
Hey! This is a ping from triage, we would like to know if you @davidtwco could give us a few more minutes to update here by fixing the conflicting files so we can move forward. Thanks. @rustbot modify labels to +S-waiting-on-author, -S-waiting-on-review |
62f89e0
to
686de3a
Compare
@edmilsonefs thanks, I've resolved the conflict. |
@bors try |
typeck: Prohibit RPIT types that inherit lifetimes Part of #61949. This PR prohibits return position `impl Trait` types that "inherit lifetimes" from the parent scope. The intent is to forbid cases that are challenging until they can be addressed properly. cc @nikomatsakis
☀️ Try build successful - checks-azure |
@craterbot run mode=check-only |
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
🎉 Experiment
|
This comment has been minimized.
This comment has been minimized.
@bors retry rolled up (oops, forgot to adjust prio) |
This comment has been minimized.
This comment has been minimized.
Rollup of 10 pull requests Successful merges: - #62760 (Deduplicate error messages in `librsctc_mir`) - #62849 (typeck: Prohibit RPIT types that inherit lifetimes) - #63383 (`async fn` lifetime elision tests) - #63421 (Implement Clone, Display for ascii::EscapeDefault) - #63459 (syntax: account for CVarArgs being in the argument list.) - #63475 (Bring back suggestion for splitting `<-` into `< -`) - #63485 (ci: move mirrors to their standalone bucket) - #63486 (Document `From` trait for `BinaryHeap`) - #63488 (improve DiagnosticBuilder docs) - #63493 (Remove unneeded comment in src/libcore/hash/mod.rs) Failed merges: r? @ghost
…imes, r=nikomatsakis typeck: Prohibit RPIT types that inherit lifetimes Part of rust-lang#61949. This PR prohibits return position `impl Trait` types that "inherit lifetimes" from the parent scope. The intent is to forbid cases that are challenging until they can be addressed properly. cc @nikomatsakis
…imes, r=nikomatsakis typeck: Prohibit RPIT types that inherit lifetimes Part of rust-lang#61949. This PR prohibits return position `impl Trait` types that "inherit lifetimes" from the parent scope. The intent is to forbid cases that are challenging until they can be addressed properly. cc @nikomatsakis
⌛ Testing commit 861d1bb with merge ade62304ed223496e69511fa5fb9b83420b7d5c9... |
…imes, r=nikomatsakis typeck: Prohibit RPIT types that inherit lifetimes Part of rust-lang#61949. This PR prohibits return position `impl Trait` types that "inherit lifetimes" from the parent scope. The intent is to forbid cases that are challenging until they can be addressed properly. cc @nikomatsakis
@bors retry rolled up. |
Rollup of 17 pull requests Successful merges: - #62760 (Deduplicate error messages in `librsctc_mir`) - #62849 (typeck: Prohibit RPIT types that inherit lifetimes) - #63383 (`async fn` lifetime elision tests) - #63421 (Implement Clone, Display for ascii::EscapeDefault) - #63459 (syntax: account for CVarArgs being in the argument list.) - #63475 (Bring back suggestion for splitting `<-` into `< -`) - #63485 (ci: move mirrors to their standalone bucket) - #63486 (Document `From` trait for `BinaryHeap`) - #63488 (improve DiagnosticBuilder docs) - #63493 (Remove unneeded comment in src/libcore/hash/mod.rs) - #63499 (handle elision in async fn correctly) - #63501 (use `ParamName` to track in-scope lifetimes instead of Ident) - #63508 (Do not ICE when synthesizing spans falling inside unicode chars) - #63511 (ci: add a check for clock drift) - #63512 (Provide map_ok and map_err method for Poll<Option<Result<T, E>>>) - #63529 (RELEASES.md: ? is one of three Kleene operators) - #63530 (Fix typo in error message.) Failed merges: r? @ghost
Rollup of 17 pull requests Successful merges: - #62760 (Deduplicate error messages in `librsctc_mir`) - #62849 (typeck: Prohibit RPIT types that inherit lifetimes) - #63383 (`async fn` lifetime elision tests) - #63421 (Implement Clone, Display for ascii::EscapeDefault) - #63459 (syntax: account for CVarArgs being in the argument list.) - #63475 (Bring back suggestion for splitting `<-` into `< -`) - #63485 (ci: move mirrors to their standalone bucket) - #63486 (Document `From` trait for `BinaryHeap`) - #63488 (improve DiagnosticBuilder docs) - #63493 (Remove unneeded comment in src/libcore/hash/mod.rs) - #63499 (handle elision in async fn correctly) - #63501 (use `ParamName` to track in-scope lifetimes instead of Ident) - #63508 (Do not ICE when synthesizing spans falling inside unicode chars) - #63511 (ci: add a check for clock drift) - #63512 (Provide map_ok and map_err method for Poll<Option<Result<T, E>>>) - #63529 (RELEASES.md: ? is one of three Kleene operators) - #63530 (Fix typo in error message.) Failed merges: r? @ghost
…amertj Stabilize `async_await` in Rust 1.39.0 Here we stabilize: - free and inherent `async fn`s, - the `<expr>.await` expression form, - and the `async move? { ... }` block form. Closes rust-lang#62149. Closes rust-lang#50547. All the blockers are now closed. <details> - [x] FCP in rust-lang#62149 - [x] rust-lang#61949; PR in rust-lang#62849. - [x] rust-lang#62517; PR in rust-lang#63376. - [x] rust-lang#63225; PR in rust-lang#63501 - [x] rust-lang#63388; PR in rust-lang#63499 - [x] rust-lang#63500; PR in rust-lang#63501 - [x] rust-lang#62121 (comment) - [x] Some tests for control flow (PR rust-lang#63387): - `?` - `return` in `async` blocks - `break` - [x] rust-lang#61775 (comment), i.e. tests for rust-lang#60944 with `async fn`s instead). PR in rust-lang#63383 </details> r? @cramertj
Stabilize `impl_trait_projections` Closes rust-lang#115659 ## TL;DR: This allows us to mention `Self` and `T::Assoc` in async fn and return-position `impl Trait`, as you would expect you'd be able to. Some examples: ```rust #![feature(return_position_impl_trait_in_trait, async_fn_in_trait)] // (just needed for final tests below) // ---------------------------------------- // struct Wrapper<'a, T>(&'a T); impl Wrapper<'_, ()> { async fn async_fn() -> Self { //^ Previously rejected because it returns `-> Self`, not `-> Wrapper<'_, ()>`. Wrapper(&()) } fn impl_trait() -> impl Iterator<Item = Self> { //^ Previously rejected because it mentions `Self`, not `Wrapper<'_, ()>`. std::iter::once(Wrapper(&())) } } // ---------------------------------------- // trait Trait<'a> { type Assoc; fn new() -> Self::Assoc; } impl Trait<'_> for () { type Assoc = (); fn new() {} } impl<'a, T: Trait<'a>> Wrapper<'a, T> { async fn mk_assoc() -> T::Assoc { //^ Previously rejected because `T::Assoc` doesn't mention `'a` in the HIR, // but ends up resolving to `<T as Trait<'a>>::Assoc`, which does rely on `'a`. // That's the important part -- the elided trait. T::new() } fn a_few_assocs() -> impl Iterator<Item = T::Assoc> { //^ Previously rejected for the same reason [T::new(), T::new(), T::new()].into_iter() } } // ---------------------------------------- // trait InTrait { async fn async_fn() -> Self; fn impl_trait() -> impl Iterator<Item = Self>; } impl InTrait for &() { async fn async_fn() -> Self { &() } //^ Previously rejected just like inherent impls fn impl_trait() -> impl Iterator<Item = Self> { //^ Previously rejected just like inherent impls [&()].into_iter() } } ``` ## Technical: Lifetimes in return-position `impl Trait` (and `async fn`) are duplicated as early-bound generics local to the opaque in order to make sure we are able to substitute any late-bound lifetimes from the function in the opaque's hidden type. (The [dev guide](https://rustc-dev-guide.rust-lang.org/return-position-impl-trait-in-trait.html#aside-opaque-lifetime-duplication) has a small section about why this is necessary -- this was written for RPITITs, but it applies to all RPITs) Prior to rust-lang#103491, all of the early-bound lifetimes not local to the opaque were replaced with `'static` to avoid issues where relating opaques caused their *non-captured* lifetimes to be related. This `'static` replacement led to strange and possibly unsound behaviors (rust-lang#61949 (comment)) (rust-lang#53613) when referencing the `Self` type alias in an impl or indirectly referencing a lifetime parameter via a projection type (via a `T::Assoc` projection without an explicit trait), since lifetime resolution is performed on the HIR, when neither `T::Assoc`-style projections or `Self` in impls are expanded. Therefore an error was implemented in rust-lang#62849 to deny this subtle behavior as a known limitation of the compiler. It was attempted by `@cjgillot` to fix this in rust-lang#91403, which was subsequently unlanded. Then it was re-attempted to much success (🎉) in rust-lang#103491, which is where we currently are in the compiler. The PR above (rust-lang#103491) fixed this issue technically by *not* replacing the opaque's parent lifetimes with `'static`, but instead using variance to properly track which lifetimes are captured and are not. The PR gated any of the "side-effects" of the PR behind a feature gate (`impl_trait_projections`) presumably to avoid having to involve T-lang or T-types in the PR as well. `@cjgillot` can clarify this if I'm misunderstanding what their intention was with the feature gate. Since we're not replacing (possibly *invariant*!) lifetimes with `'static` anymore, there are no more soundness concerns here. Therefore, this PR removes the feature gate. Tests: * `tests/ui/async-await/feature-self-return-type.rs` * `tests/ui/impl-trait/feature-self-return-type.rs` * `tests/ui/async-await/issues/issue-78600.rs` * `tests/ui/impl-trait/capture-lifetime-not-in-hir.rs` --- r? cjgillot on the impl (not much, just removing the feature gate) I'm gonna mark this as FCP for T-lang and T-types.
Stabilize `impl_trait_projections` Closes rust-lang#115659 ## TL;DR: This allows us to mention `Self` and `T::Assoc` in async fn and return-position `impl Trait`, as you would expect you'd be able to. Some examples: ```rust #![feature(return_position_impl_trait_in_trait, async_fn_in_trait)] // (just needed for final tests below) // ---------------------------------------- // struct Wrapper<'a, T>(&'a T); impl Wrapper<'_, ()> { async fn async_fn() -> Self { //^ Previously rejected because it returns `-> Self`, not `-> Wrapper<'_, ()>`. Wrapper(&()) } fn impl_trait() -> impl Iterator<Item = Self> { //^ Previously rejected because it mentions `Self`, not `Wrapper<'_, ()>`. std::iter::once(Wrapper(&())) } } // ---------------------------------------- // trait Trait<'a> { type Assoc; fn new() -> Self::Assoc; } impl Trait<'_> for () { type Assoc = (); fn new() {} } impl<'a, T: Trait<'a>> Wrapper<'a, T> { async fn mk_assoc() -> T::Assoc { //^ Previously rejected because `T::Assoc` doesn't mention `'a` in the HIR, // but ends up resolving to `<T as Trait<'a>>::Assoc`, which does rely on `'a`. // That's the important part -- the elided trait. T::new() } fn a_few_assocs() -> impl Iterator<Item = T::Assoc> { //^ Previously rejected for the same reason [T::new(), T::new(), T::new()].into_iter() } } // ---------------------------------------- // trait InTrait { async fn async_fn() -> Self; fn impl_trait() -> impl Iterator<Item = Self>; } impl InTrait for &() { async fn async_fn() -> Self { &() } //^ Previously rejected just like inherent impls fn impl_trait() -> impl Iterator<Item = Self> { //^ Previously rejected just like inherent impls [&()].into_iter() } } ``` ## Technical: Lifetimes in return-position `impl Trait` (and `async fn`) are duplicated as early-bound generics local to the opaque in order to make sure we are able to substitute any late-bound lifetimes from the function in the opaque's hidden type. (The [dev guide](https://rustc-dev-guide.rust-lang.org/return-position-impl-trait-in-trait.html#aside-opaque-lifetime-duplication) has a small section about why this is necessary -- this was written for RPITITs, but it applies to all RPITs) Prior to rust-lang#103491, all of the early-bound lifetimes not local to the opaque were replaced with `'static` to avoid issues where relating opaques caused their *non-captured* lifetimes to be related. This `'static` replacement led to strange and possibly unsound behaviors (rust-lang#61949 (comment)) (rust-lang#53613) when referencing the `Self` type alias in an impl or indirectly referencing a lifetime parameter via a projection type (via a `T::Assoc` projection without an explicit trait), since lifetime resolution is performed on the HIR, when neither `T::Assoc`-style projections or `Self` in impls are expanded. Therefore an error was implemented in rust-lang#62849 to deny this subtle behavior as a known limitation of the compiler. It was attempted by `@cjgillot` to fix this in rust-lang#91403, which was subsequently unlanded. Then it was re-attempted to much success (🎉) in rust-lang#103491, which is where we currently are in the compiler. The PR above (rust-lang#103491) fixed this issue technically by *not* replacing the opaque's parent lifetimes with `'static`, but instead using variance to properly track which lifetimes are captured and are not. The PR gated any of the "side-effects" of the PR behind a feature gate (`impl_trait_projections`) presumably to avoid having to involve T-lang or T-types in the PR as well. `@cjgillot` can clarify this if I'm misunderstanding what their intention was with the feature gate. Since we're not replacing (possibly *invariant*!) lifetimes with `'static` anymore, there are no more soundness concerns here. Therefore, this PR removes the feature gate. Tests: * `tests/ui/async-await/feature-self-return-type.rs` * `tests/ui/impl-trait/feature-self-return-type.rs` * `tests/ui/async-await/issues/issue-78600.rs` * `tests/ui/impl-trait/capture-lifetime-not-in-hir.rs` --- r? cjgillot on the impl (not much, just removing the feature gate) I'm gonna mark this as FCP for T-lang and T-types.
Part of #61949.
This PR prohibits return position
impl Trait
types that "inheritlifetimes" from the parent scope. The intent is to forbid cases that are
challenging until they can be addressed properly.
cc @nikomatsakis