Sync test without explicit Sync bound

What's a minimal:ish piece of code to require Sync (in this case on MyObject) without expressing it with an explicit bound?

Send is easy:

let mut obj = MyObject::new();
let handle = std::thread::spawn(|| {
  let id = obj.alloc();
  (obj, id)
});
let (mut obj, id) = handle.join().unwrap();
obj.release(id).unwrap();

With regards to Sync, the Nomicon phrases it sort-of like "We can safely assign this Sync because of the guarantees the borrow-checker provides":

What about Sync? For Carton to be Sync we have to enforce that you can't write to something stored in a &Carton while that same something could be read or written to from another &Carton . Since you need an &mut Carton to write to the pointer, and the borrow checker enforces that mutable references must be exclusive, there are no soundness issues making Carton sync either.

This to me makes it seem like Sync, as opposed to Send, doesn't unlock some feature, but is rather a way for the developer to slap a "Passed!" sticker on top of something they know fulfills the requirements of the borrow-checker.

But I'm wondering if there is something concrete that Sync "unlocks" that is easily demonstrated, in the same spirit that Send "unlocks" the ability demonstrated in the code snippet above.

(Purely for pedagogical reasons).

Sync is what unlocks Send for &T, i.e. you can only Send shared references to types that are Sync.

Is something like this what you want?

let value = Arc::new(Something::new());
let thread = thread::spawn({
    let value = value.clone();
    move || {
        value.access();
    }
});
value.access();
1 Like