Every single inherent method on LocalKey takes &'static self as the receiver. My question is, why does it require the reference be 'static? I can't seem to find any explanation in the docs, or anywhere else. None of the methods hold on to the reference after they return, either. All they do is de-reference it to call its function pointer.
if val {
THREAD_LOCAL_1
} else {
THREAD_LOCAL_2
}.with(|_| /* etc */ );
For example, this code produces error[E0716]: temporary value dropped while borrowed.
It's trivial to get a 'static reference to a thread_local! static, so this isn't much of a problem; I'm just wondering why the bound was put there in the first place.
I don't know precisely why the API is designed as such, but you can work around this by just taking a reference to them -- the error you're encountering is because you're trying to move these thread locals, not take reference to them:
if val {
&THREAD_LOCAL_1
} else {
&THREAD_LOCAL_2
}.with(|_| /* etc */ );
Which should be fine since references to statics should be 'static to begin with.
I do know you can just take a reference to them. I wanted to know if there's a reason the API requires specifically a 'static reference.
Also, you can absolutely use a LocalKey by value. The thread_local! macro puts it in a const, not a static, so this code compiles without problem:
thread_local!{ static VAR: Vec<i32> = vec![1, 2, 3] }
fn main() {
let x = VAR;
let y = VAR;
}
Good point, a PR would probably be the best way to find out more info.
Though, I just tested it, and I think it's actually too late to change the API. It would break any code that relied on the bound for type inference.
About the comment you linked, I also came across it while looking into this, but I think I disagree with your guess. The current implementation of LocalKey doesn't own anything; It's basically just a fancy 'static reference already. (I also don't think that can be changed in the future without breakage either.)
pub struct LocalKey<T: 'static> {
// just a plain old function pointer
inner: fn(Option<&mut Option<T>>) -> *const T,
}
They wouldn't need the 'static bound on the method receiver even if they gave out Ref's, since it's just a function pointer. All that matters is that it lives long enough to be called, right?
Nonetheless, thanks for the advice, I at least now know why the API hasn't been changed since Rust 1.0.