mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
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 | ||
await-keyword | ||
drop-order | ||
future-sizes | ||
in-trait | ||
issues | ||
multiple-lifetimes | ||
return-type-notation | ||
track-caller | ||
argument-patterns.rs | ||
async-assoc-fn-anon-lifetimes.rs | ||
async-await-let-else.rs | ||
async-await-let-else.stderr | ||
async-await.rs | ||
async-block-control-flow-static-semantics.rs | ||
async-block-control-flow-static-semantics.stderr | ||
async-borrowck-escaping-block-error.fixed | ||
async-borrowck-escaping-block-error.rs | ||
async-borrowck-escaping-block-error.stderr | ||
async-borrowck-escaping-closure-error.rs | ||
async-borrowck-escaping-closure-error.stderr | ||
async-closure-matches-expr.rs | ||
async-closure.rs | ||
async-error-span.rs | ||
async-error-span.stderr | ||
async-fn-elided-impl-lifetime-parameter.rs | ||
async-fn-nonsend.rs | ||
async-fn-nonsend.stderr | ||
async-fn-path-elision.rs | ||
async-fn-path-elision.stderr | ||
async-fn-send-uses-nonsend.rs | ||
async-fn-size-moved-locals.rs | ||
async-fn-size-uninit-locals.rs | ||
async-fn-size.rs | ||
async-is-unwindsafe.rs | ||
async-is-unwindsafe.stderr | ||
async-matches-expr.rs | ||
async-trait-fn.current.stderr | ||
async-trait-fn.next.stderr | ||
async-trait-fn.rs | ||
async-trait-fn.stderr | ||
async-unsafe-fn-call-in-safe.mir.stderr | ||
async-unsafe-fn-call-in-safe.rs | ||
async-unsafe-fn-call-in-safe.thir.stderr | ||
async-with-closure.rs | ||
await-into-future.rs | ||
await-sequence.rs | ||
await-unsize.rs | ||
awaiting-unsized-param.rs | ||
awaiting-unsized-param.stderr | ||
bound-normalization.rs | ||
clone-suggestion.fixed | ||
clone-suggestion.rs | ||
clone-suggestion.stderr | ||
conditional-and-guaranteed-initialization.rs | ||
const-async-fn-in-main.rs | ||
const-async-fn-in-main.stderr | ||
deep-futures-are-freeze.rs | ||
default-struct-update.rs | ||
dont-print-desugared-async.rs | ||
dont-print-desugared-async.stderr | ||
dont-suggest-await-on-method-return-mismatch.rs | ||
dont-suggest-await-on-method-return-mismatch.stderr | ||
dont-suggest-missing-await.rs | ||
dont-suggest-missing-await.stderr | ||
drop-and-assign.rs | ||
drop-track-bad-field-in-fru.rs | ||
drop-track-bad-field-in-fru.stderr | ||
drop-track-field-assign-nonsend.rs | ||
drop-track-field-assign-nonsend.stderr | ||
drop-track-field-assign.rs | ||
drop-tracking-unresolved-typeck-results.rs | ||
drop-tracking-unresolved-typeck-results.stderr | ||
edition-deny-async-fns-2015.current.stderr | ||
edition-deny-async-fns-2015.next.stderr | ||
edition-deny-async-fns-2015.rs | ||
edition-deny-async-fns-2015.stderr | ||
expansion-in-attrs.rs | ||
feature-async-closure.rs | ||
feature-async-closure.stderr | ||
feature-gate-async_fn_in_trait.rs | ||
feature-gate-async_fn_in_trait.stderr | ||
feature-self-return-type.rs | ||
feature-self-return-type.stderr | ||
field-assign-nonsend.rs | ||
field-assign-nonsend.stderr | ||
field-assign.rs | ||
future-contains-err-issue-115188.rs | ||
future-contains-err-issue-115188.stderr | ||
futures-api.rs | ||
generator-desc.rs | ||
generator-desc.stderr | ||
generator-not-future.rs | ||
generator-not-future.stderr | ||
generics-and-bounds.rs | ||
incorrect-move-async-order-issue-79694.fixed | ||
incorrect-move-async-order-issue-79694.rs | ||
incorrect-move-async-order-issue-79694.stderr | ||
interior-with-const-generic-expr.rs | ||
issue-54239-private-type-triggers-lint.rs | ||
issue-60709.rs | ||
issue-61076.rs | ||
issue-61076.stderr | ||
issue-61452.rs | ||
issue-61452.stderr | ||
issue-61793.rs | ||
issue-62658.rs | ||
issue-63832-await-short-temporary-lifetime-1.rs | ||
issue-63832-await-short-temporary-lifetime.rs | ||
issue-64130-1-sync.rs | ||
issue-64130-1-sync.stderr | ||
issue-64130-2-send.rs | ||
issue-64130-2-send.stderr | ||
issue-64130-3-other.rs | ||
issue-64130-3-other.stderr | ||
issue-64130-4-async-move.rs | ||
issue-64130-non-send-future-diags.rs | ||
issue-64130-non-send-future-diags.stderr | ||
issue-64391.rs | ||
issue-66312.rs | ||
issue-66312.stderr | ||
issue-66387-if-without-else.rs | ||
issue-66387-if-without-else.stderr | ||
issue-67252-unnamed-future.rs | ||
issue-67252-unnamed-future.stderr | ||
issue-67651.rs | ||
issue-67651.stderr | ||
issue-67765-async-diagnostic.rs | ||
issue-67765-async-diagnostic.stderr | ||
issue-68112.rs | ||
issue-68112.stderr | ||
issue-68523-start.rs | ||
issue-68523-start.stderr | ||
issue-68523.rs | ||
issue-68523.stderr | ||
issue-69446-fnmut-capture.rs | ||
issue-69446-fnmut-capture.stderr | ||
issue-70594.rs | ||
issue-70594.stderr | ||
issue-70818.rs | ||
issue-70818.stderr | ||
issue-70935-complex-spans.rs | ||
issue-70935-complex-spans.stderr | ||
issue-71137.rs | ||
issue-71137.stderr | ||
issue-72442.rs | ||
issue-72442.stderr | ||
issue-72470-llvm-dominate.rs | ||
issue-72590-type-error-sized.rs | ||
issue-72590-type-error-sized.stderr | ||
issue-73050.rs | ||
issue-73137.rs | ||
issue-73541-1.rs | ||
issue-73541-1.stderr | ||
issue-73541-2.rs | ||
issue-73541-2.stderr | ||
issue-73541-3.rs | ||
issue-73541-3.stderr | ||
issue-73541.rs | ||
issue-73541.stderr | ||
issue-73741-type-err.rs | ||
issue-73741-type-err.stderr | ||
issue-74047.rs | ||
issue-74047.stderr | ||
issue-74072-lifetime-name-annotations.rs | ||
issue-74072-lifetime-name-annotations.stderr | ||
issue-74497-lifetime-in-opaque.rs | ||
issue-74497-lifetime-in-opaque.stderr | ||
issue-75785-confusing-named-region.rs | ||
issue-75785-confusing-named-region.stderr | ||
issue-76547.rs | ||
issue-76547.stderr | ||
issue-77993-2.rs | ||
issue-77993-2.stderr | ||
issue-78115.rs | ||
issue-84841.rs | ||
issue-84841.stderr | ||
issue-86507.rs | ||
issue-86507.stderr | ||
issue-93197.rs | ||
issue-93648.rs | ||
issue-98634.rs | ||
issue-98634.stderr | ||
issue-101715.rs | ||
issue-101715.stderr | ||
issue-105501.rs | ||
issue-107036.rs | ||
issue-108572.rs | ||
issue-108572.stderr | ||
missed-capture-issue-107414.rs | ||
move-part-await-return-rest-struct.rs | ||
move-part-await-return-rest-tuple.rs | ||
mutually-recursive-async-impl-trait-type.rs | ||
mutually-recursive-async-impl-trait-type.stderr | ||
nested-in-impl.rs | ||
no-async-const.rs | ||
no-async-const.stderr | ||
no-const-async.rs | ||
no-const-async.stderr | ||
no-move-across-await-struct.rs | ||
no-move-across-await-struct.stderr | ||
no-move-across-await-tuple.rs | ||
no-move-across-await-tuple.stderr | ||
no-non-guaranteed-initialization.rs | ||
no-non-guaranteed-initialization.stderr | ||
no-params-non-move-async-closure.rs | ||
no-params-non-move-async-closure.stderr | ||
no-std.rs | ||
no-unsafe-async.rs | ||
no-unsafe-async.stderr | ||
non-trivial-drop.rs | ||
normalize-output-in-signature-deduction.rs | ||
partial-drop-partial-reinit.rs | ||
partial-drop-partial-reinit.stderr | ||
partial-initialization-across-await.rs | ||
partial-initialization-across-await.stderr | ||
pin-needed-to-poll-2.rs | ||
pin-needed-to-poll-2.stderr | ||
pin-needed-to-poll.rs | ||
pin-needed-to-poll.stderr | ||
proper-span-for-type-error.fixed | ||
proper-span-for-type-error.rs | ||
proper-span-for-type-error.stderr | ||
recursive-async-impl-trait-type.rs | ||
recursive-async-impl-trait-type.stderr | ||
repeat_count_const_in_async_fn.rs | ||
return-ty-raw-ptr-coercion.rs | ||
return-ty-unsize-coercion.rs | ||
send-bound-async-closure.rs | ||
suggest-missing-await-closure.fixed | ||
suggest-missing-await-closure.rs | ||
suggest-missing-await-closure.stderr | ||
suggest-missing-await.rs | ||
suggest-missing-await.stderr | ||
suggest-switching-edition-on-await-cargo.rs | ||
suggest-switching-edition-on-await-cargo.stderr | ||
suggest-switching-edition-on-await.rs | ||
suggest-switching-edition-on-await.stderr | ||
task-context-arg.rs | ||
try-on-option-in-async.rs | ||
try-on-option-in-async.stderr | ||
type-parameter-send.rs | ||
unnecessary-await.rs | ||
unnecessary-await.stderr | ||
unreachable-lint-1.rs | ||
unreachable-lint-1.stderr | ||
unreachable-lint.rs | ||
unresolved_type_param.rs | ||
unresolved_type_param.stderr | ||
unsized-across-await.rs | ||
unsized-across-await.stderr | ||
unused-lifetime.rs | ||
unused-lifetime.stderr |