Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Panic when dropping and replacing value through a mutable reference #431

Open
nilehmann opened this issue Apr 12, 2023 · 2 comments
Open
Labels
bug Something isn't working

Comments

@nilehmann
Copy link
Member

The following code panic when trying to update centers[i]

#[flux::sig(fn(&RVec<f32>[@n], usize) -> RVec<f32>[n])]
fn normal(x: &RVec<f32>, w: usize) -> RVec<f32> {
    let mut i = 0;
    let mut res = RVec::new();
    while i < x.len() {
        res.push(x[i] / (w as f32));
        i += 1;
    }
    res
}

#[flux::sig(fn (n: usize, centers: &mut RVec<RVec<f32>[n]>[@k], new_centers: RVec<(usize, (RVec<f32>, usize))>))]
fn update_centers(
    n: usize,
    centers: &mut RVec<RVec<f32>>,
    new_centers: RVec<(usize, (RVec<f32>, usize))>,
) {
    for (i, (x, size)) in new_centers {
        centers[i] = normal(&x, size)
    }
}

This is the panic

error: internal compiler error: flux-refineck/src/type_env.rs:169:17: cannot move out of `*_21`, which is behind a `&mut` reference
  --> /home/nlehmann/phd/flux-rs/flux/attic/playground.rs:24:9
   |
24 |         centers[i] = normal(&x, size)
   |         ^^^^^^^^^^
-Ztrack-diagnostics: created at /rustc/700938c0781c9f135244bb1ec846fe1a5e03ae7d/compiler/rustc_errors/src/lib.rs:995:33
@nilehmann nilehmann added the bug Something isn't working label Apr 12, 2023
@nilehmann nilehmann self-assigned this Apr 12, 2023
@nilehmann
Copy link
Member Author

Here's a minimal repro

fn test(vec: &mut RVec<RVec<i32>>) {
    vec[0] = RVec::new();
}

@nilehmann
Copy link
Member Author

nilehmann commented Apr 12, 2023

Here's the issue. Because RVec<T> is Drop, the line vec[0] = RVec::new() is "swapping" the old value with RVec::new() and dropping the old value. This used to happen as a single mir operation called DropAndReplace but now it desugars to more than one statement. Something like

1: _2 = vec.index_mut(0)
2: drop(*_2)
3: (*_2) = RVec::new()

Here _2 should have type &mut RVec<i32> but in between lines 2 and 3 , the reference momentarily points to uninitialized memory, so we are are "breaking" the invariant (i.e., it is a value of type RVec<i32>) after 2 and then reestablishing it in 3. This would be fundamentally addressed with folding/unfolding of mutable references, but in this particular case I think we could just ignore drop(*_2)

@nilehmann nilehmann removed their assignment Apr 12, 2023
@nilehmann nilehmann changed the title Panic when updating RVec<RVec<f32>> Panic when dropping and replacing value through a mutable reference Apr 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant