7b4d9e155f
Stabilize `impl_trait_projections` Closes #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 #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 (https://github.com/rust-lang/rust/issues/61949#issuecomment-508836314) (https://github.com/rust-lang/rust/issues/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 #62849 to deny this subtle behavior as a known limitation of the compiler. It was attempted by `@cjgillot` to fix this in #91403, which was subsequently unlanded. Then it was re-attempted to much success (🎉) in #103491, which is where we currently are in the compiler. The PR above (#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. |
||
---|---|---|
.. | ||
auxiliary | ||
issue-65419 | ||
issue-51719.rs | ||
issue-51719.stderr | ||
issue-51751.rs | ||
issue-51751.stderr | ||
issue-53249.rs | ||
issue-54752-async-block.rs | ||
issue-54752-async-block.stderr | ||
issue-54974.rs | ||
issue-55324.rs | ||
issue-55809.rs | ||
issue-58885.rs | ||
issue-59001.rs | ||
issue-59972.rs | ||
issue-60518.rs | ||
issue-60655-latebound-regions.rs | ||
issue-60674.rs | ||
issue-60674.stdout | ||
issue-61187.rs | ||
issue-61187.stderr | ||
issue-61986.rs | ||
issue-62009-1.rs | ||
issue-62009-1.stderr | ||
issue-62009-2.rs | ||
issue-62009-2.stderr | ||
issue-62097.rs | ||
issue-62097.stderr | ||
issue-62517-1.rs | ||
issue-62517-2.rs | ||
issue-63388-1.rs | ||
issue-63388-1.stderr | ||
issue-63388-2.rs | ||
issue-63388-2.stderr | ||
issue-63388-3.rs | ||
issue-63388-4.rs | ||
issue-64391-2.rs | ||
issue-64433.rs | ||
issue-64477-2.rs | ||
issue-64477.rs | ||
issue-64964.rs | ||
issue-65159.rs | ||
issue-65159.stderr | ||
issue-65436-raw-ptr-not-send.rs | ||
issue-66695-static-refs.rs | ||
issue-66958-non-copy-infered-type-arg.rs | ||
issue-66958-non-copy-infered-type-arg.stderr | ||
issue-67611-static-mut-refs.rs | ||
issue-67893.rs | ||
issue-67893.stderr | ||
issue-69307-nested.rs | ||
issue-69307.rs | ||
issue-72312.rs | ||
issue-72312.stderr | ||
issue-78600.rs | ||
issue-78654.full.stderr | ||
issue-78654.min.stderr | ||
issue-78654.rs | ||
issue-78938-async-block.rs | ||
issue-78938-async-block.stderr | ||
issue-95307.rs | ||
issue-95307.stderr | ||
issue-102206.rs | ||
issue-102206.stderr | ||
issue-107280.rs | ||
issue-107280.stderr | ||
issue-112225-1.rs | ||
issue-112225-2.rs | ||
issue-112225-2.stderr | ||
non-async-enclosing-span.rs | ||
non-async-enclosing-span.stderr |