@@ -397,6 +397,7 @@ crate enum TokenType {
397
397
Ident ,
398
398
Path ,
399
399
Type ,
400
+ Const ,
400
401
}
401
402
402
403
impl TokenType {
@@ -409,6 +410,7 @@ impl TokenType {
409
410
TokenType :: Ident => "identifier" . to_string ( ) ,
410
411
TokenType :: Path => "path" . to_string ( ) ,
411
412
TokenType :: Type => "type" . to_string ( ) ,
413
+ TokenType :: Const => "const" . to_string ( ) ,
412
414
}
413
415
}
414
416
}
@@ -946,6 +948,19 @@ impl<'a> Parser<'a> {
946
948
}
947
949
}
948
950
951
+ fn check_const_param ( & mut self ) -> bool {
952
+ self . check_keyword ( keywords:: Const )
953
+ }
954
+
955
+ fn check_const_arg ( & mut self ) -> bool {
956
+ if self . token . can_begin_const_arg ( ) {
957
+ true
958
+ } else {
959
+ self . expected_tokens . push ( TokenType :: Const ) ;
960
+ false
961
+ }
962
+ }
963
+
949
964
/// Expect and consume a `+`. if `+=` is seen, replace it with a `=`
950
965
/// and continue. If a `+` is not seen, return false.
951
966
///
@@ -5482,15 +5497,28 @@ impl<'a> Parser<'a> {
5482
5497
Ok ( ( ident, TraitItemKind :: Type ( bounds, default) , generics) )
5483
5498
}
5484
5499
5500
+ fn parse_const_param ( & mut self , preceding_attrs : Vec < Attribute > ) -> PResult < ' a , GenericParam > {
5501
+ self . expect_keyword ( keywords:: Const ) ?;
5502
+ let ident = self . parse_ident ( ) ?;
5503
+ self . expect ( & token:: Colon ) ?;
5504
+ let ty = self . parse_ty ( ) ?;
5505
+
5506
+ Ok ( GenericParam {
5507
+ ident,
5508
+ id : ast:: DUMMY_NODE_ID ,
5509
+ attrs : preceding_attrs. into ( ) ,
5510
+ bounds : Vec :: new ( ) ,
5511
+ kind : GenericParamKind :: Const {
5512
+ ty,
5513
+ }
5514
+ } )
5515
+ }
5516
+
5485
5517
/// Parses (possibly empty) list of lifetime and type parameters, possibly including
5486
5518
/// trailing comma and erroneous trailing attributes.
5487
5519
crate fn parse_generic_params ( & mut self ) -> PResult < ' a , Vec < ast:: GenericParam > > {
5488
- let mut lifetimes = Vec :: new ( ) ;
5489
5520
let mut params = Vec :: new ( ) ;
5490
- let mut seen_ty_param: Option < Span > = None ;
5491
- let mut last_comma_span = None ;
5492
- let mut bad_lifetime_pos = vec ! [ ] ;
5493
- let mut suggestions = vec ! [ ] ;
5521
+ let mut prev_param: Option < ParamKindOrd > = None ;
5494
5522
loop {
5495
5523
let attrs = self . parse_outer_attributes ( ) ?;
5496
5524
if self . check_lifetime ( ) {
@@ -5501,64 +5529,45 @@ impl<'a> Parser<'a> {
5501
5529
} else {
5502
5530
Vec :: new ( )
5503
5531
} ;
5504
- lifetimes . push ( ast:: GenericParam {
5532
+ params . push ( ast:: GenericParam {
5505
5533
ident : lifetime. ident ,
5506
5534
id : lifetime. id ,
5507
5535
attrs : attrs. into ( ) ,
5508
5536
bounds,
5509
5537
kind : ast:: GenericParamKind :: Lifetime ,
5510
5538
} ) ;
5511
- if let Some ( sp) = seen_ty_param {
5512
- let remove_sp = last_comma_span. unwrap_or ( self . prev_span ) . to ( self . prev_span ) ;
5513
- bad_lifetime_pos. push ( self . prev_span ) ;
5514
- if let Ok ( snippet) = self . sess . source_map ( ) . span_to_snippet ( self . prev_span ) {
5515
- suggestions. push ( ( remove_sp, String :: new ( ) ) ) ;
5516
- suggestions. push ( (
5517
- sp. shrink_to_lo ( ) ,
5518
- format ! ( "{}, " , snippet) ) ) ;
5519
- }
5520
- }
5539
+ prev_param = Some ( ParamKindOrd :: Lifetime ) ;
5540
+ } else if self . check_const_param ( ) {
5541
+ // Parse const parameter.
5542
+ params. push ( self . parse_const_param ( attrs) ?) ;
5543
+ prev_param = Some ( ParamKindOrd :: Const ) ;
5521
5544
} else if self . check_ident ( ) {
5522
5545
// Parse type parameter.
5523
5546
params. push ( self . parse_ty_param ( attrs) ?) ;
5524
- if seen_ty_param. is_none ( ) {
5525
- seen_ty_param = Some ( self . prev_span ) ;
5526
- }
5547
+ prev_param = Some ( ParamKindOrd :: Type ) ;
5527
5548
} else {
5528
5549
// Check for trailing attributes and stop parsing.
5529
5550
if !attrs. is_empty ( ) {
5530
- let param_kind = if seen_ty_param. is_some ( ) { "type" } else { "lifetime" } ;
5531
- self . struct_span_err (
5532
- attrs[ 0 ] . span ,
5533
- & format ! ( "trailing attribute after {} parameters" , param_kind) ,
5534
- )
5535
- . span_label ( attrs[ 0 ] . span , "attributes must go before parameters" )
5536
- . emit ( ) ;
5551
+ if let Some ( prev_param) = prev_param {
5552
+ self . struct_span_err (
5553
+ attrs[ 0 ] . span ,
5554
+ & format ! (
5555
+ "trailing attribute after {} parameter" ,
5556
+ prev_param,
5557
+ ) ,
5558
+ )
5559
+ . span_label ( attrs[ 0 ] . span , "attributes must go before parameters" )
5560
+ . emit ( ) ;
5561
+ }
5537
5562
}
5538
5563
break
5539
5564
}
5540
5565
5541
5566
if !self . eat ( & token:: Comma ) {
5542
5567
break
5543
5568
}
5544
- last_comma_span = Some ( self . prev_span ) ;
5545
- }
5546
- if !bad_lifetime_pos. is_empty ( ) {
5547
- let mut err = self . struct_span_err (
5548
- bad_lifetime_pos,
5549
- "lifetime parameters must be declared prior to type parameters" ,
5550
- ) ;
5551
- if !suggestions. is_empty ( ) {
5552
- err. multipart_suggestion (
5553
- "move the lifetime parameter prior to the first type parameter" ,
5554
- suggestions,
5555
- Applicability :: MachineApplicable ,
5556
- ) ;
5557
- }
5558
- err. emit ( ) ;
5559
5569
}
5560
- lifetimes. extend ( params) ; // ensure the correct order of lifetimes and type params
5561
- Ok ( lifetimes)
5570
+ Ok ( params)
5562
5571
}
5563
5572
5564
5573
/// Parse a set of optional generic type parameter declarations. Where
@@ -5740,35 +5749,16 @@ impl<'a> Parser<'a> {
5740
5749
fn parse_generic_args ( & mut self ) -> PResult < ' a , ( Vec < GenericArg > , Vec < TypeBinding > ) > {
5741
5750
let mut args = Vec :: new ( ) ;
5742
5751
let mut bindings = Vec :: new ( ) ;
5752
+ let mut misplaced_assoc_ty_bindings: Vec < Span > = Vec :: new ( ) ;
5753
+ let mut assoc_ty_bindings: Vec < Span > = Vec :: new ( ) ;
5743
5754
5744
- let mut seen_type = false ;
5745
- let mut seen_binding = false ;
5755
+ let args_lo = self . span ;
5746
5756
5747
- let mut last_comma_span = None ;
5748
- let mut first_type_or_binding_span: Option < Span > = None ;
5749
- let mut first_binding_span: Option < Span > = None ;
5750
-
5751
- let mut bad_lifetime_pos = vec ! [ ] ;
5752
- let mut bad_type_pos = vec ! [ ] ;
5753
-
5754
- let mut lifetime_suggestions = vec ! [ ] ;
5755
- let mut type_suggestions = vec ! [ ] ;
5756
5757
loop {
5757
5758
if self . check_lifetime ( ) && self . look_ahead ( 1 , |t| !t. is_like_plus ( ) ) {
5758
5759
// Parse lifetime argument.
5759
5760
args. push ( GenericArg :: Lifetime ( self . expect_lifetime ( ) ) ) ;
5760
-
5761
- if seen_type || seen_binding {
5762
- let remove_sp = last_comma_span. unwrap_or ( self . prev_span ) . to ( self . prev_span ) ;
5763
- bad_lifetime_pos. push ( self . prev_span ) ;
5764
-
5765
- if let Ok ( snippet) = self . sess . source_map ( ) . span_to_snippet ( self . prev_span ) {
5766
- lifetime_suggestions. push ( ( remove_sp, String :: new ( ) ) ) ;
5767
- lifetime_suggestions. push ( (
5768
- first_type_or_binding_span. unwrap ( ) . shrink_to_lo ( ) ,
5769
- format ! ( "{}, " , snippet) ) ) ;
5770
- }
5771
- }
5761
+ misplaced_assoc_ty_bindings. append ( & mut assoc_ty_bindings) ;
5772
5762
} else if self . check_ident ( ) && self . look_ahead ( 1 , |t| t == & token:: Eq ) {
5773
5763
// Parse associated type binding.
5774
5764
let lo = self . span ;
@@ -5782,131 +5772,59 @@ impl<'a> Parser<'a> {
5782
5772
ty,
5783
5773
span,
5784
5774
} ) ;
5785
-
5786
- seen_binding = true ;
5787
- if first_type_or_binding_span. is_none ( ) {
5788
- first_type_or_binding_span = Some ( span) ;
5789
- }
5790
- if first_binding_span. is_none ( ) {
5791
- first_binding_span = Some ( span) ;
5792
- }
5775
+ assoc_ty_bindings. push ( span) ;
5776
+ } else if self . check_const_arg ( ) {
5777
+ // Parse const argument.
5778
+ let expr = if let token:: OpenDelim ( token:: Brace ) = self . token {
5779
+ self . parse_block_expr ( None , self . span , BlockCheckMode :: Default , ThinVec :: new ( ) ) ?
5780
+ } else if self . token . can_begin_literal_or_bool ( ) {
5781
+ let lit = self . parse_lit ( ) ?;
5782
+ self . mk_expr ( lit. span , ExprKind :: Lit ( lit) , ThinVec :: new ( ) )
5783
+ } else {
5784
+ // FIXME(const_generics): to distinguish between idents for types and consts,
5785
+ // we should introduce a GenericArg::Ident in the AST and distinguish when
5786
+ // lowering to the HIR. For now, idents for const args are not permitted.
5787
+ return Err (
5788
+ self . fatal ( "identifiers may currently not be used for const generics" )
5789
+ ) ;
5790
+ } ;
5791
+ let value = AnonConst {
5792
+ id : ast:: DUMMY_NODE_ID ,
5793
+ value : expr,
5794
+ } ;
5795
+ args. push ( GenericArg :: Const ( value) ) ;
5796
+ misplaced_assoc_ty_bindings. append ( & mut assoc_ty_bindings) ;
5793
5797
} else if self . check_type ( ) {
5794
5798
// Parse type argument.
5795
- let ty_param = self . parse_ty ( ) ?;
5796
- if seen_binding {
5797
- let remove_sp = last_comma_span. unwrap_or ( self . prev_span ) . to ( self . prev_span ) ;
5798
- bad_type_pos. push ( self . prev_span ) ;
5799
-
5800
- if let Ok ( snippet) = self . sess . source_map ( ) . span_to_snippet ( self . prev_span ) {
5801
- type_suggestions. push ( ( remove_sp, String :: new ( ) ) ) ;
5802
- type_suggestions. push ( (
5803
- first_binding_span. unwrap ( ) . shrink_to_lo ( ) ,
5804
- format ! ( "{}, " , snippet) ) ) ;
5805
- }
5806
- }
5807
-
5808
- if first_type_or_binding_span. is_none ( ) {
5809
- first_type_or_binding_span = Some ( ty_param. span ) ;
5810
- }
5811
- args. push ( GenericArg :: Type ( ty_param) ) ;
5812
- seen_type = true ;
5799
+ args. push ( GenericArg :: Type ( self . parse_ty ( ) ?) ) ;
5800
+ misplaced_assoc_ty_bindings. append ( & mut assoc_ty_bindings) ;
5813
5801
} else {
5814
5802
break
5815
5803
}
5816
5804
5817
5805
if !self . eat ( & token:: Comma ) {
5818
5806
break
5819
- } else {
5820
- last_comma_span = Some ( self . prev_span ) ;
5821
- }
5822
- }
5823
-
5824
- self . maybe_report_incorrect_generic_argument_order (
5825
- bad_lifetime_pos, bad_type_pos, lifetime_suggestions, type_suggestions
5826
- ) ;
5827
-
5828
- Ok ( ( args, bindings) )
5829
- }
5830
-
5831
- /// Maybe report an error about incorrect generic argument order - "lifetime parameters
5832
- /// must be declared before type parameters", "type parameters must be declared before
5833
- /// associated type bindings" or both.
5834
- fn maybe_report_incorrect_generic_argument_order (
5835
- & self ,
5836
- bad_lifetime_pos : Vec < Span > ,
5837
- bad_type_pos : Vec < Span > ,
5838
- lifetime_suggestions : Vec < ( Span , String ) > ,
5839
- type_suggestions : Vec < ( Span , String ) > ,
5840
- ) {
5841
- let mut err = if !bad_lifetime_pos. is_empty ( ) && !bad_type_pos. is_empty ( ) {
5842
- let mut positions = bad_lifetime_pos. clone ( ) ;
5843
- positions. extend_from_slice ( & bad_type_pos) ;
5844
-
5845
- self . struct_span_err (
5846
- positions,
5847
- "generic arguments must declare lifetimes, types and associated type bindings in \
5848
- that order",
5849
- )
5850
- } else if !bad_lifetime_pos. is_empty ( ) {
5851
- self . struct_span_err (
5852
- bad_lifetime_pos. clone ( ) ,
5853
- "lifetime parameters must be declared prior to type parameters"
5854
- )
5855
- } else if !bad_type_pos. is_empty ( ) {
5856
- self . struct_span_err (
5857
- bad_type_pos. clone ( ) ,
5858
- "type parameters must be declared prior to associated type bindings"
5859
- )
5860
- } else {
5861
- return ;
5862
- } ;
5863
-
5864
- if !bad_lifetime_pos. is_empty ( ) {
5865
- for sp in & bad_lifetime_pos {
5866
- err. span_label ( * sp, "must be declared prior to type parameters" ) ;
5867
- }
5868
- }
5869
-
5870
- if !bad_type_pos. is_empty ( ) {
5871
- for sp in & bad_type_pos {
5872
- err. span_label ( * sp, "must be declared prior to associated type bindings" ) ;
5873
5807
}
5874
5808
}
5875
5809
5876
- if !lifetime_suggestions. is_empty ( ) && !type_suggestions. is_empty ( ) {
5877
- let mut suggestions = lifetime_suggestions;
5878
- suggestions. extend_from_slice ( & type_suggestions) ;
5879
-
5880
- let plural = bad_lifetime_pos. len ( ) + bad_type_pos. len ( ) > 1 ;
5881
- err. multipart_suggestion (
5882
- & format ! (
5883
- "move the parameter{}" ,
5884
- if plural { "s" } else { "" } ,
5885
- ) ,
5886
- suggestions,
5887
- Applicability :: MachineApplicable ,
5888
- ) ;
5889
- } else if !lifetime_suggestions. is_empty ( ) {
5890
- err. multipart_suggestion (
5891
- & format ! (
5892
- "move the lifetime parameter{} prior to the first type parameter" ,
5893
- if bad_lifetime_pos. len( ) > 1 { "s" } else { "" } ,
5894
- ) ,
5895
- lifetime_suggestions,
5896
- Applicability :: MachineApplicable ,
5897
- ) ;
5898
- } else if !type_suggestions. is_empty ( ) {
5899
- err. multipart_suggestion (
5900
- & format ! (
5901
- "move the type parameter{} prior to the first associated type binding" ,
5902
- if bad_type_pos. len( ) > 1 { "s" } else { "" } ,
5903
- ) ,
5904
- type_suggestions,
5905
- Applicability :: MachineApplicable ,
5810
+ // FIXME: we would like to report this in ast_validation instead, but we currently do not
5811
+ // preserve ordering of generic parameters with respect to associated type binding, so we
5812
+ // lose that information after parsing.
5813
+ if misplaced_assoc_ty_bindings. len ( ) > 0 {
5814
+ let mut err = self . struct_span_err (
5815
+ args_lo. to ( self . prev_span ) ,
5816
+ "associated type bindings must be declared after generic parameters" ,
5906
5817
) ;
5818
+ for span in misplaced_assoc_ty_bindings {
5819
+ err. span_label (
5820
+ span,
5821
+ "this associated type binding should be moved after the generic parameters" ,
5822
+ ) ;
5823
+ }
5824
+ err. emit ( ) ;
5907
5825
}
5908
5826
5909
- err . emit ( ) ;
5827
+ Ok ( ( args , bindings ) )
5910
5828
}
5911
5829
5912
5830
/// Parses an optional `where` clause and places it in `generics`.
@@ -6526,6 +6444,7 @@ impl<'a> Parser<'a> {
6526
6444
// `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
6527
6445
// `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
6528
6446
// `<` (LIFETIME|IDENT) `=` - generic parameter with a default
6447
+ // `<` const IDENT - generic const parameter
6529
6448
// The only truly ambiguous case is
6530
6449
// `<` IDENT `>` `::` IDENT ...
6531
6450
// we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
@@ -6535,7 +6454,8 @@ impl<'a> Parser<'a> {
6535
6454
( self . look_ahead ( 1 , |t| t == & token:: Pound || t == & token:: Gt ) ||
6536
6455
self . look_ahead ( 1 , |t| t. is_lifetime ( ) || t. is_ident ( ) ) &&
6537
6456
self . look_ahead ( 2 , |t| t == & token:: Gt || t == & token:: Comma ||
6538
- t == & token:: Colon || t == & token:: Eq ) )
6457
+ t == & token:: Colon || t == & token:: Eq ) ||
6458
+ self . look_ahead ( 1 , |t| t. is_keyword ( keywords:: Const ) ) )
6539
6459
}
6540
6460
6541
6461
fn parse_impl_body ( & mut self ) -> PResult < ' a , ( Vec < ImplItem > , Vec < Attribute > ) > {
0 commit comments