@@ -337,49 +337,6 @@ enum AnonymousLifetimeMode {
337337
338338 /// Pass responsibility to `resolve_lifetime` code for all cases.
339339 PassThrough ,
340-
341- /// Used in the return types of `async fn` where there exists
342- /// exactly one argument-position elided lifetime.
343- ///
344- /// In `async fn`, we lower the arguments types using the `CreateParameter`
345- /// mode, meaning that non-`dyn` elided lifetimes are assigned a fresh name.
346- /// If any corresponding elided lifetimes appear in the output, we need to
347- /// replace them with references to the fresh name assigned to the corresponding
348- /// elided lifetime in the arguments.
349- ///
350- /// For **Modern cases**, replace the anonymous parameter with a
351- /// reference to a specific freshly-named lifetime that was
352- /// introduced in argument
353- ///
354- /// For **Dyn Bound** cases, pass responsibility to
355- /// `resole_lifetime` code.
356- Replace ( LtReplacement ) ,
357- }
358-
359- /// The type of elided lifetime replacement to perform on `async fn` return types.
360- #[ derive( Copy , Clone ) ]
361- enum LtReplacement {
362- /// Fresh name introduced by the single non-dyn elided lifetime
363- /// in the arguments of the async fn.
364- Some ( ParamName ) ,
365-
366- /// There is no single non-dyn elided lifetime because no lifetimes
367- /// appeared in the arguments.
368- NoLifetimes ,
369-
370- /// There is no single non-dyn elided lifetime because multiple
371- /// lifetimes appeared in the arguments.
372- MultipleLifetimes ,
373- }
374-
375- /// Calculates the `LtReplacement` to use for elided lifetimes in the return
376- /// type based on the fresh elided lifetimes introduced in argument position.
377- fn get_elided_lt_replacement ( arg_position_lifetimes : & [ ( Span , ParamName ) ] ) -> LtReplacement {
378- match arg_position_lifetimes {
379- [ ] => LtReplacement :: NoLifetimes ,
380- [ ( _span, param) ] => LtReplacement :: Some ( * param) ,
381- _ => LtReplacement :: MultipleLifetimes ,
382- }
383340}
384341
385342struct ImplTraitTypeIdVisitor < ' a > { ids : & ' a mut SmallVec < [ NodeId ; 1 ] > }
@@ -1953,8 +1910,7 @@ impl<'a> LoweringContext<'a> {
19531910 err. emit ( ) ;
19541911 }
19551912 AnonymousLifetimeMode :: PassThrough |
1956- AnonymousLifetimeMode :: ReportError |
1957- AnonymousLifetimeMode :: Replace ( _) => {
1913+ AnonymousLifetimeMode :: ReportError => {
19581914 self . sess . buffer_lint_with_diagnostic (
19591915 ELIDED_LIFETIMES_IN_PATHS ,
19601916 CRATE_NODE_ID ,
@@ -2141,7 +2097,6 @@ impl<'a> LoweringContext<'a> {
21412097
21422098 // Remember how many lifetimes were already around so that we can
21432099 // only look at the lifetime parameters introduced by the arguments.
2144- let lifetime_count_before_args = self . lifetimes_to_define . len ( ) ;
21452100 let inputs = self . with_anonymous_lifetime_mode ( lt_mode, |this| {
21462101 decl. inputs
21472102 . iter ( )
@@ -2156,16 +2111,10 @@ impl<'a> LoweringContext<'a> {
21562111 } ) ;
21572112
21582113 let output = if let Some ( ret_id) = make_ret_async {
2159- // Calculate the `LtReplacement` to use for any return-position elided
2160- // lifetimes based on the elided lifetime parameters introduced in the args.
2161- let lt_replacement = get_elided_lt_replacement (
2162- & self . lifetimes_to_define [ lifetime_count_before_args..]
2163- ) ;
21642114 self . lower_async_fn_ret_ty (
21652115 & decl. output ,
21662116 in_band_ty_params. expect ( "`make_ret_async` but no `fn_def_id`" ) . 0 ,
21672117 ret_id,
2168- lt_replacement,
21692118 )
21702119 } else {
21712120 match decl. output {
@@ -2230,7 +2179,6 @@ impl<'a> LoweringContext<'a> {
22302179 output : & FunctionRetTy ,
22312180 fn_def_id : DefId ,
22322181 opaque_ty_node_id : NodeId ,
2233- elided_lt_replacement : LtReplacement ,
22342182 ) -> hir:: FunctionRetTy {
22352183 let span = output. span ( ) ;
22362184
@@ -2248,9 +2196,65 @@ impl<'a> LoweringContext<'a> {
22482196
22492197 self . allocate_hir_id_counter ( opaque_ty_node_id) ;
22502198
2199+ // When we create the opaque type for this async fn, it is going to have
2200+ // to capture all the lifetimes involved in the signature (including in the
2201+ // return type). This is done by introducing lifetime parameters for:
2202+ //
2203+ // - all the explicitly declared lifetimes from the impl and function itself;
2204+ // - all the elided lifetimes in the fn arguments;
2205+ // - all the elided lifetimes in the return type.
2206+ //
2207+ // So for example in this snippet:
2208+ //
2209+ // ```rust
2210+ // impl<'a> Foo<'a> {
2211+ // async fn bar<'b>(&self, x: &'b Vec<f64>, y: &str) -> &u32 {
2212+ // // ^ '0 ^ '1 ^ '2
2213+ // // elided lifetimes used below
2214+ // }
2215+ // }
2216+ // ```
2217+ //
2218+ // we would create an opaque type like:
2219+ //
2220+ // ```
2221+ // type Bar<'a, 'b, '0, '1, '2> = impl Future<Output = &'2 u32>;
2222+ // ```
2223+ //
2224+ // and we would then desugar `bar` to the equivalent of:
2225+ //
2226+ // ```rust
2227+ // impl<'a> Foo<'a> {
2228+ // fn bar<'b, '0, '1>(&'0 self, x: &'b Vec<f64>, y: &'1 str) -> Bar<'a, 'b, '0, '1, '_>
2229+ // }
2230+ // ```
2231+ //
2232+ // Note that the final parameter to `Bar` is `'_`, not `'2` --
2233+ // this is because the elided lifetimes from the return type
2234+ // should be figured out using the ordinary elision rules, and
2235+ // this desugaring achieves that.
2236+ //
2237+ // The variable `input_lifetimes_count` tracks the number of
2238+ // lifetime parameters to the opaque type *not counting* those
2239+ // lifetimes elided in the return type. This includes those
2240+ // that are explicitly declared (`in_scope_lifetimes`) and
2241+ // those elided lifetimes we found in the arguments (current
2242+ // content of `lifetimes_to_define`). Next, we will process
2243+ // the return type, which will cause `lifetimes_to_define` to
2244+ // grow.
2245+ let input_lifetimes_count = self . in_scope_lifetimes . len ( ) + self . lifetimes_to_define . len ( ) ;
2246+
22512247 let ( opaque_ty_id, lifetime_params) = self . with_hir_id_owner ( opaque_ty_node_id, |this| {
2248+ // We have to be careful to get elision right here. The
2249+ // idea is that we create a lifetime parameter for each
2250+ // lifetime in the return type. So, given a return type
2251+ // like `async fn foo(..) -> &[&u32]`, we lower to `impl
2252+ // Future<Output = &'1 [ &'2 u32 ]>`.
2253+ //
2254+ // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
2255+ // hence the elision takes place at the fn site.
22522256 let future_bound = this. with_anonymous_lifetime_mode (
2253- AnonymousLifetimeMode :: Replace ( elided_lt_replacement ) ,
2257+ AnonymousLifetimeMode :: CreateParameter ,
22542258 |this| this. lower_async_fn_output_type_to_future_bound (
22552259 output,
22562260 fn_def_id,
@@ -2304,19 +2308,52 @@ impl<'a> LoweringContext<'a> {
23042308 ( opaque_ty_id, lifetime_params)
23052309 } ) ;
23062310
2307- let generic_args =
2308- lifetime_params
2309- . iter ( ) . cloned ( )
2310- . map ( |( span, hir_name) | {
2311- GenericArg :: Lifetime ( hir:: Lifetime {
2312- hir_id : self . next_id ( ) ,
2313- span,
2314- name : hir:: LifetimeName :: Param ( hir_name) ,
2315- } )
2311+ // As documented above on the variable
2312+ // `input_lifetimes_count`, we need to create the lifetime
2313+ // arguments to our opaque type. Continuing with our example,
2314+ // we're creating the type arguments for the return type:
2315+ //
2316+ // ```
2317+ // Bar<'a, 'b, '0, '1, '_>
2318+ // ```
2319+ //
2320+ // For the "input" lifetime parameters, we wish to create
2321+ // references to the parameters themselves, including the
2322+ // "implicit" ones created from parameter types (`'a`, `'b`,
2323+ // '`0`, `'1`).
2324+ //
2325+ // For the "output" lifetime parameters, we just want to
2326+ // generate `'_`.
2327+ let mut generic_args: Vec < _ > =
2328+ lifetime_params[ ..input_lifetimes_count]
2329+ . iter ( )
2330+ . map ( |& ( span, hir_name) | {
2331+ // Input lifetime like `'a` or `'1`:
2332+ GenericArg :: Lifetime ( hir:: Lifetime {
2333+ hir_id : self . next_id ( ) ,
2334+ span,
2335+ name : hir:: LifetimeName :: Param ( hir_name) ,
23162336 } )
2317- . collect ( ) ;
2337+ } )
2338+ . collect ( ) ;
2339+ generic_args. extend (
2340+ lifetime_params[ input_lifetimes_count..]
2341+ . iter ( )
2342+ . map ( |& ( span, _) | {
2343+ // Output lifetime like `'_`.
2344+ GenericArg :: Lifetime ( hir:: Lifetime {
2345+ hir_id : self . next_id ( ) ,
2346+ span,
2347+ name : hir:: LifetimeName :: Implicit ,
2348+ } )
2349+ } )
2350+ ) ;
23182351
2319- let opaque_ty_ref = hir:: TyKind :: Def ( hir:: ItemId { id : opaque_ty_id } , generic_args) ;
2352+ // Create the `Foo<...>` refernece itself. Note that the `type
2353+ // Foo = impl Trait` is, internally, created as a child of the
2354+ // async fn, so the *type parameters* are inherited. It's
2355+ // only the lifetime parameters that we must supply.
2356+ let opaque_ty_ref = hir:: TyKind :: Def ( hir:: ItemId { id : opaque_ty_id } , generic_args. into ( ) ) ;
23202357
23212358 hir:: FunctionRetTy :: Return ( P ( hir:: Ty {
23222359 node : opaque_ty_ref,
@@ -2412,11 +2449,6 @@ impl<'a> LoweringContext<'a> {
24122449 }
24132450
24142451 AnonymousLifetimeMode :: ReportError => self . new_error_lifetime ( Some ( l. id ) , span) ,
2415-
2416- AnonymousLifetimeMode :: Replace ( replacement) => {
2417- let hir_id = self . lower_node_id ( l. id ) ;
2418- self . replace_elided_lifetime ( hir_id, span, replacement)
2419- }
24202452 } ,
24212453 ident => {
24222454 self . maybe_collect_in_band_lifetime ( ident) ;
@@ -2439,39 +2471,6 @@ impl<'a> LoweringContext<'a> {
24392471 }
24402472 }
24412473
2442- /// Replace a return-position elided lifetime with the elided lifetime
2443- /// from the arguments.
2444- fn replace_elided_lifetime (
2445- & mut self ,
2446- hir_id : hir:: HirId ,
2447- span : Span ,
2448- replacement : LtReplacement ,
2449- ) -> hir:: Lifetime {
2450- let multiple_or_none = match replacement {
2451- LtReplacement :: Some ( name) => {
2452- return hir:: Lifetime {
2453- hir_id,
2454- span,
2455- name : hir:: LifetimeName :: Param ( name) ,
2456- } ;
2457- }
2458- LtReplacement :: MultipleLifetimes => "multiple" ,
2459- LtReplacement :: NoLifetimes => "none" ,
2460- } ;
2461-
2462- let mut err = crate :: middle:: resolve_lifetime:: report_missing_lifetime_specifiers (
2463- self . sess ,
2464- span,
2465- 1 ,
2466- ) ;
2467- err. note ( & format ! (
2468- "return-position elided lifetimes require exactly one \
2469- input-position elided lifetime, found {}.", multiple_or_none) ) ;
2470- err. emit ( ) ;
2471-
2472- hir:: Lifetime { hir_id, span, name : hir:: LifetimeName :: Error }
2473- }
2474-
24752474 fn lower_generic_params (
24762475 & mut self ,
24772476 params : & [ GenericParam ] ,
@@ -3174,10 +3173,6 @@ impl<'a> LoweringContext<'a> {
31743173 AnonymousLifetimeMode :: ReportError => self . new_error_lifetime ( None , span) ,
31753174
31763175 AnonymousLifetimeMode :: PassThrough => self . new_implicit_lifetime ( span) ,
3177-
3178- AnonymousLifetimeMode :: Replace ( replacement) => {
3179- self . new_replacement_lifetime ( replacement, span)
3180- }
31813176 }
31823177 }
31833178
@@ -3231,10 +3226,6 @@ impl<'a> LoweringContext<'a> {
32313226 // This is the normal case.
32323227 AnonymousLifetimeMode :: PassThrough => self . new_implicit_lifetime ( span) ,
32333228
3234- AnonymousLifetimeMode :: Replace ( replacement) => {
3235- self . new_replacement_lifetime ( replacement, span)
3236- }
3237-
32383229 AnonymousLifetimeMode :: ReportError => self . new_error_lifetime ( None , span) ,
32393230 }
32403231 }
@@ -3266,25 +3257,11 @@ impl<'a> LoweringContext<'a> {
32663257
32673258 // This is the normal case.
32683259 AnonymousLifetimeMode :: PassThrough => { }
3269-
3270- // We don't need to do any replacement here as this lifetime
3271- // doesn't refer to an elided lifetime elsewhere in the function
3272- // signature.
3273- AnonymousLifetimeMode :: Replace ( _) => { }
32743260 }
32753261
32763262 self . new_implicit_lifetime ( span)
32773263 }
32783264
3279- fn new_replacement_lifetime (
3280- & mut self ,
3281- replacement : LtReplacement ,
3282- span : Span ,
3283- ) -> hir:: Lifetime {
3284- let hir_id = self . next_id ( ) ;
3285- self . replace_elided_lifetime ( hir_id, span, replacement)
3286- }
3287-
32883265 fn new_implicit_lifetime ( & mut self , span : Span ) -> hir:: Lifetime {
32893266 hir:: Lifetime {
32903267 hir_id : self . next_id ( ) ,
0 commit comments