@@ -316,6 +316,11 @@ enum AnonymousLifetimeMode {
316316 /// For **Deprecated** cases, report an error.
317317 CreateParameter ,
318318
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+
319324 /// Pass responsibility to `resolve_lifetime` code for all cases.
320325 PassThrough ,
321326}
@@ -736,6 +741,10 @@ impl<'a> LoweringContext<'a> {
736741 keywords:: UnderscoreLifetime . name ( ) . as_interned_str ( ) ,
737742 hir:: LifetimeParamKind :: Elided ,
738743 ) ,
744+ ParamName :: Error => (
745+ keywords:: UnderscoreLifetime . name ( ) . as_interned_str ( ) ,
746+ hir:: LifetimeParamKind :: Error ,
747+ ) ,
739748 } ;
740749
741750 // Add a definition for the in-band lifetime def
@@ -792,7 +801,7 @@ impl<'a> LoweringContext<'a> {
792801 }
793802
794803 /// 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.
796805 fn collect_fresh_in_band_lifetime ( & mut self , span : Span ) -> ParamName {
797806 assert ! ( self . is_collecting_in_band_lifetimes) ;
798807 let index = self . lifetimes_to_define . len ( ) ;
@@ -1475,7 +1484,7 @@ impl<'a> LoweringContext<'a> {
14751484 }
14761485 }
14771486 hir:: LifetimeName :: Param ( _) => lifetime. name ,
1478- hir:: LifetimeName :: Static => return ,
1487+ hir:: LifetimeName :: Error | hir :: LifetimeName :: Static => return ,
14791488 } ;
14801489
14811490 if !self . currently_bound_lifetimes . contains ( & name)
@@ -2163,7 +2172,7 @@ impl<'a> LoweringContext<'a> {
21632172 }
21642173 }
21652174 hir:: LifetimeName :: Param ( _) => lifetime. name ,
2166- hir:: LifetimeName :: Static => return ,
2175+ hir:: LifetimeName :: Error | hir :: LifetimeName :: Static => return ,
21672176 } ;
21682177
21692178 if !self . currently_bound_lifetimes . contains ( & name) {
@@ -2294,17 +2303,15 @@ impl<'a> LoweringContext<'a> {
22942303 itctx : ImplTraitContext < ' _ > ,
22952304 ) -> hir:: GenericBound {
22962305 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) ,
23062310 )
23072311 }
2312+ GenericBound :: Outlives ( ref lifetime) => {
2313+ hir:: GenericBound :: Outlives ( self . lower_lifetime ( lifetime) )
2314+ }
23082315 }
23092316 }
23102317
@@ -2323,6 +2330,8 @@ impl<'a> LoweringContext<'a> {
23232330 AnonymousLifetimeMode :: PassThrough => {
23242331 self . new_named_lifetime ( l. id , span, hir:: LifetimeName :: Underscore )
23252332 }
2333+
2334+ AnonymousLifetimeMode :: ReportError => self . new_error_lifetime ( Some ( l. id ) , span) ,
23262335 } ,
23272336 ident => {
23282337 self . maybe_collect_in_band_lifetime ( ident) ;
@@ -2361,16 +2370,26 @@ impl<'a> LoweringContext<'a> {
23612370 add_bounds : & NodeMap < Vec < GenericBound > > ,
23622371 mut itctx : ImplTraitContext < ' _ > )
23632372 -> 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+
23652378 match param. kind {
23662379 GenericParamKind :: Lifetime => {
23672380 let was_collecting_in_band = self . is_collecting_in_band_lifetimes ;
23682381 self . is_collecting_in_band_lifetimes = false ;
23692382
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+ ) ;
23712387 let param_name = match lt. name {
23722388 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 ,
23742393 } ;
23752394 let param = hir:: GenericParam {
23762395 id : lt. id ,
@@ -2494,13 +2513,18 @@ impl<'a> LoweringContext<'a> {
24942513 }
24952514
24962515 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+ )
25042528 }
25052529
25062530 fn lower_where_predicate ( & mut self , pred : & WherePredicate ) -> hir:: WherePredicate {
@@ -4843,10 +4867,38 @@ impl<'a> LoweringContext<'a> {
48434867 }
48444868 }
48454869
4870+ AnonymousLifetimeMode :: ReportError => self . new_error_lifetime ( None , span) ,
4871+
48464872 AnonymousLifetimeMode :: PassThrough => self . new_implicit_lifetime ( span) ,
48474873 }
48484874 }
48494875
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+
48504902 /// Invoked to create the lifetime argument(s) for a path like
48514903 /// `std::cell::Ref<T>`; note that implicit lifetimes in these
48524904 /// sorts of cases are deprecated. This may therefore report a warning or an
@@ -4861,6 +4913,12 @@ impl<'a> LoweringContext<'a> {
48614913 // impl Foo for std::cell::Ref<u32> // note lack of '_
48624914 AnonymousLifetimeMode :: CreateParameter => { }
48634915
4916+ AnonymousLifetimeMode :: ReportError => {
4917+ return ( 0 ..count)
4918+ . map ( |_| self . new_error_lifetime ( None , span) )
4919+ . collect ( ) ;
4920+ }
4921+
48644922 // This is the normal case.
48654923 AnonymousLifetimeMode :: PassThrough => { }
48664924 }
@@ -4891,6 +4949,10 @@ impl<'a> LoweringContext<'a> {
48914949 // `resolve_lifetime` has the code to make that happen.
48924950 AnonymousLifetimeMode :: CreateParameter => { }
48934951
4952+ AnonymousLifetimeMode :: ReportError => {
4953+ // ReportError applies to explicit use of `'_`.
4954+ }
4955+
48944956 // This is the normal case.
48954957 AnonymousLifetimeMode :: PassThrough => { }
48964958 }
0 commit comments