@@ -44,17 +44,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
4444        ) ?; 
4545        self . copy_op_allow_transmute ( & op,  dest) ?; 
4646
47-         // Give the first  pointer-size bytes  provenance that knows about the type id. 
47+         // Give the each  pointer-sized chunk  provenance that knows about the type id. 
4848        // Here we rely on `TypeId` being a newtype around an array of pointers, so we 
49-         // first project to its only field and then the first  array element . 
49+         // first project to its only field and then the array elements . 
5050        let  alloc_id = tcx. reserve_and_set_type_id_alloc ( ty) ; 
5151        let  first = self . project_field ( dest,  FieldIdx :: ZERO ) ?; 
52-         let  first = self . project_index ( & first,  0 ) ?; 
53-         let  offset = self . read_scalar ( & first) ?. to_target_usize ( & tcx) ?; 
54-         let  ptr = Pointer :: new ( alloc_id. into ( ) ,  Size :: from_bytes ( offset) ) ; 
55-         let  ptr = self . global_root_pointer ( ptr) ?; 
56-         let  val = Scalar :: from_pointer ( ptr,  & tcx) ; 
57-         self . write_scalar ( val,  & first) 
52+         let  mut  elem_iter = self . project_array_fields ( & first) ?; 
53+         while  let  Some ( ( _,  elem) )  = elem_iter. next ( self ) ? { 
54+             // Decorate this part of the hash with provenance; leave the integer part unchanged. 
55+             let  hash_fragment = self . read_scalar ( & elem) ?. to_target_usize ( & tcx) ?; 
56+             let  ptr = Pointer :: new ( alloc_id. into ( ) ,  Size :: from_bytes ( hash_fragment) ) ; 
57+             let  ptr = self . global_root_pointer ( ptr) ?; 
58+             let  val = Scalar :: from_pointer ( ptr,  & tcx) ; 
59+             self . write_scalar ( val,  & elem) ?; 
60+         } 
61+         interp_ok ( ( ) ) 
5862    } 
5963
6064    /// Returns `true` if emulation happened. 
@@ -101,34 +105,36 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
101105                let  mut  a_fields = self . project_array_fields ( & a_fields) ?; 
102106                let  mut  b_fields = self . project_array_fields ( & b_fields) ?; 
103107
104-                 let  ( _idx,  a)  = a_fields
105-                     . next ( self ) ?
106-                     . expect ( "we know the layout of TypeId has at least 2 array elements" ) ; 
107-                 let  a = self . deref_pointer ( & a) ?; 
108-                 let  ( a,  offset_a)  = self . get_ptr_type_id ( a. ptr ( ) ) ?; 
109- 
110-                 let  ( _idx,  b)  = b_fields
111-                     . next ( self ) ?
112-                     . expect ( "we know the layout of TypeId has at least 2 array elements" ) ; 
113-                 let  b = self . deref_pointer ( & b) ?; 
114-                 let  ( b,  offset_b)  = self . get_ptr_type_id ( b. ptr ( ) ) ?; 
108+                 let  mut  provenance_a = None ; 
109+                 let  mut  provenance_b = None ; 
110+                 let  mut  provenance_matches = true ; 
115111
116-                 let  provenance_matches = a == b; 
112+                 while  let  Some ( ( i,  a) )  = a_fields. next ( self ) ? { 
113+                     let  ( _,  b)  = b_fields. next ( self ) ?. unwrap ( ) ; 
117114
118-                 let  mut  eq_id = offset_a == offset_b; 
115+                     let  a = self . deref_pointer ( & a) ?; 
116+                     let  ( a,  offset_a)  = self . get_ptr_type_id ( a. ptr ( ) ) ?; 
119117
120-                 while   let   Some ( ( _ ,  a ) )  = a_fields . next ( self ) ?  { 
121-                     let  ( _ ,  b )  = b_fields . next ( self ) ? . unwrap ( ) ; 
118+                      let  b =  self . deref_pointer ( & b ) ? ; 
119+                     let  ( b ,  offset_b )  = self . get_ptr_type_id ( b . ptr ( ) ) ? ; 
122120
123-                     let  a = self . read_target_usize ( & a) ?; 
124-                     let  b = self . read_target_usize ( & b) ?; 
125-                     eq_id &= a == b; 
126-                 } 
121+                     if  * provenance_a. get_or_insert ( a)  != a { 
122+                         throw_ub_format ! ( 
123+                             "type_id_eq: the first TypeId argument is invalid, the provenance of chunk {i} does not match the first chunk's" 
124+                         ) 
125+                     } 
126+                     if  * provenance_b. get_or_insert ( b)  != b { 
127+                         throw_ub_format ! ( 
128+                             "type_id_eq: the second TypeId argument is invalid, the provenance of chunk {i} does not match the first chunk's" 
129+                         ) 
130+                     } 
131+                     provenance_matches &= a == b; 
127132
128-                 if  !eq_id && provenance_matches { 
129-                     throw_ub_format ! ( 
130-                         "type_id_eq: one of the TypeId arguments is invalid, the hash does not match the type it represents" 
131-                     ) 
133+                     if  offset_a != offset_b && provenance_matches { 
134+                         throw_ub_format ! ( 
135+                             "type_id_eq: one of the TypeId arguments is invalid, chunk {i} of the hash does not match the type it represents" 
136+                         ) 
137+                     } 
132138                } 
133139
134140                self . write_scalar ( Scalar :: from_bool ( provenance_matches) ,  dest) ?; 
0 commit comments