@@ -182,20 +182,28 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
182182 }
183183
184184 fn check_argument_compat (
185+ rust_abi : bool ,
185186 caller : TyLayout < ' tcx > ,
186187 callee : TyLayout < ' tcx > ,
187188 ) -> bool {
188189 if caller. ty == callee. ty {
189190 // No question
190191 return true ;
191192 }
193+ if !rust_abi {
194+ // Don't risk anything
195+ return false ;
196+ }
192197 // Compare layout
193198 match ( & caller. abi , & callee. abi ) {
199+ // Different valid ranges are okay (once we enforce validity,
200+ // that will take care to make it UB to leave the range, just
201+ // like for transmute).
194202 ( layout:: Abi :: Scalar ( ref caller) , layout:: Abi :: Scalar ( ref callee) ) =>
195- // Different valid ranges are okay (once we enforce validity,
196- // that will take care to make it UB to leave the range, just
197- // like for transmute).
198203 caller. value == callee. value ,
204+ ( layout:: Abi :: ScalarPair ( ref caller1, ref caller2) ,
205+ layout:: Abi :: ScalarPair ( ref callee1, ref callee2) ) =>
206+ caller1. value == callee1. value && caller2. value == callee2. value ,
199207 // Be conservative
200208 _ => false
201209 }
@@ -204,22 +212,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
204212 /// Pass a single argument, checking the types for compatibility.
205213 fn pass_argument (
206214 & mut self ,
207- skip_zst : bool ,
215+ rust_abi : bool ,
208216 caller_arg : & mut impl Iterator < Item =OpTy < ' tcx , M :: PointerTag > > ,
209217 callee_arg : PlaceTy < ' tcx , M :: PointerTag > ,
210218 ) -> EvalResult < ' tcx > {
211- if skip_zst && callee_arg. layout . is_zst ( ) {
219+ if rust_abi && callee_arg. layout . is_zst ( ) {
212220 // Nothing to do.
213221 trace ! ( "Skipping callee ZST" ) ;
214222 return Ok ( ( ) ) ;
215223 }
216224 let caller_arg = caller_arg. next ( )
217225 . ok_or_else ( || EvalErrorKind :: FunctionArgCountMismatch ) ?;
218- if skip_zst {
226+ if rust_abi {
219227 debug_assert ! ( !caller_arg. layout. is_zst( ) , "ZSTs must have been already filtered out" ) ;
220228 }
221229 // Now, check
222- if !Self :: check_argument_compat ( caller_arg. layout , callee_arg. layout ) {
230+ if !Self :: check_argument_compat ( rust_abi , caller_arg. layout , callee_arg. layout ) {
223231 return err ! ( FunctionArgMismatch ( caller_arg. layout. ty, callee_arg. layout. ty) ) ;
224232 }
225233 // We allow some transmutes here
@@ -319,7 +327,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
319327 // Figure out how to pass which arguments.
320328 // We have two iterators: Where the arguments come from,
321329 // and where they go to.
322- let skip_zst = match caller_abi {
330+ let rust_abi = match caller_abi {
323331 Abi :: Rust | Abi :: RustCall => true ,
324332 _ => false
325333 } ;
@@ -344,7 +352,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
344352 } ;
345353 // Skip ZSTs
346354 let mut caller_iter = caller_args. iter ( )
347- . filter ( |op| !skip_zst || !op. layout . is_zst ( ) )
355+ . filter ( |op| !rust_abi || !op. layout . is_zst ( ) )
348356 . map ( |op| * op) ;
349357
350358 // Now we have to spread them out across the callee's locals,
@@ -359,11 +367,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
359367 // Must be a tuple
360368 for i in 0 ..dest. layout . fields . count ( ) {
361369 let dest = self . place_field ( dest, i as u64 ) ?;
362- self . pass_argument ( skip_zst , & mut caller_iter, dest) ?;
370+ self . pass_argument ( rust_abi , & mut caller_iter, dest) ?;
363371 }
364372 } else {
365373 // Normal argument
366- self . pass_argument ( skip_zst , & mut caller_iter, dest) ?;
374+ self . pass_argument ( rust_abi , & mut caller_iter, dest) ?;
367375 }
368376 }
369377 // Now we should have no more caller args
@@ -374,7 +382,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
374382 // Don't forget to check the return type!
375383 if let Some ( caller_ret) = dest {
376384 let callee_ret = self . eval_place ( & mir:: Place :: Local ( mir:: RETURN_PLACE ) ) ?;
377- if !Self :: check_argument_compat ( caller_ret. layout , callee_ret. layout ) {
385+ if !Self :: check_argument_compat (
386+ rust_abi,
387+ caller_ret. layout ,
388+ callee_ret. layout ,
389+ ) {
378390 return err ! ( FunctionRetMismatch (
379391 caller_ret. layout. ty, callee_ret. layout. ty
380392 ) ) ;
0 commit comments