@@ -6,7 +6,7 @@ use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
66use  rustc_error_codes:: * ; 
77use  rustc_errors:: { pluralize,  struct_span_err,  Applicability ,  PResult } ; 
88use  rustc_span:: source_map:: Span ; 
9- use  rustc_span:: symbol:: kw ; 
9+ use  rustc_span:: symbol:: { kw ,  sym } ; 
1010use  syntax:: ast:: { 
1111    self ,  BareFnTy ,  FunctionRetTy ,  GenericParam ,  Ident ,  Lifetime ,  MutTy ,  Ty ,  TyKind , 
1212} ; 
@@ -17,6 +17,24 @@ use syntax::ast::{Mac, Mutability};
1717use  syntax:: ptr:: P ; 
1818use  syntax:: token:: { self ,  Token } ; 
1919
20+ /// Any `?` or `?const` modifiers that appear at the start of a bound. 
21+ struct  BoundModifiers  { 
22+     /// `?Trait`. 
23+      maybe :  Option < Span > , 
24+ 
25+     /// `?const Trait`. 
26+      maybe_const :  Option < Span > , 
27+ } 
28+ 
29+ impl  BoundModifiers  { 
30+     fn  trait_bound_modifier ( & self )  -> TraitBoundModifier  { 
31+         match  self . maybe  { 
32+             Some ( _)  => TraitBoundModifier :: Maybe , 
33+             None  => TraitBoundModifier :: None , 
34+         } 
35+     } 
36+ } 
37+ 
2038/// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`, 
2139/// `IDENT<<u8 as Trait>::AssocTy>`. 
2240/// 
@@ -195,7 +213,9 @@ impl<'a> Parser<'a> {
195213        lo :  Span , 
196214        parse_plus :  bool , 
197215    )  -> PResult < ' a ,  TyKind >  { 
198-         let  poly_trait_ref = PolyTraitRef :: new ( generic_params,  path,  lo. to ( self . prev_span ) ) ; 
216+         assert_ne ! ( self . token,  token:: Question ) ; 
217+ 
218+         let  poly_trait_ref = PolyTraitRef :: new ( generic_params,  path,  None ,  lo. to ( self . prev_span ) ) ; 
199219        let  mut  bounds = vec ! [ GenericBound :: Trait ( poly_trait_ref,  TraitBoundModifier :: None ) ] ; 
200220        if  parse_plus { 
201221            self . eat_plus ( ) ;  // `+`, or `+=` gets split and `+` is discarded 
@@ -421,12 +441,15 @@ impl<'a> Parser<'a> {
421441        let  has_parens = self . eat ( & token:: OpenDelim ( token:: Paren ) ) ; 
422442        let  inner_lo = self . token . span ; 
423443        let  is_negative = self . eat ( & token:: Not ) ; 
424-         let  question = self . eat ( & token:: Question ) . then_some ( self . prev_span ) ; 
444+ 
445+         let  modifiers = self . parse_ty_bound_modifiers ( ) ; 
425446        let  bound = if  self . token . is_lifetime ( )  { 
426-             self . parse_generic_lt_bound ( lo,  inner_lo,  has_parens,  question) ?
447+             self . error_lt_bound_with_modifiers ( modifiers) ; 
448+             self . parse_generic_lt_bound ( lo,  inner_lo,  has_parens) ?
427449        }  else  { 
428-             self . parse_generic_ty_bound ( lo,  has_parens,  question ) ?
450+             self . parse_generic_ty_bound ( lo,  has_parens,  modifiers ) ?
429451        } ; 
452+ 
430453        Ok ( if  is_negative {  Err ( anchor_lo. to ( self . prev_span ) )  }  else  {  Ok ( bound)  } ) 
431454    } 
432455
@@ -439,9 +462,7 @@ impl<'a> Parser<'a> {
439462        lo :  Span , 
440463        inner_lo :  Span , 
441464        has_parens :  bool , 
442-         question :  Option < Span > , 
443465    )  -> PResult < ' a ,  GenericBound >  { 
444-         self . error_opt_out_lifetime ( question) ; 
445466        let  bound = GenericBound :: Outlives ( self . expect_lifetime ( ) ) ; 
446467        if  has_parens { 
447468            // FIXME(Centril): Consider not erroring here and accepting `('lt)` instead, 
@@ -451,8 +472,17 @@ impl<'a> Parser<'a> {
451472        Ok ( bound) 
452473    } 
453474
454-     fn  error_opt_out_lifetime ( & self ,  question :  Option < Span > )  { 
455-         if  let  Some ( span)  = question { 
475+     /// Emits an error if any trait bound modifiers were present. 
476+      fn  error_lt_bound_with_modifiers ( & self ,  modifiers :  BoundModifiers )  { 
477+         if  let  Some ( span)  = modifiers. maybe_const  { 
478+             self . struct_span_err ( 
479+                 span, 
480+                 "`?const` may only modify trait bounds, not lifetime bounds" , 
481+             ) 
482+             . emit ( ) ; 
483+         } 
484+ 
485+         if  let  Some ( span)  = modifiers. maybe  { 
456486            self . struct_span_err ( span,  "`?` may only modify trait bounds, not lifetime bounds" ) 
457487                . emit ( ) ; 
458488        } 
@@ -478,25 +508,58 @@ impl<'a> Parser<'a> {
478508        Ok ( ( ) ) 
479509    } 
480510
511+     /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `?const Trait`. 
512+      /// 
513+      /// If no modifiers are present, this does not consume any tokens. 
514+      /// 
515+      /// ``` 
516+      /// TY_BOUND_MODIFIERS = "?" ["const" ["?"]] 
517+      /// ``` 
518+      fn  parse_ty_bound_modifiers ( & mut  self )  -> BoundModifiers  { 
519+         if  !self . eat ( & token:: Question )  { 
520+             return  BoundModifiers  {  maybe :  None ,  maybe_const :  None  } ; 
521+         } 
522+ 
523+         // `? ...` 
524+         let  first_question = self . prev_span ; 
525+         if  !self . eat_keyword ( kw:: Const )  { 
526+             return  BoundModifiers  {  maybe :  Some ( first_question) ,  maybe_const :  None  } ; 
527+         } 
528+ 
529+         // `?const ...` 
530+         let  maybe_const = first_question. to ( self . prev_span ) ; 
531+         self . sess . gated_spans . gate ( sym:: const_trait_bound_opt_out,  maybe_const) ; 
532+         if  !self . eat ( & token:: Question )  { 
533+             return  BoundModifiers  {  maybe :  None ,  maybe_const :  Some ( maybe_const)  } ; 
534+         } 
535+ 
536+         // `?const ? ...` 
537+         let  second_question = self . prev_span ; 
538+         BoundModifiers  {  maybe :  Some ( second_question) ,  maybe_const :  Some ( maybe_const)  } 
539+     } 
540+ 
481541    /// Parses a type bound according to: 
482542     /// ``` 
483543     /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) 
484-      /// TY_BOUND_NOPAREN = [? ] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`)  
544+      /// TY_BOUND_NOPAREN = [TY_BOUND_MODIFIERS ] [for<LT_PARAM_DEFS>] SIMPLE_PATH 
485545     /// ``` 
546+      /// 
547+      /// For example, this grammar accepts `?const ?for<'a: 'b> m::Trait<'a>`. 
486548     fn  parse_generic_ty_bound ( 
487549        & mut  self , 
488550        lo :  Span , 
489551        has_parens :  bool , 
490-         question :   Option < Span > , 
552+         modifiers :   BoundModifiers , 
491553    )  -> PResult < ' a ,  GenericBound >  { 
492554        let  lifetime_defs = self . parse_late_bound_lifetime_defs ( ) ?; 
493555        let  path = self . parse_path ( PathStyle :: Type ) ?; 
494556        if  has_parens { 
495557            self . expect ( & token:: CloseDelim ( token:: Paren ) ) ?; 
496558        } 
497-         let  poly_trait = PolyTraitRef :: new ( lifetime_defs,  path,  lo. to ( self . prev_span ) ) ; 
498-         let  modifier = question. map_or ( TraitBoundModifier :: None ,  |_| TraitBoundModifier :: Maybe ) ; 
499-         Ok ( GenericBound :: Trait ( poly_trait,  modifier) ) 
559+ 
560+         let  constness = modifiers. maybe_const . map ( |_| ast:: Constness :: NotConst ) ; 
561+         let  poly_trait = PolyTraitRef :: new ( lifetime_defs,  path,  constness,  lo. to ( self . prev_span ) ) ; 
562+         Ok ( GenericBound :: Trait ( poly_trait,  modifiers. trait_bound_modifier ( ) ) ) 
500563    } 
501564
502565    /// Optionally parses `for<$generic_params>`. 
0 commit comments