@@ -44,17 +44,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
44
44
) ?;
45
45
self . copy_op_allow_transmute ( & op, dest) ?;
46
46
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.
48
48
// 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 .
50
50
let alloc_id = tcx. reserve_and_set_type_id_alloc ( ty) ;
51
51
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 ( ( ) )
58
62
}
59
63
60
64
/// Returns `true` if emulation happened.
@@ -101,34 +105,36 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
101
105
let mut a_fields = self . project_array_fields ( & a_fields) ?;
102
106
let mut b_fields = self . project_array_fields ( & b_fields) ?;
103
107
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 ;
115
111
116
- let provenance_matches = a == b;
112
+ while let Some ( ( i, a) ) = a_fields. next ( self ) ? {
113
+ let ( _, b) = b_fields. next ( self ) ?. unwrap ( ) ;
117
114
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 ( ) ) ?;
119
117
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 ( ) ) ? ;
122
120
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;
127
132
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
+ }
132
138
}
133
139
134
140
self . write_scalar ( Scalar :: from_bool ( provenance_matches) , dest) ?;
0 commit comments