@@ -337,49 +337,6 @@ enum AnonymousLifetimeMode {
337
337
338
338
/// Pass responsibility to `resolve_lifetime` code for all cases.
339
339
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
- }
383
340
}
384
341
385
342
struct ImplTraitTypeIdVisitor < ' a > { ids : & ' a mut SmallVec < [ NodeId ; 1 ] > }
@@ -1953,8 +1910,7 @@ impl<'a> LoweringContext<'a> {
1953
1910
err. emit ( ) ;
1954
1911
}
1955
1912
AnonymousLifetimeMode :: PassThrough |
1956
- AnonymousLifetimeMode :: ReportError |
1957
- AnonymousLifetimeMode :: Replace ( _) => {
1913
+ AnonymousLifetimeMode :: ReportError => {
1958
1914
self . sess . buffer_lint_with_diagnostic (
1959
1915
ELIDED_LIFETIMES_IN_PATHS ,
1960
1916
CRATE_NODE_ID ,
@@ -2141,7 +2097,6 @@ impl<'a> LoweringContext<'a> {
2141
2097
2142
2098
// Remember how many lifetimes were already around so that we can
2143
2099
// only look at the lifetime parameters introduced by the arguments.
2144
- let lifetime_count_before_args = self . lifetimes_to_define . len ( ) ;
2145
2100
let inputs = self . with_anonymous_lifetime_mode ( lt_mode, |this| {
2146
2101
decl. inputs
2147
2102
. iter ( )
@@ -2156,16 +2111,10 @@ impl<'a> LoweringContext<'a> {
2156
2111
} ) ;
2157
2112
2158
2113
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
- ) ;
2164
2114
self . lower_async_fn_ret_ty (
2165
2115
& decl. output ,
2166
2116
in_band_ty_params. expect ( "`make_ret_async` but no `fn_def_id`" ) . 0 ,
2167
2117
ret_id,
2168
- lt_replacement,
2169
2118
)
2170
2119
} else {
2171
2120
match decl. output {
@@ -2230,7 +2179,6 @@ impl<'a> LoweringContext<'a> {
2230
2179
output : & FunctionRetTy ,
2231
2180
fn_def_id : DefId ,
2232
2181
opaque_ty_node_id : NodeId ,
2233
- elided_lt_replacement : LtReplacement ,
2234
2182
) -> hir:: FunctionRetTy {
2235
2183
let span = output. span ( ) ;
2236
2184
@@ -2248,9 +2196,65 @@ impl<'a> LoweringContext<'a> {
2248
2196
2249
2197
self . allocate_hir_id_counter ( opaque_ty_node_id) ;
2250
2198
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
+
2251
2247
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.
2252
2256
let future_bound = this. with_anonymous_lifetime_mode (
2253
- AnonymousLifetimeMode :: Replace ( elided_lt_replacement ) ,
2257
+ AnonymousLifetimeMode :: CreateParameter ,
2254
2258
|this| this. lower_async_fn_output_type_to_future_bound (
2255
2259
output,
2256
2260
fn_def_id,
@@ -2304,19 +2308,52 @@ impl<'a> LoweringContext<'a> {
2304
2308
( opaque_ty_id, lifetime_params)
2305
2309
} ) ;
2306
2310
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) ,
2316
2336
} )
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
+ ) ;
2318
2351
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 ( ) ) ;
2320
2357
2321
2358
hir:: FunctionRetTy :: Return ( P ( hir:: Ty {
2322
2359
node : opaque_ty_ref,
@@ -2412,11 +2449,6 @@ impl<'a> LoweringContext<'a> {
2412
2449
}
2413
2450
2414
2451
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
- }
2420
2452
} ,
2421
2453
ident => {
2422
2454
self . maybe_collect_in_band_lifetime ( ident) ;
@@ -2439,39 +2471,6 @@ impl<'a> LoweringContext<'a> {
2439
2471
}
2440
2472
}
2441
2473
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
-
2475
2474
fn lower_generic_params (
2476
2475
& mut self ,
2477
2476
params : & [ GenericParam ] ,
@@ -3174,10 +3173,6 @@ impl<'a> LoweringContext<'a> {
3174
3173
AnonymousLifetimeMode :: ReportError => self . new_error_lifetime ( None , span) ,
3175
3174
3176
3175
AnonymousLifetimeMode :: PassThrough => self . new_implicit_lifetime ( span) ,
3177
-
3178
- AnonymousLifetimeMode :: Replace ( replacement) => {
3179
- self . new_replacement_lifetime ( replacement, span)
3180
- }
3181
3176
}
3182
3177
}
3183
3178
@@ -3231,10 +3226,6 @@ impl<'a> LoweringContext<'a> {
3231
3226
// This is the normal case.
3232
3227
AnonymousLifetimeMode :: PassThrough => self . new_implicit_lifetime ( span) ,
3233
3228
3234
- AnonymousLifetimeMode :: Replace ( replacement) => {
3235
- self . new_replacement_lifetime ( replacement, span)
3236
- }
3237
-
3238
3229
AnonymousLifetimeMode :: ReportError => self . new_error_lifetime ( None , span) ,
3239
3230
}
3240
3231
}
@@ -3266,25 +3257,11 @@ impl<'a> LoweringContext<'a> {
3266
3257
3267
3258
// This is the normal case.
3268
3259
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 ( _) => { }
3274
3260
}
3275
3261
3276
3262
self . new_implicit_lifetime ( span)
3277
3263
}
3278
3264
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
-
3288
3265
fn new_implicit_lifetime ( & mut self , span : Span ) -> hir:: Lifetime {
3289
3266
hir:: Lifetime {
3290
3267
hir_id : self . next_id ( ) ,
0 commit comments