]> git.lizzy.rs Git - rust.git/commit
Auto merge of #103491 - cjgillot:self-rpit, r=oli-obk
authorbors <bors@rust-lang.org>
Mon, 21 Nov 2022 12:17:03 +0000 (12:17 +0000)
committerbors <bors@rust-lang.org>
Mon, 21 Nov 2022 12:17:03 +0000 (12:17 +0000)
commit7fe6f36224e92db6fbde952e0b7e50863161f6ee
tree581f4b1ae8eb562da89b71d1bdf4a0fc3d8d5f05
parent736c675d2ab65bcde6554e1b73340c2dbc27c85a
parentb37feca804ece8eed650465faab65f5c53494b33
Auto merge of #103491 - cjgillot:self-rpit, r=oli-obk

Support using `Self` or projections inside an RPIT/async fn

I reuse the same idea as https://github.com/rust-lang/rust/pull/103449 to use variances to encode whether a lifetime parameter is captured by impl-trait.

The current implementation of async and RPIT replace all lifetimes from the parent generics by `'static`.  This PR changes the scheme
```rust
impl<'a> Foo<'a> {
    fn foo<'b, T>() -> impl Into<Self> + 'b { ... }
}

opaque Foo::<'_a>::foo::<'_b, T>::opaque<'b>: Into<Foo<'_a>> + 'b;
impl<'a> Foo<'a> {
    // OLD
    fn foo<'b, T>() -> Foo::<'static>::foo::<'static, T>::opaque::<'b> { ... }
                             ^^^^^^^ the `Self` becomes `Foo<'static>`

    // NEW
    fn foo<'b, T>() -> Foo::<'a>::foo::<'b, T>::opaque::<'b> { ... }
                             ^^ the `Self` stays `Foo<'a>`
}
```

There is the same issue with projections. In the example, substitute `Self` by `<T as Trait<'b>>::Assoc` in the sugared version, and `Foo<'_a>` by `<T as Trait<'_b>>::Assoc` in the desugared one.

This allows to support `Self` in impl-trait, since we do not replace lifetimes by `'static` any more.  The same trick allows to use projections like `T::Assoc` where `Self` is allowed.  The feature is gated behind a `impl_trait_projections` feature gate.

The implementation relies on 2 tweaking rules for opaques in 2 places:
- we only relate substs that correspond to captured lifetimes during TypeRelation;
- we only list captured lifetimes in choice region computation.

For simplicity, I encoded the "capturedness" of lifetimes as a variance, `Bivariant` vs `Invariant` for unused vs captured lifetimes. The `variances_of` query used to ICE for opaques.

Impl-trait that do not reference `Self` or projections will have their variances as:
- `o` (invariant) for each parent type or const;
- `*` (bivariant) for each parent lifetime --> will not participate in borrowck;
- `o` (invariant) for each own lifetime.

Impl-trait that does reference `Self` and/or projections will have some parent lifetimes marked as `o` (as the example above), and participate in type relation and borrowck.  In the example above, `variances_of(opaque) = ['_a: o, '_b: *, T: o, 'b: o]`.

r? types
cc `@compiler-errors` , as you asked about the issue with `Self` and projections.
13 files changed:
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_borrowck/src/region_infer/opaque_types.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_hir_analysis/src/astconv/mod.rs
compiler/rustc_hir_analysis/src/check/check.rs
compiler/rustc_hir_analysis/src/check/wfcheck.rs
compiler/rustc_hir_analysis/src/collect/predicates_of.rs
compiler/rustc_infer/src/infer/combine.rs
compiler/rustc_infer/src/infer/opaque_types.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_ty_utils/src/ty.rs