@@ -113,28 +113,47 @@ impl<Prov: Provenance> Immediate<Prov> {
113113 }
114114
115115 /// Assert that this immediate is a valid value for the given ABI.
116- pub fn assert_matches_abi ( self , abi : Abi , cx : & impl HasDataLayout ) {
116+ pub fn assert_matches_abi ( self , abi : Abi , msg : & str , cx : & impl HasDataLayout ) {
117117 match ( self , abi) {
118118 ( Immediate :: Scalar ( scalar) , Abi :: Scalar ( s) ) => {
119- assert_eq ! ( scalar. size( ) , s. size( cx) ) ;
119+ assert_eq ! ( scalar. size( ) , s. size( cx) , "{msg}: scalar value has wrong size" ) ;
120120 if !matches ! ( s. primitive( ) , abi:: Pointer ( ..) ) {
121121 // This is not a pointer, it should not carry provenance.
122- assert ! ( matches!( scalar, Scalar :: Int ( ..) ) ) ;
122+ assert ! (
123+ matches!( scalar, Scalar :: Int ( ..) ) ,
124+ "{msg}: scalar value should be an integer, but has provenance"
125+ ) ;
123126 }
124127 }
125128 ( Immediate :: ScalarPair ( a_val, b_val) , Abi :: ScalarPair ( a, b) ) => {
126- assert_eq ! ( a_val. size( ) , a. size( cx) ) ;
129+ assert_eq ! (
130+ a_val. size( ) ,
131+ a. size( cx) ,
132+ "{msg}: first component of scalar pair has wrong size"
133+ ) ;
127134 if !matches ! ( a. primitive( ) , abi:: Pointer ( ..) ) {
128- assert ! ( matches!( a_val, Scalar :: Int ( ..) ) ) ;
135+ assert ! (
136+ matches!( a_val, Scalar :: Int ( ..) ) ,
137+ "{msg}: first component of scalar pair should be an integer, but has provenance"
138+ ) ;
129139 }
130- assert_eq ! ( b_val. size( ) , b. size( cx) ) ;
140+ assert_eq ! (
141+ b_val. size( ) ,
142+ b. size( cx) ,
143+ "{msg}: second component of scalar pair has wrong size"
144+ ) ;
131145 if !matches ! ( b. primitive( ) , abi:: Pointer ( ..) ) {
132- assert ! ( matches!( b_val, Scalar :: Int ( ..) ) ) ;
146+ assert ! (
147+ matches!( b_val, Scalar :: Int ( ..) ) ,
148+ "{msg}: second component of scalar pair should be an integer, but has provenance"
149+ ) ;
133150 }
134151 }
135- ( Immediate :: Uninit , _) => { }
152+ ( Immediate :: Uninit , _) => {
153+ assert ! ( abi. is_sized( ) , "{msg}: unsized immediates are not a thing" ) ;
154+ }
136155 _ => {
137- bug ! ( "value {self:?} does not match ABI {abi:?})" , )
156+ bug ! ( "{msg}: value {self:?} does not match ABI {abi:?})" , )
138157 }
139158 }
140159 }
@@ -241,6 +260,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
241260
242261 #[ inline( always) ]
243262 pub fn from_immediate ( imm : Immediate < Prov > , layout : TyAndLayout < ' tcx > ) -> Self {
263+ // Without a `cx` we cannot call `assert_matches_abi`.
244264 debug_assert ! (
245265 match ( imm, layout. abi) {
246266 ( Immediate :: Scalar ( ..) , Abi :: Scalar ( ..) ) => true ,
@@ -261,7 +281,6 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
261281
262282 #[ inline]
263283 pub fn from_scalar_int ( s : ScalarInt , layout : TyAndLayout < ' tcx > ) -> Self {
264- assert_eq ! ( s. size( ) , layout. size) ;
265284 Self :: from_scalar ( Scalar :: from ( s) , layout)
266285 }
267286
@@ -334,7 +353,10 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
334353 /// given layout.
335354 // Not called `offset` to avoid confusion with the trait method.
336355 fn offset_ ( & self , offset : Size , layout : TyAndLayout < ' tcx > , cx : & impl HasDataLayout ) -> Self {
337- debug_assert ! ( layout. is_sized( ) , "unsized immediates are not a thing" ) ;
356+ // Verify that the input matches its type.
357+ if cfg ! ( debug_assertions) {
358+ self . assert_matches_abi ( self . layout . abi , "invalid input to Immediate::offset" , cx) ;
359+ }
338360 // `ImmTy` have already been checked to be in-bounds, so we can just check directly if this
339361 // remains in-bounds. This cannot actually be violated since projections are type-checked
340362 // and bounds-checked.
@@ -368,32 +390,14 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
368390 // the field covers the entire type
369391 _ if layout. size == self . layout . size => {
370392 assert_eq ! ( offset. bytes( ) , 0 ) ;
371- assert ! (
372- match ( self . layout. abi, layout. abi) {
373- ( Abi :: Scalar ( l) , Abi :: Scalar ( r) ) => l. size( cx) == r. size( cx) ,
374- ( Abi :: ScalarPair ( l1, l2) , Abi :: ScalarPair ( r1, r2) ) =>
375- l1. size( cx) == r1. size( cx) && l2. size( cx) == r2. size( cx) ,
376- _ => false ,
377- } ,
378- "cannot project into {} immediate with equally-sized field {}\n outer ABI: {:#?}\n field ABI: {:#?}" ,
379- self . layout. ty,
380- layout. ty,
381- self . layout. abi,
382- layout. abi,
383- ) ;
384393 * * self
385394 }
386395 // extract fields from types with `ScalarPair` ABI
387396 ( Immediate :: ScalarPair ( a_val, b_val) , Abi :: ScalarPair ( a, b) ) => {
388- assert_matches ! ( layout. abi, Abi :: Scalar ( ..) ) ;
389397 Immediate :: from ( if offset. bytes ( ) == 0 {
390- // It is "okay" to transmute from `usize` to a pointer (GVN relies on that).
391- // So only compare the size.
392- assert_eq ! ( layout. size, a. size( cx) ) ;
393398 a_val
394399 } else {
395400 assert_eq ! ( offset, a. size( cx) . align_to( b. align( cx) . abi) ) ;
396- assert_eq ! ( layout. size, b. size( cx) ) ;
397401 b_val
398402 } )
399403 }
@@ -405,6 +409,8 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
405409 self . layout
406410 ) ,
407411 } ;
412+ // Ensure the new layout matches the new value.
413+ inner_val. assert_matches_abi ( layout. abi , "invalid field type in Immediate::offset" , cx) ;
408414
409415 ImmTy :: from_immediate ( inner_val, layout)
410416 }
0 commit comments