Skip to content

Commit f06ae6a

Browse files
committed
Simplify RPITIT desugaring
We had added an RPITIT desugaring that was rather complicated. This complication was due to trying to explain what it would mean to not capture generic parameters that are part of the trait header. However, it's likely that there's no good way to express that semantic in the surface syntax. Let's instead simplify the desugaring and make a note of its limitations.
1 parent 972be34 commit f06ae6a

File tree

1 file changed

+11
-106
lines changed

1 file changed

+11
-106
lines changed

text/3617-precise-capturing.md

Lines changed: 11 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ The [syntax for `impl Trait`][] is revised and extended as follows:
207207

208208
## Reference desugarings
209209

210-
The desugarings that follow can be used to answer questions about how `use<..>` is expected to work with respect to the capturing of generic parameters in opaque types.
210+
The desugarings that follow can be used to answer questions about how `use<..>` is expected to work with respect to the capturing of generic parameters.
211211

212212
### Reference desugaring for `use<..>` in RPIT
213213

@@ -275,126 +275,31 @@ mod _0 {
275275

276276
### Reference desugaring for `use<..>` in RPITIT
277277

278-
Similarly, we can describe the semantics of `use<..>` in return position `impl Trait` in trait (RPITIT) using anonymous associated types and ATPIT. If we consider the following code:
278+
Similarly, we can describe the semantics of `use<..>` in return position `impl Trait` in trait (RPITIT) using anonymous associated types. If we consider the following code:
279279

280280
```rust
281-
use core::marker::PhantomData;
282-
283-
struct C<
284-
'r, 's, 't, R, S, T, const CR: u8, const CS: u8, const CT: u8,
285-
> {
286-
_p: PhantomData<(&'r (), &'s (), &'t (), R, S, T)>,
287-
}
288-
289281
trait Trait<'r, R, const CR: u8> {
290282
fn f<'t, T, const CT: u8>(
291283
) -> impl use<'r, 't, R, T, CR, CT, Self> Sized;
292284
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
293-
// This is the `use<..>` specifier in the trait definition.
294-
}
295-
296-
struct Ty<'s, S, const CS: u8>(&'s (), S);
297-
impl<'r, 's, R, S, const CR: u8, const CS: u8> Trait<'r, R, CR>
298-
for Ty<'s, S, CS>
299-
{
300-
fn f<'t, T, const CT: u8>(
301-
) -> impl use<'r, 's, 't, R, S, T, CR, CS, CT> Sized {
302-
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
303-
// This is the `use<..>` specifier in the
304-
// trait implementation.
305-
C::<'r, 's, 't, R, S, T, CR, CS, CT> { _p: PhantomData }
306-
}
285+
// This is the `use<..>` specifier to desugar.
307286
}
308287
```
309288

310-
Then we can desugar this as follows, without the use of `use<..>` specifiers, while preserving equivalent semantics with respect to the capturing of generic parameters:
289+
Then we can desugar this as follows, without the use of a `use<..>` specifier, while preserving equivalent semantics with respect to the capturing of generic parameters:
311290

312291
```rust
313-
use core::marker::PhantomData;
314-
315-
struct C<
316-
'r, 's, 't, R, S, T, const CR: u8, const CS: u8, const CT: u8,
317-
> {
318-
_p: PhantomData<(&'r (), &'s (), &'t (), R, S, T)>,
319-
}
320-
321-
trait Trait<'r, R, const CR: u8>: Sized {
322-
fn f<'t, T, const CT: u8>(
323-
) -> <Self as _0::G<'r, R, CR>>::Opaque<'t, T, CT>
324-
// ^^^^ ^^^^^^^^^ ^^^^^^^^^
325-
// These are the arguments given to the `use<..>` specifier in the
326-
// trait definition.
327-
//
328-
// Reducing what is captured by removing arguments from that
329-
// `use<..>` is equivalent to removing arguments from here
330-
// and as needed below.
331-
//
332-
// If `Self` is removed from the `use<..>` specifier, that's
333-
// equivalent to replacing `Self` with `()` here and in the impl
334-
// below. I.e., removing `Self` means that we can't capture any
335-
// generic parameters in the impl that are not used as input
336-
// arguments to the trait.
337-
//
338-
// Similarly, if trait input parameters are removed from the
339-
// `use<..>` specifier, they must be removed from the input
340-
// parameters to the trait `G` below.
341-
where Self: _0::G<'r, R, CR>;
342-
}
343-
344-
struct Ty<'s, S, const CS: u8>(&'s (), S);
345-
impl<'r, 's, R, S, const CR: u8, const CS: u8> Trait<'r, R, CR>
346-
for Ty<'s, S, CS>
347-
{
292+
trait Trait<'r, R, const CR: u8> {
293+
type _0<'t, T, const CT: u8>: Sized;
348294
fn f<'t, T, const CT: u8>(
349-
) -> <Self as _0::G<'r, R, CR>>::Opaque<'t, T, CT> {
350-
<() as _0::H>::f::<'r, 's, 't, R, S, T, CR, CS, CT>()
351-
}
352-
}
353-
354-
mod _0 {
355-
use super::*;
356-
pub trait G<'r, R, const CR: u8> {
357-
type Opaque<'t, T, const CT: u8>;
358-
}
359-
impl<'r, 's, R, S, const CR: u8, const CS: u8> G<'r, R, CR>
360-
for Ty<'s, S, CS>
361-
{
362-
type Opaque<'t, T, const CT: u8>
363-
= <() as H>::Opaque<'r, 's, 't, R, S, T, CR, CS, CT>;
364-
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
365-
// These are the arguments given to the `use<..>` specifier in
366-
// the trait implementation.
367-
//
368-
// Reducing what is captured by removing arguments from that
369-
// `use<..>` is equivalent to removing arguments from this
370-
// list and as needed elsewhere.
371-
}
372-
pub trait H {
373-
type Opaque<
374-
'r, 's, 't, R, S, T,
375-
const CR: u8, const CS: u8, const CT: u8,
376-
>;
377-
fn f<
378-
'r, 's, 't, R, S, T,
379-
const CR: u8, const CS: u8, const CT: u8,
380-
>() -> Self::Opaque<'r, 's, 't, R, S, T, CR, CS, CT>;
381-
}
382-
impl H for () {
383-
type Opaque<
384-
'r, 's, 't, R, S, T,
385-
const CR: u8, const CS: u8, const CT: u8,
386-
> = impl Sized;
387-
#[inline(always)]
388-
fn f<
389-
'r, 's, 't, R, S, T,
390-
const CR: u8, const CS: u8, const CT: u8,
391-
>() -> Self::Opaque<'r, 's, 't, R, S, T, CR, CS, CT> {
392-
C::<'r, 's, 't, R, S, T, CR, CS, CT> { _p: PhantomData }
393-
}
394-
}
295+
) -> <Self as Trait<'r, R, CR>>::_0<'t, T, CT>;
296+
// ^^^^ ^^^^^^^^^ ^^^^^^^^^
297+
// These are the arguments given to the `use<..>` specifier.
395298
}
396299
```
397300

301+
Note that this desugaring does not allow for removing from the `use<..>` specifier `Self` or any generics that are input parameters to the trait. This is, in fact, an implementation restriction that is likely to be part of initial rounds of stabilization.
302+
398303
## Avoiding capture of higher ranked lifetimes in nested opaques
399304

400305
According to the Lifetime Capture Rules 2024, a nested `impl Trait` opaque type *must* capture all generic parameters in scope, including higher ranked ones. However, for implementation reasons, Rust does not yet support higher ranked lifetime bounds on nested opaque types (see [#104288][]). Therefore, in Rust 2024, this code, which is valid in Rust 2021, fails to compile:

0 commit comments

Comments
 (0)