@@ -3,10 +3,9 @@ use super::{Parser, TokenType};
3
3
use crate :: maybe_whole;
4
4
use rustc_ast:: ptr:: P ;
5
5
use rustc_ast:: token:: { self , Token } ;
6
- use rustc_ast:: {
7
- self as ast, AngleBracketedArg , AngleBracketedArgs , GenericArg , ParenthesizedArgs ,
8
- } ;
6
+ use rustc_ast:: { self as ast, AngleBracketedArg , AngleBracketedArgs , ParenthesizedArgs } ;
9
7
use rustc_ast:: { AnonConst , AssocTyConstraint , AssocTyConstraintKind , BlockCheckMode } ;
8
+ use rustc_ast:: { GenericArg , GenericArgs } ;
10
9
use rustc_ast:: { Path , PathSegment , QSelf } ;
11
10
use rustc_errors:: { pluralize, Applicability , PResult } ;
12
11
use rustc_span:: source_map:: { BytePos , Span } ;
@@ -414,32 +413,40 @@ impl<'a> Parser<'a> {
414
413
415
414
/// Parses a single argument in the angle arguments `<...>` of a path segment.
416
415
fn parse_angle_arg ( & mut self ) -> PResult < ' a , Option < AngleBracketedArg > > {
417
- if self . check_ident ( ) && self . look_ahead ( 1 , |t| matches ! ( t. kind, token:: Eq | token:: Colon ) )
418
- {
419
- // Parse associated type constraint.
420
- let lo = self . token . span ;
421
- let ident = self . parse_ident ( ) ?;
422
- let kind = if self . eat ( & token:: Eq ) {
423
- let ty = self . parse_assoc_equality_term ( ident, self . prev_token . span ) ?;
424
- AssocTyConstraintKind :: Equality { ty }
425
- } else if self . eat ( & token:: Colon ) {
426
- let bounds = self . parse_generic_bounds ( Some ( self . prev_token . span ) ) ?;
427
- AssocTyConstraintKind :: Bound { bounds }
428
- } else {
429
- unreachable ! ( ) ;
430
- } ;
416
+ let lo = self . token . span ;
417
+ let arg = self . parse_generic_arg ( ) ?;
418
+ match arg {
419
+ Some ( arg) => {
420
+ if self . check ( & token:: Colon ) | self . check ( & token:: Eq ) {
421
+ let ( ident, gen_args) = self . get_ident_from_generic_arg ( arg, lo) ?;
422
+ let kind = if self . eat ( & token:: Colon ) {
423
+ // Parse associated type constraint bound.
424
+
425
+ let bounds = self . parse_generic_bounds ( Some ( self . prev_token . span ) ) ?;
426
+ AssocTyConstraintKind :: Bound { bounds }
427
+ } else if self . eat ( & token:: Eq ) {
428
+ // Parse associated type equality constraint
429
+
430
+ let ty = self . parse_assoc_equality_term ( ident, self . prev_token . span ) ?;
431
+ AssocTyConstraintKind :: Equality { ty }
432
+ } else {
433
+ unreachable ! ( ) ;
434
+ } ;
431
435
432
- let span = lo. to ( self . prev_token . span ) ;
436
+ let span = lo. to ( self . prev_token . span ) ;
433
437
434
- // Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
435
- if let AssocTyConstraintKind :: Bound { .. } = kind {
436
- self . sess . gated_spans . gate ( sym:: associated_type_bounds, span) ;
438
+ // Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
439
+ if let AssocTyConstraintKind :: Bound { .. } = kind {
440
+ self . sess . gated_spans . gate ( sym:: associated_type_bounds, span) ;
441
+ }
442
+ let constraint =
443
+ AssocTyConstraint { id : ast:: DUMMY_NODE_ID , ident, gen_args, kind, span } ;
444
+ Ok ( Some ( AngleBracketedArg :: Constraint ( constraint) ) )
445
+ } else {
446
+ Ok ( Some ( AngleBracketedArg :: Arg ( arg) ) )
447
+ }
437
448
}
438
-
439
- let constraint = AssocTyConstraint { id : ast:: DUMMY_NODE_ID , ident, kind, span } ;
440
- Ok ( Some ( AngleBracketedArg :: Constraint ( constraint) ) )
441
- } else {
442
- Ok ( self . parse_generic_arg ( ) ?. map ( AngleBracketedArg :: Arg ) )
449
+ _ => Ok ( None ) ,
443
450
}
444
451
}
445
452
@@ -534,4 +541,54 @@ impl<'a> Parser<'a> {
534
541
} ;
535
542
Ok ( Some ( arg) )
536
543
}
544
+
545
+ fn get_ident_from_generic_arg (
546
+ & self ,
547
+ gen_arg : GenericArg ,
548
+ lo : Span ,
549
+ ) -> PResult < ' a , ( Ident , Option < GenericArgs > ) > {
550
+ let gen_arg_span = gen_arg. span ( ) ;
551
+ match gen_arg {
552
+ GenericArg :: Type ( t) => match t. into_inner ( ) . kind {
553
+ ast:: TyKind :: Path ( qself, mut path) => {
554
+ if let Some ( qself) = qself {
555
+ let mut err = self . struct_span_err (
556
+ gen_arg_span,
557
+ "qualified paths cannot be used in associated type constraints" ,
558
+ ) ;
559
+ err. span_label (
560
+ qself. path_span ,
561
+ "not allowed in associated type constraints" ,
562
+ ) ;
563
+ return Err ( err) ;
564
+ }
565
+ if path. segments . len ( ) == 1 {
566
+ let path_seg = path. segments . remove ( 0 ) ;
567
+ let ident = path_seg. ident ;
568
+ let gen_args = path_seg. args . map ( |args| args. into_inner ( ) ) ;
569
+ return Ok ( ( ident, gen_args) ) ;
570
+ }
571
+ let err = self . struct_span_err (
572
+ path. span ,
573
+ "paths with multiple segments cannot be used in associated type constraints" ,
574
+ ) ;
575
+ return Err ( err) ;
576
+ }
577
+ _ => {
578
+ let span = lo. to ( self . prev_token . span ) ;
579
+ let err = self . struct_span_err (
580
+ span,
581
+ "only path types can be used in associated type constraints" ,
582
+ ) ;
583
+ return Err ( err) ;
584
+ }
585
+ } ,
586
+ _ => {
587
+ let span = lo. to ( self . prev_token . span ) ;
588
+ let err = self
589
+ . struct_span_err ( span, "only types can be used in associated type constraints" ) ;
590
+ return Err ( err) ;
591
+ }
592
+ }
593
+ }
537
594
}
0 commit comments