thread_local-rs
thread_local-rs copied to clipboard
Remove T: Send as a trait bound on the struct and just rely on method bounds
I understand that T: Send is a requirement for ThreadLocal to function, but could the Send bound be removed from the struct definition and just retained for method impls.
This would greatly simply generic struct definitions, which nest structs containing a ThreadLocal. Currently the Send bound propagates, even to impls of structs containing thread locals that don't make use of the actual thread local or any of its methods.
Obviously where methods of the ThreadLocal are called then the trait bound is needed.
Use case: I have a struct A<T>, which is contained in struct B<T>, which is contained in struct C<T> etc. If I add a ThreadLocal to A (to count method invocations say or method invocation timing metrics), then B, C and so on, all need to declare T:Send. As do trait impls such as impl Display for C<T>, PAartialEq it seems.
Sure, that sounds fine! Would you like to submit a PR for this?
Trying to understand the model here.
ThreadLocal<T>: Sendif and only ifT: SendThreadLocal<T>: Syncif and only ifT: Send, which makes sense since it hands out&T, which is only Send if and only ifT: Sync.ThreadLocal::newandThreadLocal::with_capacitycan be called with anyT.ThreadLocal::{get, get_or, get_or_try, get_or_default}currently all requireT: Sendbut turn a&ThreadLocal<T>into a&Tor an Option.ThreadLocal's Drop impl is only sound if any of the following are true: a. TheThreadLocalis empty. b.T: Sendand thus it's safe to drop all instances stored in the ThreadLocal on another thread. c.T: !Sendand all of the instances ofTstored in the ThreadLocal are all constructed from the thread that is dropping theThreadLocal.- Rust only allows the
Dropimpl's generic params to match those of the struct definition.
A ThreadLocal constructed with a T: !Send is, itself, not Send and not Sync, and thus can only be constructed, live, be borrowed on, and dropped from a single thread without unsound unsafe elsewhere. Given points 1, 5a, and 5c, would it not be sound to replace the T: Send constraints on ThreadLocal::get and ThreadLocal::iter with T: Sync? ThreadLocal::iter_mut and the get_or* variants that create would still require T: Send since the items can be moved out of the returned &mut T, including in the Drop impl.
This would resolve the issues with #75 as well.