@@ -3,10 +3,9 @@ use super::{Parser, TokenType};
33use crate :: maybe_whole;
44use rustc_ast:: ptr:: P ;
55use 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 } ;
97use rustc_ast:: { AnonConst , AssocTyConstraint , AssocTyConstraintKind , BlockCheckMode } ;
8+ use rustc_ast:: { GenericArg , GenericArgs } ;
109use rustc_ast:: { Path , PathSegment , QSelf } ;
1110use rustc_errors:: { pluralize, Applicability , PResult } ;
1211use rustc_span:: source_map:: { BytePos , Span } ;
@@ -414,32 +413,40 @@ impl<'a> Parser<'a> {
414413
415414 /// Parses a single argument in the angle arguments `<...>` of a path segment.
416415 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+ } ;
431435
432- let span = lo. to ( self . prev_token . span ) ;
436+ let span = lo. to ( self . prev_token . span ) ;
433437
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+ }
437448 }
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 ) ,
443450 }
444451 }
445452
@@ -542,4 +549,54 @@ impl<'a> Parser<'a> {
542549 } ;
543550 Ok ( Some ( arg) )
544551 }
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+ }
545602}
0 commit comments