@@ -269,15 +269,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
269
269
// Heuristic for type comparison.
270
270
let layout_compat = || {
271
271
if caller_abi. layout . ty == callee_abi. layout . ty {
272
- // No question
272
+ // Fast path: definitely compatible.
273
273
return true ;
274
274
}
275
- if caller_abi. layout . is_unsized ( ) || callee_abi. layout . is_unsized ( ) {
276
- // No, no, no. We require the types to *exactly* match for unsized arguments. If
277
- // these are somehow unsized "in a different way" (say, `dyn Trait` vs `[i32]`),
278
- // then who knows what happens.
279
- return false ;
280
- }
281
275
// This is tricky. Some ABIs split aggregates up into multiple registers etc, so we have
282
276
// to be super careful here. For the scalar ABIs we conveniently already have all the
283
277
// newtypes unwrapped etc, so in those cases we can just compare the scalar components.
@@ -288,14 +282,41 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
288
282
( abi:: Abi :: Scalar ( caller) , abi:: Abi :: Scalar ( callee) ) => {
289
283
primitive_abi_compat ( caller. primitive ( ) , callee. primitive ( ) )
290
284
}
285
+ (
286
+ abi:: Abi :: Vector { element : caller_element, count : caller_count } ,
287
+ abi:: Abi :: Vector { element : callee_element, count : callee_count } ,
288
+ ) => {
289
+ primitive_abi_compat ( caller_element. primitive ( ) , callee_element. primitive ( ) )
290
+ && caller_count == callee_count
291
+ }
291
292
(
292
293
abi:: Abi :: ScalarPair ( caller1, caller2) ,
293
294
abi:: Abi :: ScalarPair ( callee1, callee2) ,
294
295
) => {
295
296
primitive_abi_compat ( caller1. primitive ( ) , callee1. primitive ( ) )
296
297
&& primitive_abi_compat ( caller2. primitive ( ) , callee2. primitive ( ) )
297
298
}
298
- // Be conservative.
299
+ (
300
+ abi:: Abi :: Aggregate { sized : caller_sized } ,
301
+ abi:: Abi :: Aggregate { sized : callee_sized } ,
302
+ ) => {
303
+ // For these we rely on all the information being encoded in the `PassMode`, so
304
+ // here we only habe to check in-memory compatibility.
305
+ // FIXME: unwrap transparent newtype wrappers instead.
306
+ if !caller_sized || !callee_sized {
307
+ // No, no, no. We require the types to *exactly* match for unsized arguments. If
308
+ // these are somehow unsized "in a different way" (say, `dyn Trait` vs `[i32]`),
309
+ // then who knows what happens.
310
+ // FIXME: ideally we'd support newtyped around unized types, but that requires ensuring
311
+ // that for all values of the metadata, both types will compute the same dynamic size...
312
+ // not an easy thing to check.
313
+ return false ;
314
+ }
315
+ caller_abi. layout . size == callee_abi. layout . size
316
+ && caller_abi. layout . align . abi == callee_abi. layout . align . abi
317
+ }
318
+ // What remains is `Abi::Uninhabited` (which can never be passed anyway) and
319
+ // mismatching ABIs, that should all be rejected.
299
320
_ => false ,
300
321
}
301
322
} ;
@@ -333,15 +354,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
333
354
_ => false ,
334
355
} ;
335
356
336
- // We have to check both. `layout_compat` is needed to reject e.g. `i32` vs `f32`,
337
- // which is not reflected in `PassMode`. `mode_compat` is needed to reject `u8` vs `bool`,
338
- // which have the same `abi::Primitive` but different `arg_ext`.
357
+ // Ideally `PassMode` would capture everything there is about argument passing, but that is
358
+ // not the case: in `FnAbi::llvm_type`, also parts of the layout and type information are
359
+ // used. So we need to check that *both* sufficiently agree to ensures the arguments are
360
+ // compatible.
361
+ // For instance, `layout_compat` is needed to reject `i32` vs `f32`, which is not reflected
362
+ // in `PassMode`. `mode_compat` is needed to reject `u8` vs `bool`, which have the same
363
+ // `abi::Primitive` but different `arg_ext`.
339
364
if layout_compat ( ) && mode_compat ( ) {
340
- // Something went very wrong if our checks don't even imply that the layout is the same.
341
- assert ! (
342
- caller_abi. layout. size == callee_abi. layout. size
343
- && caller_abi. layout. align. abi == callee_abi. layout. align. abi
344
- ) ;
345
365
return true ;
346
366
}
347
367
trace ! (
0 commit comments