Open
Description
I noticed this while writing a codegen test for #37939 (comment).
It seems that Result<u32, u32>
and Result<i32, i32>
are passed as two 32-bit numbers, while Result<i32, u32>
and Result<u32, i32>
are passed as a single 64-bit number.
Compiler: rustc 1.65.0-nightly (86c6ebee8 2022-08-16)
Code
pub fn result_nop_match_i32(x: Result<i32, i32>) -> Result<i32, i32> {
match x {
Ok(x) => Ok(x),
Err(x) => Err(x),
}
}
pub fn result_nop_match_u32(x: Result<u32, u32>) -> Result<u32, u32> {
match x {
Ok(x) => Ok(x),
Err(x) => Err(x),
}
}
pub fn result_nop_match_i32_u32(x: Result<i32, u32>) -> Result<i32, u32> {
match x {
Ok(x) => Ok(x),
Err(x) => Err(x),
}
}
pub fn result_nop_match_u32_i32(x: Result<u32, i32>) -> Result<u32, i32> {
match x {
Ok(x) => Ok(x),
Err(x) => Err(x),
}
}
LLVM IR
define { i32, i32 } @_ZN7example20result_nop_match_i3217h90973337e0ea1f0bE(i32 noundef %0, i32 %1) unnamed_addr #0 !dbg !6 {
%2 = insertvalue { i32, i32 } undef, i32 %0, 0, !dbg !11
%3 = insertvalue { i32, i32 } %2, i32 %1, 1, !dbg !11
ret { i32, i32 } %3, !dbg !11
}
define { i32, i32 } @_ZN7example20result_nop_match_u3217ha367bf54ac4241a2E(i32 noundef %0, i32 %1) unnamed_addr #0 !dbg !12 {
%2 = insertvalue { i32, i32 } undef, i32 %0, 0, !dbg !13
%3 = insertvalue { i32, i32 } %2, i32 %1, 1, !dbg !13
ret { i32, i32 } %3, !dbg !13
}
define i64 @_ZN7example24result_nop_match_i32_u3217h0912c9953cfa7e17E(i64 returned %0) unnamed_addr #0 !dbg !14 {
ret i64 %0, !dbg !15
}
define i64 @_ZN7example24result_nop_match_u32_i3217h8fc452067b26b8ddE(i64 returned %0) unnamed_addr #0 !dbg !16 {
ret i64 %0, !dbg !17
}
https://rust.godbolt.org/z/n91oWdjMh
I'm not sure if there's something stopping Result<u32, u32>
from being coerced to a single 64-bit number (maybe some heuristic for auto-vectorization?), but this seemed a bit odd to me. It's also a bit surprising to me that Result<u32, u32>
is represented as define { i32, i32 }
, but I don't really know a lot about the Rust ABI.