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.
This commit is contained in:
@@ -1539,7 +1539,6 @@ fn check_fn_or_method<'tcx>(
|
||||
|
||||
check_return_position_impl_trait_in_trait_bounds(
|
||||
tcx,
|
||||
wfcx,
|
||||
def_id,
|
||||
sig.output(),
|
||||
hir_decl.output.span(),
|
||||
@@ -1575,9 +1574,9 @@ fn check_fn_or_method<'tcx>(
|
||||
|
||||
/// Basically `check_associated_type_bounds`, but separated for now and should be
|
||||
/// deduplicated when RPITITs get lowered into real associated items.
|
||||
#[tracing::instrument(level = "trace", skip(tcx))]
|
||||
fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
wfcx: &WfCheckingCtxt<'_, 'tcx>,
|
||||
fn_def_id: LocalDefId,
|
||||
fn_output: Ty<'tcx>,
|
||||
span: Span,
|
||||
@@ -1591,18 +1590,22 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
|
||||
&& tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder
|
||||
&& tcx.impl_trait_in_trait_parent(proj.item_def_id) == fn_def_id.to_def_id()
|
||||
{
|
||||
let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id);
|
||||
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
|
||||
let normalized_bound = wfcx.normalize(span, None, bound);
|
||||
traits::wf::predicate_obligations(
|
||||
wfcx.infcx,
|
||||
wfcx.param_env,
|
||||
wfcx.body_id,
|
||||
normalized_bound,
|
||||
bound_span,
|
||||
)
|
||||
// Create a new context, since we want the opaque's ParamEnv and not the parent's.
|
||||
let span = tcx.def_span(proj.item_def_id);
|
||||
enter_wf_checking_ctxt(tcx, span, proj.item_def_id.expect_local(), |wfcx| {
|
||||
let bounds = wfcx.tcx().explicit_item_bounds(proj.item_def_id);
|
||||
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
|
||||
let normalized_bound = wfcx.normalize(span, None, bound);
|
||||
traits::wf::predicate_obligations(
|
||||
wfcx.infcx,
|
||||
wfcx.param_env,
|
||||
wfcx.body_id,
|
||||
normalized_bound,
|
||||
bound_span,
|
||||
)
|
||||
});
|
||||
wfcx.register_obligations(wf_obligations);
|
||||
});
|
||||
wfcx.register_obligations(wf_obligations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user