@@ -8,22 +8,22 @@ use crate::ast::selection_set::{FieldSelection, InlineFragmentSelection, Selecti
88use  crate :: ast:: value:: Value ; 
99use  crate :: state:: supergraph_state:: { self ,  OperationKind ,  TypeNode } ; 
1010
11- /// Order -dependent hashing 
11+ /// A trait for hashing AST nodes, with support for both order -dependent and order-independent  hashing.  
1212pub  trait  ASTHash  { 
13-     fn  ast_hash < H :  Hasher > ( & self ,  hasher :  & mut  H ) ; 
13+     fn  ast_hash < H :  Hasher ,   const   ORDER_INDEPENDENT :   bool > ( & self ,  hasher :  & mut  H ) ; 
1414} 
1515
1616pub  fn  ast_hash ( query :  & OperationDefinition )  -> u64  { 
1717    let  mut  hasher = FxHasher :: default ( ) ; 
18-     query. ast_hash ( & mut  hasher) ; 
18+     query. ast_hash :: < _ ,   false > ( & mut  hasher) ; 
1919    hasher. finish ( ) 
2020} 
2121// In all ShapeHash implementations, we never include anything to do with 
2222// the position of the element in the query, i.e., fields that involve 
2323// `Pos` 
2424
2525impl  ASTHash  for  & OperationKind  { 
26-     fn  ast_hash < H :  Hasher > ( & self ,  hasher :  & mut  H )  { 
26+     fn  ast_hash < H :  Hasher ,   const   ORDER_INDEPENDENT :   bool > ( & self ,  hasher :  & mut  H )  { 
2727        match  self  { 
2828            OperationKind :: Query  => "Query" . hash ( hasher) , 
2929            OperationKind :: Mutation  => "Mutation" . hash ( hasher) , 
@@ -33,55 +33,72 @@ impl ASTHash for &OperationKind {
3333} 
3434
3535impl  ASTHash  for  OperationDefinition  { 
36-     fn  ast_hash < H :  Hasher > ( & self ,  hasher :  & mut  H )  { 
36+     fn  ast_hash < H :  Hasher ,   const   ORDER_INDEPENDENT :   bool > ( & self ,  hasher :  & mut  H )  { 
3737        self . operation_kind 
3838            . as_ref ( ) 
3939            . or ( Some ( & supergraph_state:: OperationKind :: Query ) ) 
40-             . ast_hash ( hasher) ; 
40+             . ast_hash :: < _ ,   ORDER_INDEPENDENT > ( hasher) ; 
4141
42-         self . selection_set . ast_hash ( hasher) ; 
43-         self . variable_definitions . ast_hash ( hasher) ; 
42+         self . selection_set . ast_hash :: < _ ,  ORDER_INDEPENDENT > ( hasher) ; 
43+         self . variable_definitions 
44+             . ast_hash :: < _ ,  ORDER_INDEPENDENT > ( hasher) ; 
4445    } 
4546} 
4647
4748impl < T :  ASTHash >  ASTHash  for  Option < T >  { 
48-     fn  ast_hash < H :  Hasher > ( & self ,  hasher :  & mut  H )  { 
49+     fn  ast_hash < H :  Hasher ,   const   ORDER_INDEPENDENT :   bool > ( & self ,  hasher :  & mut  H )  { 
4950        match  self  { 
5051            None  => false . hash ( hasher) , 
5152            Some ( t)  => { 
5253                Some ( true ) . hash ( hasher) ; 
53-                 t. ast_hash ( hasher) ; 
54+                 t. ast_hash :: < _ ,   ORDER_INDEPENDENT > ( hasher) ; 
5455            } 
5556        } 
5657    } 
5758} 
5859
5960impl  ASTHash  for  SelectionSet  { 
60-     fn  ast_hash < H :  Hasher > ( & self ,  hasher :  & mut  H )  { 
61-         for  item in  & self . items  { 
62-             item. ast_hash ( hasher) ; 
61+     fn  ast_hash < H :  Hasher ,  const  ORDER_INDEPENDENT :  bool > ( & self ,  hasher :  & mut  H )  { 
62+         if  ORDER_INDEPENDENT  { 
63+             let  mut  combined_hash:  u64  = 0 ; 
64+             let  build_hasher = FxBuildHasher ; 
65+ 
66+             // To achieve an order-independent hash, we hash each key-value pair 
67+             // individually and then combine their hashes using XOR (^). 
68+             // Since XOR is commutative, the final hash is not affected by the iteration order. 
69+             for  item in  & self . items  { 
70+                 let  mut  key_val_hasher = build_hasher. build_hasher ( ) ; 
71+                 item. ast_hash :: < _ ,  ORDER_INDEPENDENT > ( & mut  key_val_hasher) ; 
72+                 combined_hash ^= key_val_hasher. finish ( ) ; 
73+             } 
74+ 
75+             hasher. write_u64 ( combined_hash) ; 
76+         }  else  { 
77+             for  item in  & self . items  { 
78+                 item. ast_hash :: < _ ,  ORDER_INDEPENDENT > ( hasher) ; 
79+             } 
6380        } 
6481    } 
6582} 
6683
6784impl  ASTHash  for  SelectionItem  { 
68-     fn  ast_hash < H :  Hasher > ( & self ,  hasher :  & mut  H )  { 
85+     fn  ast_hash < H :  Hasher ,   const   ORDER_INDEPENDENT :   bool > ( & self ,  hasher :  & mut  H )  { 
6986        match  self  { 
70-             SelectionItem :: Field ( field)  => field. ast_hash ( hasher) , 
71-             SelectionItem :: InlineFragment ( frag)  => frag. ast_hash ( hasher) , 
87+             SelectionItem :: Field ( field)  => field. ast_hash :: < _ ,   ORDER_INDEPENDENT > ( hasher) , 
88+             SelectionItem :: InlineFragment ( frag)  => frag. ast_hash :: < _ ,   ORDER_INDEPENDENT > ( hasher) , 
7289            SelectionItem :: FragmentSpread ( name)  => name. hash ( hasher) , 
7390        } 
7491    } 
7592} 
7693
7794impl  ASTHash  for  & FieldSelection  { 
78-     fn  ast_hash < H :  Hasher > ( & self ,  hasher :  & mut  H )  { 
95+     fn  ast_hash < H :  Hasher ,   const   ORDER_INDEPENDENT :   bool > ( & self ,  hasher :  & mut  H )  { 
7996        self . name . hash ( hasher) ; 
8097        self . alias . hash ( hasher) ; 
81-         self . selections . ast_hash ( hasher) ; 
98+         self . selections . ast_hash :: < _ ,   ORDER_INDEPENDENT > ( hasher) ; 
8299
83100        if  let  Some ( args)  = & self . arguments  { 
84-             args. ast_hash ( hasher) ; 
101+             args. ast_hash :: < _ ,   ORDER_INDEPENDENT > ( hasher) ; 
85102        } 
86103
87104        if  let  Some ( var_name)  = self . include_if . as_ref ( )  { 
@@ -96,9 +113,9 @@ impl ASTHash for &FieldSelection {
96113} 
97114
98115impl  ASTHash  for  & InlineFragmentSelection  { 
99-     fn  ast_hash < H :  Hasher > ( & self ,  hasher :  & mut  H )  { 
116+     fn  ast_hash < H :  Hasher ,   const   ORDER_INDEPENDENT :   bool > ( & self ,  hasher :  & mut  H )  { 
100117        self . type_condition . hash ( hasher) ; 
101-         self . selections . ast_hash ( hasher) ; 
118+         self . selections . ast_hash :: < _ ,   ORDER_INDEPENDENT > ( hasher) ; 
102119        if  let  Some ( var_name)  = self . include_if . as_ref ( )  { 
103120            "@include" . hash ( hasher) ; 
104121            var_name. hash ( hasher) ; 
@@ -111,7 +128,7 @@ impl ASTHash for &InlineFragmentSelection {
111128} 
112129
113130impl  ASTHash  for  ArgumentsMap  { 
114-     fn  ast_hash < H :  Hasher > ( & self ,  state :  & mut  H )  { 
131+     fn  ast_hash < H :  Hasher ,   const   ORDER_INDEPENDENT :   bool > ( & self ,  state :  & mut  H )  { 
115132        let  mut  combined_hash:  u64  = 0 ; 
116133        let  build_hasher = FxBuildHasher ; 
117134
@@ -121,7 +138,7 @@ impl ASTHash for ArgumentsMap {
121138        for  ( key,  value)  in  self . into_iter ( )  { 
122139            let  mut  key_val_hasher = build_hasher. build_hasher ( ) ; 
123140            key. hash ( & mut  key_val_hasher) ; 
124-             value. ast_hash ( & mut  key_val_hasher) ; 
141+             value. ast_hash :: < _ ,   ORDER_INDEPENDENT > ( & mut  key_val_hasher) ; 
125142            combined_hash ^= key_val_hasher. finish ( ) ; 
126143        } 
127144
@@ -130,15 +147,15 @@ impl ASTHash for ArgumentsMap {
130147} 
131148
132149impl  ASTHash  for  Vec < VariableDefinition >  { 
133-     fn  ast_hash < H :  Hasher > ( & self ,  hasher :  & mut  H )  { 
150+     fn  ast_hash < H :  Hasher ,   const   ORDER_INDEPENDENT :   bool > ( & self ,  hasher :  & mut  H )  { 
134151        let  mut  combined_hash:  u64  = 0 ; 
135152        let  build_hasher = FxBuildHasher ; 
136153        // To achieve an order-independent hash, we hash each key-value pair 
137154        // individually and then combine their hashes using XOR (^). 
138155        // Since XOR is commutative, the final hash is not affected by the iteration order. 
139156        for  variable in  self . iter ( )  { 
140157            let  mut  local_hasher = build_hasher. build_hasher ( ) ; 
141-             variable. ast_hash ( & mut  local_hasher) ; 
158+             variable. ast_hash :: < _ ,   ORDER_INDEPENDENT > ( & mut  local_hasher) ; 
142159            combined_hash ^= local_hasher. finish ( ) ; 
143160        } 
144161
@@ -147,41 +164,41 @@ impl ASTHash for Vec<VariableDefinition> {
147164} 
148165
149166impl  ASTHash  for  VariableDefinition  { 
150-     fn  ast_hash < H :  Hasher > ( & self ,  hasher :  & mut  H )  { 
167+     fn  ast_hash < H :  Hasher ,   const   ORDER_INDEPENDENT :   bool > ( & self ,  hasher :  & mut  H )  { 
151168        self . name . hash ( hasher) ; 
152-         self . variable_type . ast_hash ( hasher) ; 
153-         self . default_value . ast_hash ( hasher) ; 
169+         self . variable_type . ast_hash :: < _ ,   ORDER_INDEPENDENT > ( hasher) ; 
170+         self . default_value . ast_hash :: < _ ,   ORDER_INDEPENDENT > ( hasher) ; 
154171    } 
155172} 
156173
157174impl  ASTHash  for  TypeNode  { 
158-     fn  ast_hash < H :  Hasher > ( & self ,  hasher :  & mut  H )  { 
175+     fn  ast_hash < H :  Hasher ,   const   ORDER_INDEPENDENT :   bool > ( & self ,  hasher :  & mut  H )  { 
159176        match  self  { 
160177            TypeNode :: Named ( name)  => name. hash ( hasher) , 
161178            TypeNode :: List ( inner)  => { 
162179                "list" . hash ( hasher) ; 
163-                 inner. ast_hash ( hasher) ; 
180+                 inner. ast_hash :: < _ ,   ORDER_INDEPENDENT > ( hasher) ; 
164181            } 
165182            TypeNode :: NonNull ( inner)  => { 
166183                "non_null" . hash ( hasher) ; 
167-                 inner. ast_hash ( hasher) ; 
184+                 inner. ast_hash :: < _ ,   ORDER_INDEPENDENT > ( hasher) ; 
168185            } 
169186        } 
170187    } 
171188} 
172189
173190impl  ASTHash  for  Value  { 
174-     fn  ast_hash < H :  Hasher > ( & self ,  hasher :  & mut  H )  { 
191+     fn  ast_hash < H :  Hasher ,   const   ORDER_INDEPENDENT :   bool > ( & self ,  hasher :  & mut  H )  { 
175192        match  self  { 
176193            Value :: List ( values)  => { 
177194                for  value in  values { 
178-                     value. ast_hash ( hasher) ; 
195+                     value. ast_hash :: < _ ,   ORDER_INDEPENDENT > ( hasher) ; 
179196                } 
180197            } 
181198            Value :: Object ( map)  => { 
182199                for  ( name,  value)  in  map { 
183200                    name. hash ( hasher) ; 
184-                     value. ast_hash ( hasher) ; 
201+                     value. ast_hash :: < _ ,   ORDER_INDEPENDENT > ( hasher) ; 
185202                } 
186203            } 
187204            Value :: Null  => { 
@@ -310,10 +327,10 @@ mod tests {
310327        args2. add_argument ( "a" . to_string ( ) ,  Value :: Int ( 1 ) ) ; 
311328
312329        let  mut  hasher1 = FxHasher :: default ( ) ; 
313-         args1. ast_hash ( & mut  hasher1) ; 
330+         args1. ast_hash :: < _ ,   true > ( & mut  hasher1) ; 
314331
315332        let  mut  hasher2 = FxHasher :: default ( ) ; 
316-         args2. ast_hash ( & mut  hasher2) ; 
333+         args2. ast_hash :: < _ ,   true > ( & mut  hasher2) ; 
317334
318335        assert_eq ! ( 
319336            hasher1. finish( ) , 
@@ -351,10 +368,10 @@ mod tests {
351368        ] ; 
352369
353370        let  mut  hasher1 = FxHasher :: default ( ) ; 
354-         vars1. ast_hash ( & mut  hasher1) ; 
371+         vars1. ast_hash :: < _ ,   true > ( & mut  hasher1) ; 
355372
356373        let  mut  hasher2 = FxHasher :: default ( ) ; 
357-         vars2. ast_hash ( & mut  hasher2) ; 
374+         vars2. ast_hash :: < _ ,   true > ( & mut  hasher2) ; 
358375
359376        assert_eq ! ( 
360377            hasher1. finish( ) , 
0 commit comments