@@ -316,6 +316,11 @@ enum AnonymousLifetimeMode {
316
316
/// For **Deprecated** cases, report an error.
317
317
CreateParameter ,
318
318
319
+ /// Give a hard error when either `&` or `'_` is written. Used to
320
+ /// rule out things like `where T: Foo<'_>`. Does not imply an
321
+ /// error on default object bounds (e.g., `Box<dyn Foo>`).
322
+ ReportError ,
323
+
319
324
/// Pass responsibility to `resolve_lifetime` code for all cases.
320
325
PassThrough ,
321
326
}
@@ -736,6 +741,10 @@ impl<'a> LoweringContext<'a> {
736
741
keywords:: UnderscoreLifetime . name ( ) . as_interned_str ( ) ,
737
742
hir:: LifetimeParamKind :: Elided ,
738
743
) ,
744
+ ParamName :: Error => (
745
+ keywords:: UnderscoreLifetime . name ( ) . as_interned_str ( ) ,
746
+ hir:: LifetimeParamKind :: Error ,
747
+ ) ,
739
748
} ;
740
749
741
750
// Add a definition for the in-band lifetime def
@@ -792,7 +801,7 @@ impl<'a> LoweringContext<'a> {
792
801
}
793
802
794
803
/// When we have either an elided or `'_` lifetime in an impl
795
- /// header, we convert it to
804
+ /// header, we convert it to an in-band lifetime.
796
805
fn collect_fresh_in_band_lifetime ( & mut self , span : Span ) -> ParamName {
797
806
assert ! ( self . is_collecting_in_band_lifetimes) ;
798
807
let index = self . lifetimes_to_define . len ( ) ;
@@ -1475,7 +1484,7 @@ impl<'a> LoweringContext<'a> {
1475
1484
}
1476
1485
}
1477
1486
hir:: LifetimeName :: Param ( _) => lifetime. name ,
1478
- hir:: LifetimeName :: Static => return ,
1487
+ hir:: LifetimeName :: Error | hir :: LifetimeName :: Static => return ,
1479
1488
} ;
1480
1489
1481
1490
if !self . currently_bound_lifetimes . contains ( & name)
@@ -2163,7 +2172,7 @@ impl<'a> LoweringContext<'a> {
2163
2172
}
2164
2173
}
2165
2174
hir:: LifetimeName :: Param ( _) => lifetime. name ,
2166
- hir:: LifetimeName :: Static => return ,
2175
+ hir:: LifetimeName :: Error | hir :: LifetimeName :: Static => return ,
2167
2176
} ;
2168
2177
2169
2178
if !self . currently_bound_lifetimes . contains ( & name) {
@@ -2294,17 +2303,15 @@ impl<'a> LoweringContext<'a> {
2294
2303
itctx : ImplTraitContext < ' _ > ,
2295
2304
) -> hir:: GenericBound {
2296
2305
match * tpb {
2297
- GenericBound :: Trait ( ref ty, modifier) => hir:: GenericBound :: Trait (
2298
- self . lower_poly_trait_ref ( ty, itctx) ,
2299
- self . lower_trait_bound_modifier ( modifier) ,
2300
- ) ,
2301
- GenericBound :: Outlives ( ref lifetime) => {
2302
- // We don't want to accept `'a: '_`:
2303
- self . with_anonymous_lifetime_mode (
2304
- AnonymousLifetimeMode :: PassThrough ,
2305
- |this| hir:: GenericBound :: Outlives ( this. lower_lifetime ( lifetime) ) ,
2306
+ GenericBound :: Trait ( ref ty, modifier) => {
2307
+ hir:: GenericBound :: Trait (
2308
+ self . lower_poly_trait_ref ( ty, itctx) ,
2309
+ self . lower_trait_bound_modifier ( modifier) ,
2306
2310
)
2307
2311
}
2312
+ GenericBound :: Outlives ( ref lifetime) => {
2313
+ hir:: GenericBound :: Outlives ( self . lower_lifetime ( lifetime) )
2314
+ }
2308
2315
}
2309
2316
}
2310
2317
@@ -2323,6 +2330,8 @@ impl<'a> LoweringContext<'a> {
2323
2330
AnonymousLifetimeMode :: PassThrough => {
2324
2331
self . new_named_lifetime ( l. id , span, hir:: LifetimeName :: Underscore )
2325
2332
}
2333
+
2334
+ AnonymousLifetimeMode :: ReportError => self . new_error_lifetime ( Some ( l. id ) , span) ,
2326
2335
} ,
2327
2336
ident => {
2328
2337
self . maybe_collect_in_band_lifetime ( ident) ;
@@ -2361,16 +2370,26 @@ impl<'a> LoweringContext<'a> {
2361
2370
add_bounds : & NodeMap < Vec < GenericBound > > ,
2362
2371
mut itctx : ImplTraitContext < ' _ > )
2363
2372
-> hir:: GenericParam {
2364
- let mut bounds = self . lower_param_bounds ( & param. bounds , itctx. reborrow ( ) ) ;
2373
+ let mut bounds = self . with_anonymous_lifetime_mode (
2374
+ AnonymousLifetimeMode :: ReportError ,
2375
+ |this| this. lower_param_bounds ( & param. bounds , itctx. reborrow ( ) ) ,
2376
+ ) ;
2377
+
2365
2378
match param. kind {
2366
2379
GenericParamKind :: Lifetime => {
2367
2380
let was_collecting_in_band = self . is_collecting_in_band_lifetimes ;
2368
2381
self . is_collecting_in_band_lifetimes = false ;
2369
2382
2370
- let lt = self . lower_lifetime ( & Lifetime { id : param. id , ident : param. ident } ) ;
2383
+ let lt = self . with_anonymous_lifetime_mode (
2384
+ AnonymousLifetimeMode :: ReportError ,
2385
+ |this| this. lower_lifetime ( & Lifetime { id : param. id , ident : param. ident } ) ,
2386
+ ) ;
2371
2387
let param_name = match lt. name {
2372
2388
hir:: LifetimeName :: Param ( param_name) => param_name,
2373
- _ => hir:: ParamName :: Plain ( lt. name . ident ( ) ) ,
2389
+ hir:: LifetimeName :: Implicit
2390
+ | hir:: LifetimeName :: Underscore
2391
+ | hir:: LifetimeName :: Static => hir:: ParamName :: Plain ( lt. name . ident ( ) ) ,
2392
+ hir:: LifetimeName :: Error => ParamName :: Error ,
2374
2393
} ;
2375
2394
let param = hir:: GenericParam {
2376
2395
id : lt. id ,
@@ -2494,13 +2513,18 @@ impl<'a> LoweringContext<'a> {
2494
2513
}
2495
2514
2496
2515
fn lower_where_clause ( & mut self , wc : & WhereClause ) -> hir:: WhereClause {
2497
- hir:: WhereClause {
2498
- id : self . lower_node_id ( wc. id ) . node_id ,
2499
- predicates : wc. predicates
2500
- . iter ( )
2501
- . map ( |predicate| self . lower_where_predicate ( predicate) )
2502
- . collect ( ) ,
2503
- }
2516
+ self . with_anonymous_lifetime_mode (
2517
+ AnonymousLifetimeMode :: ReportError ,
2518
+ |this| {
2519
+ hir:: WhereClause {
2520
+ id : this. lower_node_id ( wc. id ) . node_id ,
2521
+ predicates : wc. predicates
2522
+ . iter ( )
2523
+ . map ( |predicate| this. lower_where_predicate ( predicate) )
2524
+ . collect ( ) ,
2525
+ }
2526
+ } ,
2527
+ )
2504
2528
}
2505
2529
2506
2530
fn lower_where_predicate ( & mut self , pred : & WherePredicate ) -> hir:: WherePredicate {
@@ -4843,10 +4867,38 @@ impl<'a> LoweringContext<'a> {
4843
4867
}
4844
4868
}
4845
4869
4870
+ AnonymousLifetimeMode :: ReportError => self . new_error_lifetime ( None , span) ,
4871
+
4846
4872
AnonymousLifetimeMode :: PassThrough => self . new_implicit_lifetime ( span) ,
4847
4873
}
4848
4874
}
4849
4875
4876
+ /// Report an error on illegal use of `'_` or a `&T` with no explicit lifetime;
4877
+ /// return a "error lifetime".
4878
+ fn new_error_lifetime ( & mut self , id : Option < NodeId > , span : Span ) -> hir:: Lifetime {
4879
+ let ( id, msg, label) = match id {
4880
+ Some ( id) => ( id, "`'_` cannot be used here" , "`'_` is a reserved lifetime name" ) ,
4881
+
4882
+ None => (
4883
+ self . next_id ( ) . node_id ,
4884
+ "`&` without an explicit lifetime name cannot be used here" ,
4885
+ "explicit lifetime name needed here" ,
4886
+ ) ,
4887
+ } ;
4888
+
4889
+ let mut err = struct_span_err ! (
4890
+ self . sess,
4891
+ span,
4892
+ E0637 ,
4893
+ "{}" ,
4894
+ msg,
4895
+ ) ;
4896
+ err. span_label ( span, label) ;
4897
+ err. emit ( ) ;
4898
+
4899
+ self . new_named_lifetime ( id, span, hir:: LifetimeName :: Error )
4900
+ }
4901
+
4850
4902
/// Invoked to create the lifetime argument(s) for a path like
4851
4903
/// `std::cell::Ref<T>`; note that implicit lifetimes in these
4852
4904
/// sorts of cases are deprecated. This may therefore report a warning or an
@@ -4861,6 +4913,12 @@ impl<'a> LoweringContext<'a> {
4861
4913
// impl Foo for std::cell::Ref<u32> // note lack of '_
4862
4914
AnonymousLifetimeMode :: CreateParameter => { }
4863
4915
4916
+ AnonymousLifetimeMode :: ReportError => {
4917
+ return ( 0 ..count)
4918
+ . map ( |_| self . new_error_lifetime ( None , span) )
4919
+ . collect ( ) ;
4920
+ }
4921
+
4864
4922
// This is the normal case.
4865
4923
AnonymousLifetimeMode :: PassThrough => { }
4866
4924
}
@@ -4891,6 +4949,10 @@ impl<'a> LoweringContext<'a> {
4891
4949
// `resolve_lifetime` has the code to make that happen.
4892
4950
AnonymousLifetimeMode :: CreateParameter => { }
4893
4951
4952
+ AnonymousLifetimeMode :: ReportError => {
4953
+ // ReportError applies to explicit use of `'_`.
4954
+ }
4955
+
4894
4956
// This is the normal case.
4895
4957
AnonymousLifetimeMode :: PassThrough => { }
4896
4958
}
0 commit comments