If for some magic reason thread::sleep_ms(1000) takes longer than 2000ms the main function would reach its end and deallocate the closure that is about to get called. Basically use after free.
And that's possible, because the sleep call is a suggestion, not a guarantee. If the CPU is blocked for 2s, then the order of waking the threads is undetermined, and the race will occur.
That is technically a race (sure) but at that point the program is getting killed anyway. Agree on the overall point though. I am a big fan of moving complete ownership / lifetime. It just makes things easier to reason about. In Chromium weak pointers are used to solve this use after free problem.