Skip to content

Miscompilation of code in or around Iterator::position #161

Description

@benhansen-io

I tried this code (also available at https://github.com/benhansen-io/esp-miscompile-test)

use esp_idf_sys as _; // If using the `libstart` feature of `esp-idf-sys`, always keep this module imported

#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct RGB {
    r: u8,
    g: u8,
    b: u8,
}

impl RGB {
    fn new(r: u8, g: u8, b: u8) -> RGB {
        RGB { r, g, b }
    }
}

fn next_color(curr: RGB, order: &[RGB]) -> RGB {
    let curr_idx = order
        .iter()
        .position(|c| {
            // println!("UNCOMMENT TO STOP PANIC");
            *c == curr
        })
        .unwrap();
    let next_idx = if curr_idx == order.len() - 1 {
        0
    } else {
        curr_idx + 1
    };
    order[next_idx]
}

#[no_mangle]
extern "C" fn rust_main() -> i32 {
    // Temporary. Will disappear once ESP-IDF 4.4 is released, but for now it is necessary to call this function once,
    // or else some patches to the runtime implemented by esp-idf-sys might not link properly.
    esp_idf_sys::link_patches();

    let green: RGB = RGB::new(0, 255, 0);
    let blue: RGB = RGB::new(0, 0, 255);
    let yellow: RGB = RGB::new(255, 255, 0);

    let color_order = [yellow, blue, green];
    let mut curr = yellow;
    println!("Starting");
    loop {
        println!("curr: {:?}", curr);
        curr = next_color(curr, &color_order);
        println!("next: {:?}", curr);
        std::thread::sleep(std::time::Duration::from_millis(500));
    }
}

I expected to see this happen:

2023-02-15 20:44:15 Hello world from C!
2023-02-15 20:44:15 Starting
2023-02-15 20:44:15 curr: RGB { r: 255, g: 255, b: 0 }
2023-02-15 20:44:15 next: RGB { r: 0, g: 0, b: 255 }
2023-02-15 20:44:15 curr: RGB { r: 0, g: 0, b: 255 }
2023-02-15 20:44:16 next: RGB { r: 0, g: 255, b: 0 }
2023-02-15 20:44:16 curr: RGB { r: 0, g: 255, b: 0 }
2023-02-15 20:44:16 next: RGB { r: 255, g: 255, b: 0 }
2023-02-15 20:44:16 curr: RGB { r: 255, g: 255, b: 0 }
...

Instead, this happened:

2023-02-15 20:43:28 Hello world from C!                                                                                                                         
2023-02-15 20:43:28 Starting                                                                                                                                    
2023-02-15 20:43:28 curr: RGB { r: 255, g: 255, b: 0 }                                                                                                          
2023-02-15 20:43:28 next: RGB { r: 0, g: 0, b: 255 }                                                                                                            
2023-02-15 20:43:28 curr: RGB { r: 0, g: 0, b: 255 }                                                                                                            
2023-02-15 20:43:28 ESP-ROM:esp32s3-20210327
2023-02-15 20:43:29 curr: RGB { r: 0, g: 0, b: 255 }
2023-02-15 20:43:29 ESP-ROM:esp32s3-20210327
2023-02-15 20:43:30 curr: RGB { r: 0, g: 0, b: 255 }
2023-02-15 20:43:30 ESP-ROM:esp32s3-20210327
...

Without panic abort immediate I also see:

2023-02-15 20:49:27 thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', src/lib.rs:23:10

Adding the commented out println! or removing the opt-level = "s" both cause the correct output to be displayed.

Meta

rustc --version --verbose:

rustc 1.65.0 (897e37553 2022-11-02)
binary: rustc
commit-hash: 897e37553bba8b42751c67658967889d11ecd120
commit-date: 2022-11-02
host: x86_64-unknown-linux-gnu
release: 1.65.0
LLVM version: 15.0.0

(tested on 1.67.0 too)

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions