@@ -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
@@ -542,4 +549,54 @@ impl<'a> Parser<'a> {
542
549
} ;
543
550
Ok ( Some ( arg) )
544
551
}
552
+
553
+ fn get_ident_from_generic_arg (
554
+ & self ,
555
+ gen_arg : GenericArg ,
556
+ lo : Span ,
557
+ ) -> PResult < ' a , ( Ident , Option < GenericArgs > ) > {
558
+ let gen_arg_span = gen_arg. span ( ) ;
559
+ match gen_arg {
560
+ GenericArg :: Type ( t) => match t. into_inner ( ) . kind {
561
+ ast:: TyKind :: Path ( qself, mut path) => {
562
+ if let Some ( qself) = qself {
563
+ let mut err = self . struct_span_err (
564
+ gen_arg_span,
565
+ "qualified paths cannot be used in associated type constraints" ,
566
+ ) ;
567
+ err. span_label (
568
+ qself. path_span ,
569
+ "not allowed in associated type constraints" ,
570
+ ) ;
571
+ return Err ( err) ;
572
+ }
573
+ if path. segments . len ( ) == 1 {
574
+ let path_seg = path. segments . remove ( 0 ) ;
575
+ let ident = path_seg. ident ;
576
+ let gen_args = path_seg. args . map ( |args| args. into_inner ( ) ) ;
577
+ return Ok ( ( ident, gen_args) ) ;
578
+ }
579
+ let err = self . struct_span_err (
580
+ path. span ,
581
+ "paths with multiple segments cannot be used in associated type constraints" ,
582
+ ) ;
583
+ return Err ( err) ;
584
+ }
585
+ _ => {
586
+ let span = lo. to ( self . prev_token . span ) ;
587
+ let err = self . struct_span_err (
588
+ span,
589
+ "only path types can be used in associated type constraints" ,
590
+ ) ;
591
+ return Err ( err) ;
592
+ }
593
+ } ,
594
+ _ => {
595
+ let span = lo. to ( self . prev_token . span ) ;
596
+ let err = self
597
+ . struct_span_err ( span, "only types can be used in associated type constraints" ) ;
598
+ return Err ( err) ;
599
+ }
600
+ }
601
+ }
545
602
}
0 commit comments