@@ -269,15 +269,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
269269 // Heuristic for type comparison.
270270 let layout_compat = || {
271271 if caller_abi. layout . ty == callee_abi. layout . ty {
272- // No question
272+ // Fast path: definitely compatible.
273273 return true ;
274274 }
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- }
281275 // This is tricky. Some ABIs split aggregates up into multiple registers etc, so we have
282276 // to be super careful here. For the scalar ABIs we conveniently already have all the
283277 // 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> {
288282 ( abi:: Abi :: Scalar ( caller) , abi:: Abi :: Scalar ( callee) ) => {
289283 primitive_abi_compat ( caller. primitive ( ) , callee. primitive ( ) )
290284 }
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+ }
291292 (
292293 abi:: Abi :: ScalarPair ( caller1, caller2) ,
293294 abi:: Abi :: ScalarPair ( callee1, callee2) ,
294295 ) => {
295296 primitive_abi_compat ( caller1. primitive ( ) , callee1. primitive ( ) )
296297 && primitive_abi_compat ( caller2. primitive ( ) , callee2. primitive ( ) )
297298 }
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.
299320 _ => false ,
300321 }
301322 } ;
@@ -333,15 +354,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
333354 _ => false ,
334355 } ;
335356
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`.
339364 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- ) ;
345365 return true ;
346366 }
347367 trace ! (
0 commit comments