@@ -639,6 +639,37 @@ impl<'a> AstValidator<'a> {
639639 . emit ( ) ;
640640 }
641641 }
642+
643+ /// Enforce generic args coming before constraints in `<...>` of a path segment.
644+ fn check_generic_args_before_constraints ( & self , data : & AngleBracketedArgs ) {
645+ // Early exit in case it's partitioned as it should be.
646+ if data. args . iter ( ) . is_partitioned ( |arg| matches ! ( arg, AngleBracketedArg :: Arg ( _) ) ) {
647+ return ;
648+ }
649+ // Find all generic argument coming after the first constraint...
650+ let mut misplaced_args = Vec :: new ( ) ;
651+ let mut first = None ;
652+ for arg in & data. args {
653+ match ( arg, first) {
654+ ( AngleBracketedArg :: Arg ( a) , Some ( _) ) => misplaced_args. push ( a. span ( ) ) ,
655+ ( AngleBracketedArg :: Constraint ( c) , None ) => first = Some ( c. span ) ,
656+ ( AngleBracketedArg :: Arg ( _) , None ) | ( AngleBracketedArg :: Constraint ( _) , Some ( _) ) => {
657+ }
658+ }
659+ }
660+ // ...and then error:
661+ self . err_handler ( )
662+ . struct_span_err (
663+ data. span ,
664+ "constraints in a path segment must come after generic arguments" ,
665+ )
666+ . span_labels (
667+ misplaced_args,
668+ "this generic argument must come before the first constraint" ,
669+ )
670+ . span_label ( first. unwrap ( ) , "the first constraint is provided here" )
671+ . emit ( ) ;
672+ }
642673}
643674
644675/// Checks that generic parameters are in the correct order,
@@ -1008,17 +1039,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10081039 fn visit_generic_args ( & mut self , _: Span , generic_args : & ' a GenericArgs ) {
10091040 match * generic_args {
10101041 GenericArgs :: AngleBracketed ( ref data) => {
1011- walk_list ! ( self , visit_generic_arg, & data. args) ;
1012-
1013- // Type bindings such as `Item = impl Debug` in `Iterator<Item = Debug>`
1014- // are allowed to contain nested `impl Trait`.
1015- self . with_impl_trait ( None , |this| {
1016- walk_list ! (
1017- this,
1018- visit_assoc_ty_constraint_from_generic_args,
1019- & data. constraints
1020- ) ;
1021- } ) ;
1042+ self . check_generic_args_before_constraints ( data) ;
1043+
1044+ for arg in & data. args {
1045+ match arg {
1046+ AngleBracketedArg :: Arg ( arg) => self . visit_generic_arg ( arg) ,
1047+ // Type bindings such as `Item = impl Debug` in `Iterator<Item = Debug>`
1048+ // are allowed to contain nested `impl Trait`.
1049+ AngleBracketedArg :: Constraint ( constraint) => {
1050+ self . with_impl_trait ( None , |this| {
1051+ this. visit_assoc_ty_constraint_from_generic_args ( constraint) ;
1052+ } ) ;
1053+ }
1054+ }
1055+ }
10221056 }
10231057 GenericArgs :: Parenthesized ( ref data) => {
10241058 walk_list ! ( self , visit_ty, & data. inputs) ;
0 commit comments