Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more ABI test cases to miri (RFC 3391) #125672

Merged
merged 2 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 22 additions & 9 deletions compiler/rustc_const_eval/src/interpret/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,17 +294,30 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {

/// Unwrap types that are guaranteed a null-pointer-optimization
fn unfold_npo(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
// Check if this is `Option` wrapping some type.
let inner = match layout.ty.kind() {
ty::Adt(def, args) if self.tcx.is_diagnostic_item(sym::Option, def.did()) => {
args[0].as_type().unwrap()
}
_ => {
// Not an `Option`.
return Ok(layout);
// Check if this is `Option` wrapping some type or if this is `Result` wrapping a 1-ZST and
// another type.
let ty::Adt(def, args) = layout.ty.kind() else {
// Not an ADT, so definitely no NPO.
return Ok(layout);
};
let inner = if self.tcx.is_diagnostic_item(sym::Option, def.did()) {
// The wrapped type is the only arg.
self.layout_of(args[0].as_type().unwrap())?
} else if self.tcx.is_diagnostic_item(sym::Result, def.did()) {
// We want to extract which (if any) of the args is not a 1-ZST.
let lhs = self.layout_of(args[0].as_type().unwrap())?;
let rhs = self.layout_of(args[1].as_type().unwrap())?;
if lhs.is_1zst() {
rhs
} else if rhs.is_1zst() {
lhs
} else {
return Ok(layout); // no NPO
}
} else {
return Ok(layout); // no NPO
};
let inner = self.layout_of(inner)?;

// Check if the inner type is one of the NPO-guaranteed ones.
// For that we first unpeel transparent *structs* (but not unions).
let is_npo = |def: AdtDef<'tcx>| {
Expand Down
16 changes: 14 additions & 2 deletions src/tools/miri/tests/pass/function_calls/abi_compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,24 @@ fn main() {
test_abi_compat(main as fn(), id::<i32> as fn(i32) -> i32);
// - 1-ZST
test_abi_compat((), [0u8; 0]);
// - Guaranteed null-pointer-optimizations (RFC 3391).
// - Guaranteed Option<X> null-pointer-optimizations (RFC 3391).
test_abi_compat(&0u32 as *const u32, Some(&0u32));
test_abi_compat(main as fn(), Some(main as fn()));
test_abi_compat(0u32, Some(num::NonZero::new(1u32).unwrap()));
test_abi_compat(&0u32 as *const u32, Some(Wrapper(&0u32)));
test_abi_compat(0u32, Some(Wrapper(num::NonZero::new(1u32).unwrap())));
test_abi_compat(0u32, Some(Wrapper(num::NonZeroU32::new(1u32).unwrap())));
// - Guaranteed Result<X, ZST1> does the same as Option<X> (RFC 3391)
test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(&0u32));
test_abi_compat(main as fn(), Result::<_, ()>::Ok(main as fn()));
test_abi_compat(0u32, Result::<_, ()>::Ok(num::NonZeroU32::new(1).unwrap()));
test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(Wrapper(&0u32)));
test_abi_compat(0u32, Result::<_, ()>::Ok(Wrapper(num::NonZeroU32::new(1).unwrap())));
// - Guaranteed Result<ZST1, X> also does the same as Option<X> (RFC 3391)
test_abi_compat(&0u32 as *const u32, Result::<(), _>::Err(&0u32));
test_abi_compat(main as fn(), Result::<(), _>::Err(main as fn()));
test_abi_compat(0u32, Result::<(), _>::Err(num::NonZeroU32::new(1).unwrap()));
test_abi_compat(&0u32 as *const u32, Result::<(), _>::Err(Wrapper(&0u32)));
test_abi_compat(0u32, Result::<(), _>::Err(Wrapper(num::NonZeroU32::new(1).unwrap())));

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