`|=` operator on `bool` results in invalid Rust being generated
I tried running c2rust on BRRtools as an example of a small but nontrivial C project. However the generated Rust fails to compile. The input C in question is:
https://github.com/Optiroc/BRRtools/blob/9f6c4708150120284102f9899632d7f5f0b0638a/src/brr_encoder.c#L596-L598
I minified this example to the following C code (x can be either bool or int):
#include <stdbool.h>
// both bool and int reproduce the bug
extern bool x;
int main() {
bool initial_block = false;
initial_block |= x;
}
Running the latest c2rust 030df665741bb9d1b29fe41cdbfd7223a67c5995 produces the following Rust code:
#![allow(dead_code, mutable_transmutes, non_camel_case_types, non_snake_case,
non_upper_case_globals, unused_assignments, unused_mut)]
#![register_tool(c2rust)]
#![feature(main, register_tool)]
use ::c2rust_out::*;
extern "C" {
// both bool and int reproduce the bug
#[no_mangle]
static mut x: bool;
}
unsafe fn main_0() -> libc::c_int {
let mut initial_block: bool = 0 as libc::c_int != 0;
initial_block = (initial_block as libc::c_int | x as libc::c_int) as bool;
return 0;
}
#[main]
pub fn main() { unsafe { ::std::process::exit(main_0() as i32) } }
which produces an error when compiling on both cargo +nightly-2019-12-05 and stable:
error[E0054]: cannot cast as `bool`
--> src/brr_encoder.rs:13:21
|
13 | initial_block = (initial_block as libc::c_int | x as libc::c_int) as bool;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: compare with zero instead: `(initial_block as libc::c_int | x as libc::c_int) != 0`
I've uploaded at repo at https://github.com/nyanpasu64/c2rust-bug. Steps to reproduce:
c2rust transpile --binary brr_encoder --overwrite-existing compile_commands.json
cargo build
The same problem also occurs with &=.
c2rust also generates invalid code when casting bool directly to a pointer type (because boolean as *mut T is invalid).
https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=44a0720a276e962309baf54ba59f759b
I'm guessing this is also the same issue:
_Bool q = 1;
q += 1;
let mut q: bool = 1 as libc::c_int != 0;
q = (q as libc::c_int + 1 as libc::c_int) as bool;
error[E0054]: cannot cast as `bool`
--> src/binary.rs:245:9
|
245 | q = (q as libc::c_int + 1 as libc::c_int) as bool;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: compare with zero instead: `(q as libc::c_int + 1 as libc::c_int) != 0`