LLVM assertion when creating a closure with `move` - rust

I have tried to create a mutable reference to clone from captured variable. But compiler said:
rustc: /home/rustbuild/src/rust-buildbot/slave/nightly-linux/build/src/llvm/lib/IR/Instructions.cpp:2522:
static llvm::CastInst* llvm::CastInst::CreatePointerCast(llvm::Value*, llvm::Type*, const llvm::Twine&, llvm::Instruction*):
Assertion `S->getType()->isPtrOrPtrVectorTy() && "Invalid cast"' failed.
What am I doing wrong?
fn foo(t: &mut int){
println!("{}", t);
}
fn main() {
let test = 10;
let h = move || {
let mut r = &mut test.clone();
foo(r);
};
h();
}

This is most likely a bug in the compiler which causes LLVM to crash (the assertion happens in LLVM code, not in Rust - otherwise there would be corresponding message and a possibility to get a backtrace). I've submitted a ticket here, you can subscribe to it to follow its progress.

Related

Rust 2021 vs. 2018: trait `std::marker::Send` is not implemented - what is the correct way to do this in 2021 edition?

I am currently following a course on Rust and have found that there is a bit that compiles with the 2018 edition of Rust but not the 2021 edition. While I could just change my edition and continue on, I'd like to understand further what would be correct way to proceed if I were using the 2021 edition and why the difference occurs?
The error that comes with the 2021 edition is:
let handle = std::thread::spawn(move || {
^^^^^^^^^^^^^^^^^^
*mut [T] cannot be sent between threads safely
threaded_fun(&mut *raw_s.0)
});
=help: ... the trait `Send` is not implemented for `*mut [T]`
The original code was working on multithreaded sort function, but I've tried to take out as much as I think I could so that it's just splitting out a vector and printing it's progress.
use std::fmt::Debug;
struct RawSend<T>(*mut [T]); // one element tuple
unsafe impl<T> Send for RawSend<T> {}
pub fn threaded_fun<T: 'static + PartialOrd + Debug + Send>(v: &mut [T]) {
if v.len() <= 1 {
return;
}
let p = v.len()/2;
println!("{:?}", v);
let (a, b) = v.split_at_mut(p);
let raw_a: *mut [T] = a as *mut [T];
let raw_s = RawSend(raw_a);
unsafe {
let handle = std::thread::spawn(move || {
threaded_fun(&mut *raw_s.0)
});
threaded_fun(&mut b[..]);
// unsafe is required because compiler doesn't know we combine these
handle.join().ok();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn threaded_test() {
let mut v = vec![1,2,3,4,5,6,7,8,9,10];
threaded_fun(&mut v);
panic!(); // Test is just to activate the function. `cargo test`
}
}
This is because Edition 2021 has partial captures in closures.
What this means is that in Rust 2018,
|| a.b
will capture "a" in its entirety, but in Rust 2021, it will only perform a partial capture of a.b, and if the structure has other fields those remain available to the creator of the closure.
In your case however, it means raw_s.0 is what's captured and used for the computation of the closure's traits, and since it's not Send (as it's a raw pointer) the closure is not Send anymore either. The change in traits computation was specifically noted in the editions changelog.
You can fix that by forcing a capture of the structure itself e.g.
let raw_s = raw_s;
or
let _ = &raw_s;
Note that cargo has a cargo fix subcommand which can migrate this sort of changes for you (using the --edition flag).
This is because edition 2021 changed how closures capture. In 2018, they capture entire structs, but in 2021, they will capture individual struct members.
This causes the closure to attempt to capture the raw pointer (raw_s.0) instead of the whole RawSend. You can work around this by explicitly forcing raw_s to move:
unsafe {
let handle = std::thread::spawn(move || {
let raw_s = raw_s;
threaded_fun(&mut *raw_s.0)
});
threaded_fun(&mut b[..]);
// unsafe is required because compiler doesn't know we combine these
handle.join().ok();
}

How to access mutable iterables inside a nested loop

Every now and then, I run into the same issue with borrowing (or not borrowing) mutable variables inside a loop, and I finally sat down and compiled a minimal example. As a result, the code is a little silly, but it is the shortest version that I could come up with that highlights the problem:
struct Association {
used: bool,
key: usize,
value: String,
}
impl Association {
fn new(key: usize, value: &str) -> Self {
Association{used: false, key: key, value: value.to_string()}
}
}
fn find_unused<'a>(data: &'a mut Vec<Association>) -> Option<&'a String> {
for k in 0.. {
for a in data {
if a.key == k && !a.used {
a.used = true;
return Some(&a.value);
}
}
}
None
}
fn main() {
let mut assoc = vec![
Association::new(7, "Hello"),
Association::new(9, "World")
];
println!("{}", find_unused(&mut assoc).unwrap());
println!("{}", find_unused(&mut assoc).unwrap());
}
This will fail with an error because data was moved before. If I borrow it instead, it will fail because it was borrowed before. I would like to understand exactly what is happening and how to solve it in general. In particular, I do not want to change the structure of the code, even if it is silly. I do not want to implement a workaround, because this is just a minimal example: Please assume that the nesting of the loops is the "right" way to do it, even if it is utterly silly here, which it definitely is.
I would only like to know how to communicate to the borrow checker that what is happening here is actually ok. I know of one way to do this:
fn find_unused<'a>(data: &'a mut Vec<Association>) -> Option<&'a String> {
for k in 0.. {
for j in 0..data.len() {
if data[j].key == k && !data[j].used {
data[j].used = true;
return Some(&data[j].value);
}
}
}
None
}
This compiles without error and works as intended. In my naïve understanding, there should be a way to express the above with iterators instead of indexing, and I would like to know how that would be done.
The behavior you want is possible if you:
make fresh mutable borrows in each nested loop
And wait for rustc to integrate more Polonius capabilities. (Can experiment now with cargo +nightly rustc -- -Z polonius). While you wait, you could use unsafe like in this post: Borrow checker complains about multiple borrowing, when only one will ever occur
Keeping the rest of your code the same and focussing on this part, but with the return commented out:
fn find_unused<'a>(data: &'a mut Vec<Association>) -> Option<&'a String> {
for k in 0.. {
for a in data { // Error - but rustc says what to do here
if a.key == k && !a.used {
a.used = true;
// return Some(&a.value);
}
}
}
None
}
The error messages from rustc say what to do and why. The mutable borrow in the parameters is moved (used up) by the call to into_iter() in for a in data.
rustc recommends a mutable re-borrow. This way we don't try to borrow something that has already been moved. Making that change (and keeping the return commented-out for now), the following now type-checks:
fn find_unused<'a>(data: &'a mut Vec<Association>) -> Option<&'a String> {
for k in 0.. {
for a in &mut *data { // we took rustc's suggestion
if a.key == k && !a.used {
a.used = true;
// return Some(&a.value);
}
}
}
None
}
If we un-comment the return, we get an error saying that the lifetime of the value we're returning doesn't match 'a.
But if we run with cargo +nightly rustc -- -Z polonius, the code type-checks.
#stargateur suggested trying polonius in a comment
Here's my guess as to why Polonius helps:
For the current rustc borrow-checker, lifetimes in function signatures are treated in a relatively coarse and simplistic way within the body of the function. I think what's happening here is that 'a is supposed to span the entire function body, but the fresh mutable borrow for a only spans part of the function body, so Rust doesn't unify them.
Polonius tracks origins of borrows in types. So it knows that the lifetime of &a.value comes from a, which comes from data, which has lifetime 'a, so Polonius knows the return is OK.
I'm basing this on The Polonius Talk but The Book is probably more up-to-date

How to return the captured variable from `FnMut` closure, which is a captor at the same time

I have a function, collect_n, that returns a Future that repeatedly polls a futures::sync::mpsc::Receiver and collects the results into a vector, and resolves with that vector. The problem is that it consumes the Receiver, so that Receiver can't be used again. I'm trying to write a version that takes ownership of the Receiver but then returns ownership back to the caller when the returned Future resolves.
Here's what I wrote:
/// Like collect_n but returns the mpsc::Receiver it consumes so it can be reused.
pub fn collect_n_reusable<T>(
mut rx: mpsc::Receiver<T>,
n: usize,
) -> impl Future<Item = (mpsc::Receiver<T>, Vec<T>), Error = ()> {
let mut events = Vec::new();
future::poll_fn(move || {
while events.len() < n {
let e = try_ready!(rx.poll()).unwrap();
events.push(e);
}
let ret = mem::replace(&mut events, Vec::new());
Ok(Async::Ready((rx, ret)))
})
}
This results in a compile error:
error[E0507]: cannot move out of `rx`, a captured variable in an `FnMut` closure
--> src/test_util.rs:200:26
|
189 | mut rx: mpsc::Receiver<T>,
| ------ captured outer variable
...
200 | Ok(Async::Ready((rx, ret)))
| ^^ move occurs because `rx` has type `futures::sync::mpsc::Receiver<T>`, which does not implement the `Copy` trait
How can I accomplish what I'm trying to do?
It is not possible unless your variable is shareable like Rc or Arc, since FnMut can be called multiple times it is possible that your closure needs to return the captured variable more than one. But after returning you lose the ownership of the variable so you cannot return it back, due to safety Rust doesn't let you do this.
According to your logic we know that once your Future is ready it will not need to be polled again, so we can create a solution without using smart pointer. Lets consider a container object like below, I've used Option:
use futures::sync::mpsc;
use futures::{Future, Async, try_ready};
use futures::stream::Stream;
use core::mem;
pub fn collect_n_reusable<T>(
mut rx: mpsc::Receiver<T>,
n: usize,
) -> impl Future<Item = (mpsc::Receiver<T>, Vec<T>), Error = ()> {
let mut events = Vec::new();
let mut rx = Some(rx); //wrapped with an Option
futures::future::poll_fn(move || {
while events.len() < n {
let e = try_ready!(rx.as_mut().unwrap().poll()).unwrap();//used over an Option
events.push(e);
}
let ret = mem::replace(&mut events, Vec::new());
//We took it from option and returned.
//Careful this will panic if the return line got execute more than once.
Ok(Async::Ready((rx.take().unwrap(), ret)))
})
.fuse()
}
Basically we captured the container not the receiver. So this made compiler happy. I used fuse() to make sure the closure will not be called again after returning Async::Ready, otherwise it would panic for further polls.
The other solution would be using std::mem::swap :
futures::future::poll_fn(move || {
while events.len() < n {
let e = try_ready!(rx.poll()).unwrap();
events.push(e);
}
let mut place_holder_receiver = futures::sync::mpsc::channel(0).1; //creating object with same type to swap with actual one.
let ret = mem::replace(&mut events, Vec::new());
mem::swap(&mut place_holder_receiver, &mut rx); //Swapping the actual receiver with the placeholder
Ok(Async::Ready((place_holder_receiver, ret))) //so we can return placeholder in here
})
.fuse()
Simply I've swapped actual receiver with the place_holder_receiver. Since placeholder is created in FnMut(Not captured) we can return it as many time as we want, so compiler is happy again. Thanks to fuse() this closure will not be called after successful return, otherwise it would return the Receivers with a dropped Sender.
See also:
https://docs.rs/futures/0.3.4/futures/future/trait.FutureExt.html#method.fuse

Vector holding mutable functions

I would like to have a vector with functions. Then I would like to iterate on this vector and execute functions one by one. The functions would mutate an external state. Additionally, I would like to be able to place the same function twice in the vector.
The problems I have are:
I cannot dereference and execute the function from the vector,
Adding the same function to the vector twice fails with, understandable, error that I cannot have two mutable references.
The closest I got is:
fn main() {
let mut c = 0;
{
let mut f = ||{c += 1};
let mut v: Vec<&mut FnMut()> = vec![];
v.push(&mut f);
// How to execute the stored function? The following complains about
// an immutable reference:
// assignment into an immutable reference
// (v[0])();
// How to store the same function twice? The following will fail with:
// cannot borrow `f` as mutable more than once at a time
// v.push(&mut f);
}
println!("c {}", c);
}
For the first problem, I don't really know why no mutable dereference happens here (in my opinion, it should), but there is a simple workaround: just do the dereference and then reference manually:
(&mut *v[0])();
Your second problem is more complex, though. There is no simple solution, because what you're trying to do violates Rust aliasing guarantees, and since you did not describe the purpose of it, I can't suggest alternatives properly. In general, however, you can overcome this error by switching to runtime borrow-checking with Cell/RefCell or Mutex (the latter is when you need concurrent access). With Cell (works nice for primitives):
use std::cell::Cell;
fn main() {
let c = Cell::new(0);
{
let f = || { c.set(c.get() + 1); };
let mut v: Vec<&Fn()> = vec![];
v.push(&f);
v.push(&f);
v[0]();
v[1]();
}
println!("c {}", c.get());
}
With RefCell (works nice for more complex types):
use std::cell::RefCell;
fn main() {
let c = RefCell::new(0);
{
let f = || { *c.borrow_mut() += 1; };
let mut v: Vec<&Fn()> = vec![];
v.push(&f);
v.push(&f);
v[0]();
v[1]();
}
println!("c {}", *c.borrow());
}
As you can see, now you have &Fn() instead of &mut FnMut(), which can be aliased freely, and whose captured environment may also contain aliased references (immutable, of course).

Discerning lifetimes understanding the move keyword

I've been playing around with AudioUnit via Rust and the Rust library coreaudio-rs. Their example seems to work well:
extern crate coreaudio;
use coreaudio::audio_unit::{AudioUnit, IOType};
use coreaudio::audio_unit::render_callback::{self, data};
use std::f32::consts::PI;
struct Iter {
value: f32,
}
impl Iterator for Iter {
type Item = [f32; 2];
fn next(&mut self) -> Option<[f32; 2]> {
self.value += 440.0 / 44_100.0;
let amp = (self.value * PI * 2.0).sin() as f32 * 0.15;
Some([amp, amp])
}
}
fn main() {
run().unwrap()
}
fn run() -> Result<(), coreaudio::Error> {
// 440hz sine wave generator.
let mut samples = Iter { value: 0.0 };
//let buf: Vec<[f32; 2]> = vec![[0.0, 0.0]];
//let mut samples = buf.iter();
// Construct an Output audio unit that delivers audio to the default output device.
let mut audio_unit = try!(AudioUnit::new(IOType::DefaultOutput));
// Q: What is this type?
let callback = move |args| {
let Args { num_frames, mut data, .. } = args;
for i in 0..num_frames {
let sample = samples.next().unwrap();
for (channel_idx, channel) in data.channels_mut().enumerate() {
channel[i] = sample[channel_idx];
}
}
Ok(())
};
type Args = render_callback::Args<data::NonInterleaved<f32>>;
try!(audio_unit.set_render_callback(callback));
try!(audio_unit.start());
std::thread::sleep(std::time::Duration::from_millis(30000));
Ok(())
}
However, changing it up a little bit to load via a buffer doesn't work as well:
extern crate coreaudio;
use coreaudio::audio_unit::{AudioUnit, IOType};
use coreaudio::audio_unit::render_callback::{self, data};
fn main() {
run().unwrap()
}
fn run() -> Result<(), coreaudio::Error> {
let buf: Vec<[f32; 2]> = vec![[0.0, 0.0]];
let mut samples = buf.iter();
// Construct an Output audio unit that delivers audio to the default output device.
let mut audio_unit = try!(AudioUnit::new(IOType::DefaultOutput));
// Q: What is this type?
let callback = move |args| {
let Args { num_frames, mut data, .. } = args;
for i in 0..num_frames {
let sample = samples.next().unwrap();
for (channel_idx, channel) in data.channels_mut().enumerate() {
channel[i] = sample[channel_idx];
}
}
Ok(())
};
type Args = render_callback::Args<data::NonInterleaved<f32>>;
try!(audio_unit.set_render_callback(callback));
try!(audio_unit.start());
std::thread::sleep(std::time::Duration::from_millis(30000));
Ok(())
}
It says, correctly so, that buf only lives until the end of run and does not live long enough for the audio unit—which makes sense, because "borrowed value must be valid for the static lifetime...".
In any case, that doesn't bother me; I can modify the iterator to load and read from the buffer just fine. However, it does raise some questions:
Why does the Iter { value: 0.0 } have the 'static lifetime?
If it doesn't have the 'static lifetime, why does it say the borrowed value must be valid for the 'static lifetime?
If it does have the 'static lifetime, why? It seems like it would be on the heap and closed on by callback.
I understand that the move keyword allows moving inside the closure, which doesn't help me understand why it interacts with lifetimes. Why can't it move the buffer? Do I have to move both the buffer and the iterator into the closure? How would I do that?
Over all this, how do I figure out the expected lifetime without trying to be a compiler myself? It doesn't seem like guessing and compiling is always a straightforward method to resolving these issues.
Why does the Iter { value: 0.0 } have the 'static lifetime?
It doesn't; only references have lifetimes.
why does it say the borrowed value must be valid for the 'static lifetime
how do I figure out the expected lifetime without trying to be a compiler myself
Read the documentation; it tells you the restriction:
fn set_render_callback<F, D>(&mut self, f: F) -> Result<(), Error>
where
F: FnMut(Args<D>) -> Result<(), ()> + 'static, // <====
D: Data
This restriction means that any references inside of F must live at least as long as the 'static lifetime. Having no references is also acceptable.
All type and lifetime restrictions are expressed at the function boundary — this is a hard rule of Rust.
I understand that the move keyword allows moving inside the closure, which doesn't help me understand why it interacts with lifetimes.
The only thing that the move keyword does is force every variable directly used in the closure to be moved into the closure. Otherwise, the compiler tries to be conservative and move in references/mutable references/values based on the usage inside the closure.
Why can't it move the buffer?
The variable buf is never used inside the closure.
Do I have to move both the buffer and the iterator into the closure? How would I do that?
By creating the iterator inside the closure. Now buf is used inside the closure and will be moved:
let callback = move |args| {
let mut samples = buf.iter();
// ...
}
It doesn't seem like guessing and compiling is always a straightforward method to resolving these issues.
Sometimes it is, and sometimes you have to think about why you believe the code to be correct and why the compiler states it isn't and come to an understanding.

Resources