Skip to content

Commit 3f73e3e

Browse files
authored
Unrolled build for rust-lang#125672
Rollup merge of rust-lang#125672 - Lokathor:update-miri-result-ffi, r=RalfJung Add more ABI test cases to miri (RFC 3391) Part of rust-lang#110503 cc `@RalfJung`
2 parents 7ebd2bd + b710404 commit 3f73e3e

File tree

2 files changed

+36
-11
lines changed

2 files changed

+36
-11
lines changed

compiler/rustc_const_eval/src/interpret/terminator.rs

+22-9
Original file line numberDiff line numberDiff line change
@@ -294,17 +294,30 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
294294

295295
/// Unwrap types that are guaranteed a null-pointer-optimization
296296
fn unfold_npo(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
297-
// Check if this is `Option` wrapping some type.
298-
let inner = match layout.ty.kind() {
299-
ty::Adt(def, args) if self.tcx.is_diagnostic_item(sym::Option, def.did()) => {
300-
args[0].as_type().unwrap()
301-
}
302-
_ => {
303-
// Not an `Option`.
304-
return Ok(layout);
297+
// Check if this is `Option` wrapping some type or if this is `Result` wrapping a 1-ZST and
298+
// another type.
299+
let ty::Adt(def, args) = layout.ty.kind() else {
300+
// Not an ADT, so definitely no NPO.
301+
return Ok(layout);
302+
};
303+
let inner = if self.tcx.is_diagnostic_item(sym::Option, def.did()) {
304+
// The wrapped type is the only arg.
305+
self.layout_of(args[0].as_type().unwrap())?
306+
} else if self.tcx.is_diagnostic_item(sym::Result, def.did()) {
307+
// We want to extract which (if any) of the args is not a 1-ZST.
308+
let lhs = self.layout_of(args[0].as_type().unwrap())?;
309+
let rhs = self.layout_of(args[1].as_type().unwrap())?;
310+
if lhs.is_1zst() {
311+
rhs
312+
} else if rhs.is_1zst() {
313+
lhs
314+
} else {
315+
return Ok(layout); // no NPO
305316
}
317+
} else {
318+
return Ok(layout); // no NPO
306319
};
307-
let inner = self.layout_of(inner)?;
320+
308321
// Check if the inner type is one of the NPO-guaranteed ones.
309322
// For that we first unpeel transparent *structs* (but not unions).
310323
let is_npo = |def: AdtDef<'tcx>| {

src/tools/miri/tests/pass/function_calls/abi_compat.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,24 @@ fn main() {
8383
test_abi_compat(main as fn(), id::<i32> as fn(i32) -> i32);
8484
// - 1-ZST
8585
test_abi_compat((), [0u8; 0]);
86-
// - Guaranteed null-pointer-optimizations (RFC 3391).
86+
// - Guaranteed Option<X> null-pointer-optimizations (RFC 3391).
8787
test_abi_compat(&0u32 as *const u32, Some(&0u32));
8888
test_abi_compat(main as fn(), Some(main as fn()));
8989
test_abi_compat(0u32, Some(num::NonZero::new(1u32).unwrap()));
9090
test_abi_compat(&0u32 as *const u32, Some(Wrapper(&0u32)));
91-
test_abi_compat(0u32, Some(Wrapper(num::NonZero::new(1u32).unwrap())));
91+
test_abi_compat(0u32, Some(Wrapper(num::NonZeroU32::new(1u32).unwrap())));
92+
// - Guaranteed Result<X, ZST1> does the same as Option<X> (RFC 3391)
93+
test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(&0u32));
94+
test_abi_compat(main as fn(), Result::<_, ()>::Ok(main as fn()));
95+
test_abi_compat(0u32, Result::<_, ()>::Ok(num::NonZeroU32::new(1).unwrap()));
96+
test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(Wrapper(&0u32)));
97+
test_abi_compat(0u32, Result::<_, ()>::Ok(Wrapper(num::NonZeroU32::new(1).unwrap())));
98+
// - Guaranteed Result<ZST1, X> also does the same as Option<X> (RFC 3391)
99+
test_abi_compat(&0u32 as *const u32, Result::<(), _>::Err(&0u32));
100+
test_abi_compat(main as fn(), Result::<(), _>::Err(main as fn()));
101+
test_abi_compat(0u32, Result::<(), _>::Err(num::NonZeroU32::new(1).unwrap()));
102+
test_abi_compat(&0u32 as *const u32, Result::<(), _>::Err(Wrapper(&0u32)));
103+
test_abi_compat(0u32, Result::<(), _>::Err(Wrapper(num::NonZeroU32::new(1).unwrap())));
92104

93105
// These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible
94106
// with the wrapped field.

0 commit comments

Comments
 (0)