]> git.lizzy.rs Git - rust.git/commitdiff
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)
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:
1  2 
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

Simple merge
Simple merge
index 1b109ca6b11dd0d851c4e0470cd5c21b62c12030,fd7456e8c9d2aee67c2c31468e12bde8afab7694..29312a21b4d464f8af5e6c407d27f133727b6fe5
@@@ -785,8 -813,10 +785,9 @@@ symbols! 
          ignore,
          impl_header_lifetime_elision,
          impl_lint_pass,
 -        impl_macros,
          impl_trait_in_bindings,
          impl_trait_in_fn_trait_return,
+         impl_trait_projections,
          implied_by,
          import,
          import_name_type,
Simple merge