@@ -2155,6 +2155,54 @@ impl Mutability {
2155
2155
}
2156
2156
}
2157
2157
2158
+ /// Either a known lifetime, or the magic `'_` elided lifetime.
2159
+ ///
2160
+ /// Warning: elided lifetimes are not always valid, and sometimes named
2161
+ /// lifetimes are required. In particular, this should never be used for
2162
+ /// output lifetimes.
2163
+ ///
2164
+ /// However, because output lifetimes are never elided, a lifetime that only
2165
+ /// occurs in a single input position can always be elided.
2166
+ #[ derive( Debug , PartialEq , Eq , Hash , Clone ) ]
2167
+ pub enum Lifetime {
2168
+ Named ( LifetimeName ) ,
2169
+ Elided ,
2170
+ }
2171
+
2172
+ impl Lifetime {
2173
+ /// Formats a lifetime for use as a reference lifetime parameter.
2174
+ ///
2175
+ /// In this case, elided lifetimes are empty.
2176
+ pub fn format_for_reference ( & self ) -> TokenStream {
2177
+ match self {
2178
+ Lifetime :: Named ( lifetime) => quote ! { #lifetime} ,
2179
+ Lifetime :: Elided => quote ! { } ,
2180
+ }
2181
+ }
2182
+
2183
+ /// Returns a lifetime ID, if this is a non-elided lifetime. Otherwise
2184
+ /// returns None.
2185
+ pub fn id ( & self ) -> Option < LifetimeId > {
2186
+ match self {
2187
+ Lifetime :: Named ( lifetime) => Some ( lifetime. id ) ,
2188
+ Lifetime :: Elided => None ,
2189
+ }
2190
+ }
2191
+ }
2192
+
2193
+ /// Formats a lifetime for use anywhere.
2194
+ ///
2195
+ /// For the specific context of references, prefer `format_for_reference`, as it
2196
+ /// gives a more idiomatic formatting for elided lifetimes.
2197
+ impl ToTokens for Lifetime {
2198
+ fn to_tokens ( & self , tokens : & mut TokenStream ) {
2199
+ match self {
2200
+ Lifetime :: Named ( named) => named. to_tokens ( tokens) ,
2201
+ Lifetime :: Elided => tokens. extend ( quote ! { ' _ } ) ,
2202
+ }
2203
+ }
2204
+ }
2205
+
2158
2206
#[ derive( Clone , Debug , PartialEq , Eq ) ]
2159
2207
enum RsTypeKind {
2160
2208
Pointer {
@@ -2164,12 +2212,12 @@ enum RsTypeKind {
2164
2212
Reference {
2165
2213
referent : Rc < RsTypeKind > ,
2166
2214
mutability : Mutability ,
2167
- lifetime : LifetimeName ,
2215
+ lifetime : Lifetime ,
2168
2216
} ,
2169
2217
RvalueReference {
2170
2218
referent : Rc < RsTypeKind > ,
2171
2219
mutability : Mutability ,
2172
- lifetime : LifetimeName ,
2220
+ lifetime : Lifetime ,
2173
2221
} ,
2174
2222
FuncPtr {
2175
2223
abi : Rc < str > ,
@@ -2257,6 +2305,7 @@ impl RsTypeKind {
2257
2305
pub fn format_mut_ref_as_uninitialized ( & self ) -> Result < TokenStream > {
2258
2306
match self {
2259
2307
RsTypeKind :: Reference { referent, lifetime, mutability : Mutability :: Mut } => {
2308
+ let lifetime = lifetime. format_for_reference ( ) ;
2260
2309
Ok ( quote ! { & #lifetime mut :: std:: mem:: MaybeUninit < #referent > } )
2261
2310
}
2262
2311
_ => bail ! ( "Expected reference to format as MaybeUninit, got: {:?}" , self ) ,
@@ -2286,7 +2335,7 @@ impl RsTypeKind {
2286
2335
} => {
2287
2336
referent = reference_pointee;
2288
2337
mutability = reference_mutability;
2289
- lifetime = quote ! { # reference_lifetime} ;
2338
+ lifetime = reference_lifetime;
2290
2339
}
2291
2340
RsTypeKind :: Record { .. } => {
2292
2341
// This case doesn't happen for methods, but is needed for free functions mapped
@@ -2296,6 +2345,7 @@ impl RsTypeKind {
2296
2345
_ => bail ! ( "Unexpected type of `self` parameter: {:?}" , self ) ,
2297
2346
}
2298
2347
let mut_ = mutability. format_for_reference ( ) ;
2348
+ let lifetime = lifetime. format_for_reference ( ) ;
2299
2349
if mutability == & Mutability :: Mut && !referent. is_unpin ( ) {
2300
2350
// TODO(b/239661934): Add a `use ::std::pin::Pin` to the crate, and use
2301
2351
// `Pin`.
@@ -2367,8 +2417,8 @@ impl RsTypeKind {
2367
2417
/// if the same LifetimeId is used in two `type_args`).
2368
2418
pub fn lifetimes ( & self ) -> impl Iterator < Item = LifetimeId > + ' _ {
2369
2419
self . dfs_iter ( ) . filter_map ( |t| match t {
2370
- RsTypeKind :: Reference { lifetime, .. } => Some ( lifetime. id ) ,
2371
- RsTypeKind :: RvalueReference { lifetime, .. } => Some ( lifetime. id ) ,
2420
+ RsTypeKind :: Reference { lifetime, .. } => lifetime. id ( ) ,
2421
+ RsTypeKind :: RvalueReference { lifetime, .. } => lifetime. id ( ) ,
2372
2422
_ => None ,
2373
2423
} )
2374
2424
}
@@ -2397,6 +2447,7 @@ impl ToTokens for RsTypeKind {
2397
2447
}
2398
2448
RsTypeKind :: Reference { referent, mutability, lifetime } => {
2399
2449
let mut_ = mutability. format_for_reference ( ) ;
2450
+ let lifetime = lifetime. format_for_reference ( ) ;
2400
2451
let reference = quote ! { & #lifetime #mut_ #referent} ;
2401
2452
if mutability == & Mutability :: Mut && !referent. is_unpin ( ) {
2402
2453
// TODO(b/239661934): Add a `use ::std::pin::Pin` to the crate, and use
@@ -2519,14 +2570,15 @@ fn rs_type_kind(db: &dyn BindingsGenerator, ty: ir::RsType) -> Result<RsTypeKind
2519
2570
}
2520
2571
Ok ( Rc :: new ( get_type_args ( ) ?. remove ( 0 ) ) )
2521
2572
} ;
2522
- let get_lifetime = || -> Result < LifetimeName > {
2573
+ let get_lifetime = || -> Result < Lifetime > {
2523
2574
if ty. lifetime_args . len ( ) != 1 {
2524
2575
bail ! ( "Missing reference lifetime (need exactly 1 lifetime argument): {:?}" , ty) ;
2525
2576
}
2526
2577
let lifetime_id = ty. lifetime_args [ 0 ] ;
2527
2578
ir. get_lifetime ( lifetime_id)
2528
2579
. ok_or_else ( || anyhow ! ( "no known lifetime with id {lifetime_id:?}" ) )
2529
2580
. cloned ( )
2581
+ . map ( |lifetime| Lifetime :: Named ( lifetime) )
2530
2582
} ;
2531
2583
2532
2584
let result = match ty. name . as_deref ( ) {
@@ -6774,4 +6826,28 @@ mod tests {
6774
6826
) ;
6775
6827
Ok ( ( ) )
6776
6828
}
6829
+
6830
+ #[ test]
6831
+ fn test_lifetime_elision_for_references ( ) {
6832
+ let type_args: & [ RsTypeKind ] = & [ ] ;
6833
+ let referent = Rc :: new ( RsTypeKind :: Other { name : "T" . into ( ) , type_args : type_args. into ( ) } ) ;
6834
+ let reference = RsTypeKind :: Reference {
6835
+ referent : referent,
6836
+ mutability : Mutability :: Const ,
6837
+ lifetime : Lifetime :: Elided ,
6838
+ } ;
6839
+ assert_rs_matches ! ( quote! { #reference} , quote! { & T } ) ;
6840
+ }
6841
+
6842
+ #[ test]
6843
+ fn test_lifetime_elision_for_rvalue_references ( ) {
6844
+ let type_args: & [ RsTypeKind ] = & [ ] ;
6845
+ let referent = Rc :: new ( RsTypeKind :: Other { name : "T" . into ( ) , type_args : type_args. into ( ) } ) ;
6846
+ let reference = RsTypeKind :: RvalueReference {
6847
+ referent : referent,
6848
+ mutability : Mutability :: Mut ,
6849
+ lifetime : Lifetime :: Elided ,
6850
+ } ;
6851
+ assert_rs_matches ! ( quote! { #reference} , quote! { RvalueReference <' _, T >} ) ;
6852
+ }
6777
6853
}
0 commit comments