@@ -2570,7 +2570,54 @@ impl<'a> LoweringContext<'a> {
2570
2570
2571
2571
self . allocate_hir_id_counter ( opaque_ty_node_id) ;
2572
2572
2573
+ // When we create the opaque type for this async fn, it is going to have
2574
+ // to capture all the lifetimes involved in the signature (including in the
2575
+ // return type). This is done by introducing lifetime parameters for:
2576
+ //
2577
+ // - all the explicitly declared lifetimes from the impl and function itself;
2578
+ // - all the elided lifetimes in the fn arguments;
2579
+ // - all the elided lifetimes in the return type.
2580
+ //
2581
+ // So for example in this snippet:
2582
+ //
2583
+ // ```rust
2584
+ // impl<'a> Foo<'a> {
2585
+ // async fn bar<'b>(&self, x: &'b Vec<f64>, y: &str) -> &u32 {
2586
+ // // ^ '0 ^ '1 ^ '2
2587
+ // // elided lifetimes used below
2588
+ // }
2589
+ // }
2590
+ // ```
2591
+ //
2592
+ // we would create an opaque type like:
2593
+ //
2594
+ // ```
2595
+ // type Bar<'a, 'b, '0, '1, '2> = impl Future<Output = &'2 u32>;
2596
+ // ```
2597
+ //
2598
+ // and we would then desugar `bar` to the equivalent of:
2599
+ //
2600
+ // ```rust
2601
+ // impl<'a> Foo<'a> {
2602
+ // fn bar<'b, '0, '1>(&'0 self, x: &'b Vec<f64>, y: &'1 str) -> Bar<'a, 'b, '0, '1, '_>
2603
+ // }
2604
+ // ```
2605
+ //
2606
+ // Note that the final parameter to `Bar` is `'_`, not `'2` --
2607
+ // this is because the elided lifetimes from the return type
2608
+ // should be figured out using the ordinary elision rules, and
2609
+ // this desugaring achieves that.
2610
+ //
2611
+ // The variable `input_lifetimes_count` tracks the number of
2612
+ // lifetime parameters to the opaque type *not counting* those
2613
+ // lifetimes elided in the return type. This includes those
2614
+ // that are explicitly declared (`in_scope_lifetimes`) and
2615
+ // those elided lifetimes we found in the arguments (current
2616
+ // content of `lifetimes_to_define`). Next, we will process
2617
+ // the return type, which will cause `lifetimes_to_define` to
2618
+ // grow.
2573
2619
let input_lifetimes_count = self . in_scope_lifetimes . len ( ) + self . lifetimes_to_define . len ( ) ;
2620
+
2574
2621
let ( opaque_ty_id, lifetime_params) = self . with_hir_id_owner ( opaque_ty_node_id, |this| {
2575
2622
// We have to be careful to get elision right here. The
2576
2623
// idea is that we create a lifetime parameter for each
@@ -2635,29 +2682,27 @@ impl<'a> LoweringContext<'a> {
2635
2682
( opaque_ty_id, lifetime_params)
2636
2683
} ) ;
2637
2684
2638
- // Create the generic lifetime arguments that we will supply
2639
- // to the opaque return type. Consider:
2685
+ // As documented above on the variable
2686
+ // `input_lifetimes_count`, we need to create the lifetime
2687
+ // arguments to our opaque type. Continuing with our example,
2688
+ // we're creating the type arguments for the return type:
2640
2689
//
2641
- // ```rust
2642
- // async fn foo(x: &u32, ) -> &[&u32] { .. }
2643
2690
// ```
2644
- //
2645
- // Here, we would create something like:
2646
- //
2647
- // ```rust
2648
- // type Foo<'a, 'b, 'c> = impl Future<Output = &'a [&'b u32]>;
2649
- // fn foo<'a>(x: &'a u32) -> Foo<'a, '_, '_>
2691
+ // Bar<'a, 'b, '0, '1, '_>
2650
2692
// ```
2651
2693
//
2652
- // Note that for the lifetimes which came from the input
2653
- // (`'a`, here), we supply them as arguments to the return
2654
- // type `Foo`. But for those lifetime parameters (`'b`, `'c`)
2655
- // that we created from the return type, we want to use `'_`
2656
- // in the return type, so as to trigger elision.
2694
+ // For the "input" lifetime parameters, we wish to create
2695
+ // references to the parameters themselves, including the
2696
+ // "implicit" ones created from parameter types (`'a`, `'b`,
2697
+ // '`0`, `'1`).
2698
+ //
2699
+ // For the "output" lifetime parameters, we just want to
2700
+ // generate `'_`.
2657
2701
let mut generic_args: Vec < _ > =
2658
2702
lifetime_params[ ..input_lifetimes_count]
2659
2703
. iter ( )
2660
2704
. map ( |& ( span, hir_name) | {
2705
+ // Input lifetime like `'a` or `'1`:
2661
2706
GenericArg :: Lifetime ( hir:: Lifetime {
2662
2707
hir_id : self . next_id ( ) ,
2663
2708
span,
@@ -2669,6 +2714,7 @@ impl<'a> LoweringContext<'a> {
2669
2714
lifetime_params[ input_lifetimes_count..]
2670
2715
. iter ( )
2671
2716
. map ( |& ( span, _) | {
2717
+ // Output lifetime like `'_`.
2672
2718
GenericArg :: Lifetime ( hir:: Lifetime {
2673
2719
hir_id : self . next_id ( ) ,
2674
2720
span,
0 commit comments