@@ -639,6 +639,37 @@ impl<'a> AstValidator<'a> {
639
639
. emit ( ) ;
640
640
}
641
641
}
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
+ }
642
673
}
643
674
644
675
/// Checks that generic parameters are in the correct order,
@@ -1008,17 +1039,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1008
1039
fn visit_generic_args ( & mut self , _: Span , generic_args : & ' a GenericArgs ) {
1009
1040
match * generic_args {
1010
1041
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
+ }
1022
1056
}
1023
1057
GenericArgs :: Parenthesized ( ref data) => {
1024
1058
walk_list ! ( self , visit_ty, & data. inputs) ;
0 commit comments