Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upMutexGuard<Cell<i32>> must not be Sync #41622
Comments
RalfJung
changed the title from
MutexGuard<Cell<i32>> must not be sync
to
MutexGuard<Cell<i32>> must not be Sync
Apr 29, 2017
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
RalfJung
Apr 29, 2017
Member
Btw, this bug was found while trying to prove soundnes of (an idealized version of) Mutex. Yay for formal methods :D
Also, this hints at a more general problem: OIBITS for types with custom invariants ("unsafe types") are dangerous.
|
Btw, this bug was found while trying to prove soundnes of (an idealized version of) Also, this hints at a more general problem: OIBITS for types with custom invariants ("unsafe types") are dangerous. |
This was referenced Apr 29, 2017
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
RalfJung
Apr 29, 2017
Member
Also, this hints at a more general problem: OIBITS for types with custom invariants ("unsafe types") are dangerous.
To elaborate on this (from a formal proof perspective): To prove correctness of Send/Sync for an unsafe type (i.e., a type with its own invariant), I need to know exactly under which bounds the type is Send/Sync -- this defines the theorem I have to prove. However, if the type does not have an explicit impl for Send/Sync, I don't know how to even figure this out -- I would have to chase all types (including safe ones, and across all abstractions) of all fields recursively and then check when they are Send/Sync... that's way too error-prone. What I do instead is I try to compile small programs that only work e.g. if T: Send implies MutexGuard<T>: Sync. However, I may easily miss impls this way -- maybe we need T: Send+'static to get MutexGuard<T>: Sync? It is impossible to cover all possible constraints.
Also, even if there is an impl, there are still some subtleties: First of all, does giving a restrictive positive impl disable the more liberal automatic impl? (Tests indicate yes.) What if there is a restrictve negative impl? If I find impl<T: 'static> !Sync for MutexGuard<T>, does the automatic impl still apply for types that do not satisfy T:'static? (I haven't yet seen such a restrictive negative impl, so I don't know -- but this can happen accidentally with ?Sized if the type has T: ?Sized but the negative impl just has T.)
To elaborate on this (from a formal proof perspective): To prove correctness of Send/Sync for an unsafe type (i.e., a type with its own invariant), I need to know exactly under which bounds the type is Send/Sync -- this defines the theorem I have to prove. However, if the type does not have an explicit impl for Send/Sync, I don't know how to even figure this out -- I would have to chase all types (including safe ones, and across all abstractions) of all fields recursively and then check when they are Send/Sync... that's way too error-prone. What I do instead is I try to compile small programs that only work e.g. if Also, even if there is an impl, there are still some subtleties: First of all, does giving a restrictive positive impl disable the more liberal automatic impl? (Tests indicate yes.) What if there is a restrictve negative impl? If I find |
RalfJung commentedApr 29, 2017
•
edited
Edited 1 time
-
RalfJung
edited Apr 29, 2017 (most recent)
Right now,
MutexGuard<Cell<i32>>satisfies theSyncbound. That is rather bad, because it lets me write a program that has a data race:The
getandsetcalls in the two threads are unsynchronized (as usual for aCell), and they are racing. This is a soundness bug.The cause for this is that
MutexGuard<T>implementsSyncwheneverTimplementsSend, which is plain wrong. The fix is to letMutexGuard<T>implementSyncwheneverTimplementsSync. I will submit a PR soon.