Skip to content

c2rust generates invalid Rust code for compound literals with pointers requiring mutability #1166

Open
@Yeaseen

Description

Description

c2rust produces invalid Rust code when translating compound literals involving pointers and expressions (e.g., condition--). The generated Rust code incorrectly declares a temporary variable as immutable (let) while attempting to create a mutable reference (&mut) to it, leading to a Rust compiler error.

Source C code

int main() {
    int condition = 1; 
    int *single_value = &(int){condition--}; 
    return 0;
}

Expected Behavior

c2rust should generate valid Rust code that handles the mutability requirements of the compound literal, resulting in successful compilation.

Translated Rust code

#![allow(dead_code, mutable_transmutes, non_camel_case_types, non_snake_case, non_upper_case_globals, unused_assignments, unused_mut)]
use ::transpiled_code::*;
unsafe fn main_0() -> libc::c_int {
    let mut condition: libc::c_int = 1 as libc::c_int;
    let fresh0 = condition;
    condition = condition - 1;
    let mut single_value: *mut libc::c_int = &mut fresh0 as *mut libc::c_int;
    return 0 as libc::c_int;
}
pub fn main() {
    unsafe { ::std::process::exit(main_0() as i32) }
}

Cargo build failure

The translated Rust code incorrectly declares a temporary variable (fresh0) as immutable and attempts to create a mutable reference to it, causing the following Rust compile-time error.

error[E0596]: cannot borrow `fresh0` as mutable, as it is not declared as mutable
 --> src/runner.rs:7:46
  |
7 |     let mut single_value: *mut libc::c_int = &mut fresh0 as *mut libc::c_int;
  |                                              ^^^^^^^^^^^ cannot borrow as mutable

Observation

I think &(int){condition--} involves modifying condition, but the temporary value created by the compound literal (fresh0) does not need to be mutable, as it is never modified in the original C code. Instead, c2rust should declare fresh0 as immutable and adjust the pointer type accordingly to align with C semantics.

let mut condition: libc::c_int = 1 as libc::c_int;
let fresh0 = condition; // fresh0 is immutable
condition = condition - 1; // condition is decremented
let single_value: *const libc::c_int = &fresh0; // Use a const pointer

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions