@@ -315,6 +315,11 @@ enum AnonymousLifetimeMode {
315315 /// For **Deprecated** cases, report an error.
316316 CreateParameter ,
317317
318+ /// Give a hard error when either `&` or `'_` is written. Used to
319+ /// rule out things like `where T: Foo<'_>`. Does not imply an
320+ /// error on default object bounds (e.g., `Box<dyn Foo>`).
321+ ReportError ,
322+
318323 /// Pass responsibility to `resolve_lifetime` code for all cases.
319324 PassThrough ,
320325}
@@ -735,6 +740,10 @@ impl<'a> LoweringContext<'a> {
735740 keywords:: UnderscoreLifetime . name ( ) . as_interned_str ( ) ,
736741 hir:: LifetimeParamKind :: Elided ,
737742 ) ,
743+ ParamName :: Error => (
744+ keywords:: UnderscoreLifetime . name ( ) . as_interned_str ( ) ,
745+ hir:: LifetimeParamKind :: Error ,
746+ ) ,
738747 } ;
739748
740749 // Add a definition for the in-band lifetime def
@@ -791,7 +800,7 @@ impl<'a> LoweringContext<'a> {
791800 }
792801
793802 /// When we have either an elided or `'_` lifetime in an impl
794- /// header, we convert it to
803+ /// header, we convert it to an in-band lifetime.
795804 fn collect_fresh_in_band_lifetime ( & mut self , span : Span ) -> ParamName {
796805 assert ! ( self . is_collecting_in_band_lifetimes) ;
797806 let index = self . lifetimes_to_define . len ( ) ;
@@ -1474,7 +1483,7 @@ impl<'a> LoweringContext<'a> {
14741483 }
14751484 }
14761485 hir:: LifetimeName :: Param ( _) => lifetime. name ,
1477- hir:: LifetimeName :: Static => return ,
1486+ hir:: LifetimeName :: Error | hir :: LifetimeName :: Static => return ,
14781487 } ;
14791488
14801489 if !self . currently_bound_lifetimes . contains ( & name)
@@ -2162,7 +2171,7 @@ impl<'a> LoweringContext<'a> {
21622171 }
21632172 }
21642173 hir:: LifetimeName :: Param ( _) => lifetime. name ,
2165- hir:: LifetimeName :: Static => return ,
2174+ hir:: LifetimeName :: Error | hir :: LifetimeName :: Static => return ,
21662175 } ;
21672176
21682177 if !self . currently_bound_lifetimes . contains ( & name) {
@@ -2293,10 +2302,12 @@ impl<'a> LoweringContext<'a> {
22932302 itctx : ImplTraitContext < ' _ > ,
22942303 ) -> hir:: GenericBound {
22952304 match * tpb {
2296- GenericBound :: Trait ( ref ty, modifier) => hir:: GenericBound :: Trait (
2297- self . lower_poly_trait_ref ( ty, itctx) ,
2298- self . lower_trait_bound_modifier ( modifier) ,
2299- ) ,
2305+ GenericBound :: Trait ( ref ty, modifier) => {
2306+ hir:: GenericBound :: Trait (
2307+ self . lower_poly_trait_ref ( ty, itctx) ,
2308+ self . lower_trait_bound_modifier ( modifier) ,
2309+ )
2310+ }
23002311 GenericBound :: Outlives ( ref lifetime) => {
23012312 hir:: GenericBound :: Outlives ( self . lower_lifetime ( lifetime) )
23022313 }
@@ -2318,6 +2329,8 @@ impl<'a> LoweringContext<'a> {
23182329 AnonymousLifetimeMode :: PassThrough => {
23192330 self . new_named_lifetime ( l. id , span, hir:: LifetimeName :: Underscore )
23202331 }
2332+
2333+ AnonymousLifetimeMode :: ReportError => self . new_error_lifetime ( Some ( l. id ) , span) ,
23212334 } ,
23222335 ident => {
23232336 self . maybe_collect_in_band_lifetime ( ident) ;
@@ -2356,16 +2369,26 @@ impl<'a> LoweringContext<'a> {
23562369 add_bounds : & NodeMap < Vec < GenericBound > > ,
23572370 mut itctx : ImplTraitContext < ' _ > )
23582371 -> hir:: GenericParam {
2359- let mut bounds = self . lower_param_bounds ( & param. bounds , itctx. reborrow ( ) ) ;
2372+ let mut bounds = self . with_anonymous_lifetime_mode (
2373+ AnonymousLifetimeMode :: ReportError ,
2374+ |this| this. lower_param_bounds ( & param. bounds , itctx. reborrow ( ) ) ,
2375+ ) ;
2376+
23602377 match param. kind {
23612378 GenericParamKind :: Lifetime => {
23622379 let was_collecting_in_band = self . is_collecting_in_band_lifetimes ;
23632380 self . is_collecting_in_band_lifetimes = false ;
23642381
2365- let lt = self . lower_lifetime ( & Lifetime { id : param. id , ident : param. ident } ) ;
2382+ let lt = self . with_anonymous_lifetime_mode (
2383+ AnonymousLifetimeMode :: ReportError ,
2384+ |this| this. lower_lifetime ( & Lifetime { id : param. id , ident : param. ident } ) ,
2385+ ) ;
23662386 let param_name = match lt. name {
23672387 hir:: LifetimeName :: Param ( param_name) => param_name,
2368- _ => hir:: ParamName :: Plain ( lt. name . ident ( ) ) ,
2388+ hir:: LifetimeName :: Implicit
2389+ | hir:: LifetimeName :: Underscore
2390+ | hir:: LifetimeName :: Static => hir:: ParamName :: Plain ( lt. name . ident ( ) ) ,
2391+ hir:: LifetimeName :: Error => ParamName :: Error ,
23692392 } ;
23702393 let param = hir:: GenericParam {
23712394 id : lt. id ,
@@ -2489,13 +2512,18 @@ impl<'a> LoweringContext<'a> {
24892512 }
24902513
24912514 fn lower_where_clause ( & mut self , wc : & WhereClause ) -> hir:: WhereClause {
2492- hir:: WhereClause {
2493- id : self . lower_node_id ( wc. id ) . node_id ,
2494- predicates : wc. predicates
2495- . iter ( )
2496- . map ( |predicate| self . lower_where_predicate ( predicate) )
2497- . collect ( ) ,
2498- }
2515+ self . with_anonymous_lifetime_mode (
2516+ AnonymousLifetimeMode :: ReportError ,
2517+ |this| {
2518+ hir:: WhereClause {
2519+ id : this. lower_node_id ( wc. id ) . node_id ,
2520+ predicates : wc. predicates
2521+ . iter ( )
2522+ . map ( |predicate| this. lower_where_predicate ( predicate) )
2523+ . collect ( ) ,
2524+ }
2525+ } ,
2526+ )
24992527 }
25002528
25012529 fn lower_where_predicate ( & mut self , pred : & WherePredicate ) -> hir:: WherePredicate {
@@ -4837,10 +4865,38 @@ impl<'a> LoweringContext<'a> {
48374865 }
48384866 }
48394867
4868+ AnonymousLifetimeMode :: ReportError => self . new_error_lifetime ( None , span) ,
4869+
48404870 AnonymousLifetimeMode :: PassThrough => self . new_implicit_lifetime ( span) ,
48414871 }
48424872 }
48434873
4874+ /// Report an error on illegal use of `'_` or a `&T` with no explicit lifetime;
4875+ /// return a "error lifetime".
4876+ fn new_error_lifetime ( & mut self , id : Option < NodeId > , span : Span ) -> hir:: Lifetime {
4877+ let ( id, msg, label) = match id {
4878+ Some ( id) => ( id, "`'_` cannot be used here" , "`'_` is a reserved lifetime name" ) ,
4879+
4880+ None => (
4881+ self . next_id ( ) . node_id ,
4882+ "`&` without an explicit lifetime name cannot be used here" ,
4883+ "explicit lifetime name needed here" ,
4884+ ) ,
4885+ } ;
4886+
4887+ let mut err = struct_span_err ! (
4888+ self . sess,
4889+ span,
4890+ E0637 ,
4891+ "{}" ,
4892+ msg,
4893+ ) ;
4894+ err. span_label ( span, label) ;
4895+ err. emit ( ) ;
4896+
4897+ self . new_named_lifetime ( id, span, hir:: LifetimeName :: Error )
4898+ }
4899+
48444900 /// Invoked to create the lifetime argument(s) for a path like
48454901 /// `std::cell::Ref<T>`; note that implicit lifetimes in these
48464902 /// sorts of cases are deprecated. This may therefore report a warning or an
@@ -4855,6 +4911,12 @@ impl<'a> LoweringContext<'a> {
48554911 // impl Foo for std::cell::Ref<u32> // note lack of '_
48564912 AnonymousLifetimeMode :: CreateParameter => { }
48574913
4914+ AnonymousLifetimeMode :: ReportError => {
4915+ return ( 0 ..count)
4916+ . map ( |_| self . new_error_lifetime ( None , span) )
4917+ . collect ( ) ;
4918+ }
4919+
48584920 // This is the normal case.
48594921 AnonymousLifetimeMode :: PassThrough => { }
48604922 }
@@ -4885,6 +4947,10 @@ impl<'a> LoweringContext<'a> {
48854947 // `resolve_lifetime` has the code to make that happen.
48864948 AnonymousLifetimeMode :: CreateParameter => { }
48874949
4950+ AnonymousLifetimeMode :: ReportError => {
4951+ // ReportError applies to explicit use of `'_`.
4952+ }
4953+
48884954 // This is the normal case.
48894955 AnonymousLifetimeMode :: PassThrough => { }
48904956 }
0 commit comments