In binder_thread_read in the Linux kernel, C2Rust translated a C wait macro into a Rust labeled block whose value was assigned to __ret:
The generated shape was effectively:
__ret = '_c2rust_label_1: {
let mut __ret_0: c_long = 0;
's_53: {
loop {
...
__ret_0 = __int;
break 's_53;
}
finish_wait(...);
}
} as c_int;
The problem is that this block’s final expression was (), because the inner labeled block ended with finish_wait(...), and Rust treats that as unit. Then C2Rust tried to cast () to c_int, which is invalid. Also, the labeled break 's_53 had no value, so the labeled block could not produce the intended integer value on that exit path.
The fix was to make the wait block actually yield __ret_0:
break 's_53 __ret_0;
...
finish_wait(...);
__ret_0
So now the block consistently evaluates to the wait result, usually 0, or the interrupt/error value from prepare_to_wait_event.
See transpiled binder_thread_read in binder.rs.txt
In
binder_thread_readin the Linux kernel, C2Rust translated a C wait macro into a Rust labeled block whose value was assigned to__ret:The generated shape was effectively:
The problem is that this block’s final expression was
(), because the inner labeled block ended withfinish_wait(...), and Rust treats that as unit. Then C2Rust tried to cast()toc_int, which is invalid. Also, the labeled break's_53had no value, so the labeled block could not produce the intended integer value on that exit path.The fix was to make the wait block actually yield
__ret_0:So now the block consistently evaluates to the wait result, usually
0, or the interrupt/error value fromprepare_to_wait_event.See transpiled
binder_thread_readin binder.rs.txt