extendr / rextendr

An R package that helps scaffolding extendr-enabled packages or compiling Rust code dynamically
https://extendr.github.io/rextendr/
Other
181 stars 27 forks source link

Strange panic, possibly related to overflow? #242

Closed Jaage closed 1 year ago

Jaage commented 1 year ago

I have code that runs fine in Rust, and compiles when running rust_source(), but panic when called from R:

let D = 
    izip!(
        df.column("A").unwrap().i32().unwrap().into_no_null_iter().collect::<Vec<i32>>(),
        df.column("B").unwrap().i32().unwrap().into_no_null_iter().collect::<Vec<i32>>()
    )
    .into_iter().map(|(a, b)| a + b * width ).collect::<Vec<i32>>();

let E = 
    izip!(
        df.column("A").unwrap().i32().unwrap().into_no_null_iter().collect::<Vec<i32>>(),
        df.column("B").unwrap().i32().unwrap().into_no_null_iter().collect::<Vec<i32>>(),
        df.column("C").unwrap().i32().unwrap().into_no_null_iter().collect::<Vec<i32>>()
    )
    .into_iter().map(|(a, b, c)| a + b * width + c * width * width).collect::<Vec<i32>>();

I know there are no nulls, and it does not panic when calling the Rust code directly. All values are positive integers, but I know that they overflow on occasion as I see negative values in the column. My guess is it has something to do with the overflowing, but I am not sure why that would happen when it is called from R, but not Rust. The panic occurs here, well before any values are returned to R.

Any ideas?

Ilia-Kosenkov commented 1 year ago

Hi, we need at least the meaasge that you get when it panics. Also, a reproducible example could be a nice addition (or at least a code snippet which shows how you define your extendr function that has this issue).

Jaage commented 1 year ago

I identified the error was coming from .into_iter().map(|(a, b, c)| a + b * width + c * width * width).collect::<Vec<i32>>();

Converting everything to i64 solved the issue. Still not sure why it only panicked when called from R and not Rust. I can try to add the full function and some dummy data to recreate the issue tomorrow.

yutannihilation commented 1 year ago

rust_source() compiles with the dev profile, where overflow-checks is enabled. I think you probably use the release profile when you run the bare Rust code, but you should probably use the dev profile for development, and the release profile for performance measurement. Hope this helps!

Jaage commented 1 year ago

That sounds exactly like it! Thanks!