- Notifications
You must be signed in to change notification settings - Fork 14k
Description
The nalgebra linear algebra library has a swap_rows method which allows the user to swap two rows of a matrix. Unfortunately, I'm currently investigating a code generation heisenbug which causes this method to corrupt the matrix data in some circumstances.
Given the UB-like symptoms, and the fact that the implementation of swap_rows takes multiple (non-overlapping) &mut references to the target matrix, I wondered if this could be a violation of Rust's aliasing rules. However, @nagisa confirmed that this is not not the case, and that the compiler is probably the culprit here. He identified the recent upgrade from LLVM 7 to LLVM 8 as a cause of this issue (but that later turned out to be incorrect).
Here is a minimal reproducer of my problem:
extern crate nalgebra; use nalgebra::Matrix3x4; fn swappy() -> Matrix3x4<f32> { let mut mat = Matrix3x4::new(1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.); // NOTE: This printf makes the bug go away, suggesting UB or a codegen issue // println!("Result: {}", mat); for i in 0..2 { for j in i+1..3 { if mat[(j, 3)] > mat[(i, 3)] { mat.swap_rows(i, j); } } } mat } fn main() { let mat = swappy(); println!("Result: {}", mat); }To reproduce the issue, you must build in release mode. The issue is also sensitive to the amount of codegen units in flight, therefore I strongly recommend building with codegen-units=1 as well.
I expect the following output:
┌ ┐ │ 9 10 11 12 │ │ 5 6 7 8 │ │ 1 2 3 4 │ └ ┘ Instead, on my systems (nalgebra 0.16.2, rust 1.29, Ivy Bridge & Haswell CPUs) I get the following output:
┌ ┐ │ 9 10 11 12 │ │ 5 6 7 8 │ │ 1 6 7 4 │ └ ┘