error[E0716]: temporary value dropped while borrowed
--> libk\src\nvme\mod.rs:688:38
|
688 | register_interrupt_handler(int, &move |_| {
| _____________________________________-^
| |_____________________________________|
| ||
689 | || for (i, (qid, queue)) in QUEUES.lock().iter().enumerate() {
690 | || if *qid == id {
691 | || queue.enqueue(true).unwrap_or_else(|_| warn!("Queue {} lost interrupt", i));
692 | || }
693 | || }
694 | || });
| || ^ - temporary value is freed at the end of this statement
| ||_____|
| |______creates a temporary which is freed while still in use
| cast requires that borrow lasts for `'static`
Now, the interesting thing to note is that QUEUES is a static declared using lazy_static. I've tried this same thing with iterators and it gives me the same message. I've tried it with and without move and no go either, and I'm really confused on what's creating the supposed 'temporary value'. I've tried cloning/copying those that are outside the loop (except for QUEUES because that's static) and it still complains. If its the iterators, I don't really understand why that's so much of an issue, because I'd be going from an iterator to a Filter to a for_each and then the iterator is fully consumed -- is that not right?
I've even tried doing what the explanation says and creating a temporary variable for the mutex guard, everything that's outside the closure... It still doesn't like it. So I'm not sure what to try now. The code is:
let id = dev.unique_dev_id;
let int = dev.int_line.clone();
register_interrupt_handler(int, &move |_| {
for (i, (qid, queue)) in QUEUES.lock().iter().enumerate() {
if *qid == id {
queue.enqueue(true).unwrap_or_else(|_| warn!("Queue {} lost interrupt", i));
}
}
});
What's its function header? The error message suggests something like &'static dyn Fn(…), which sounds interesting, to say the least. In that case, you'd have to box and leak the closure
Box::leak(Box::new(move |_| …)
before passing it as an argument.
Also, is that the full error message? There are usually help and note messages below the error hinting at what to do.
So that's why I was taking a reference to it. Since I'm loading these functions into a static list of them, would it be better to pin them to ensure the compiler doesn't move them around? Something like:
Edit: Okay, so it doesn't like that, apparently. I have a function for unregistering handlers when a driver is ready to be shut down:
pub fn unregister_interrupt_handler(int: u8, id: usize) -> bool {
x86_64::instructions::interrupts::disable();
debug!("Unregistering handler for int. {:X} (id {:X})", int, id);
let mut tbl = IRQ_FUNCS.write();
let irq = 32_u8.saturating_add(int);
if let Some(funcs) = tbl.get_mut(&irq) {
if funcs.len() >= id {
let _ = funcs.remove(id);
} else {
x86_64::instructions::interrupts::enable();
return false;
}
}
x86_64::instructions::interrupts::enable();
true
}
I've tried that, and this:
pub fn unregister_interrupt_handler(int: u8, id: usize) -> bool {
x86_64::instructions::interrupts::disable();
debug!("Unregistering handler for int. {:X} (id {:X})", int, id);
let mut tbl = IRQ_FUNCS.write();
let irq = 32_u8.saturating_add(int);
if let Some(funcs) = tbl.get_mut(&irq) {
if funcs.len() >= id {
let b = funcs.remove(id);
drop(b);
} else {
x86_64::instructions::interrupts::enable();
return false;
}
}
x86_64::instructions::interrupts::enable();
true
}
It really hates both of these, I think. I don't know because its not syntactically or semantically incorrect, but it did this after it complained that I needed to use the result of Box<T>.
Fixed the problem. My target triplet file contained +sse in my features list, and apparently the compiler_builtins crate doesn't like that. (Or something doesn't.)