On Wed, 13 Sept 2023 at 16:20, Nikl Kelbon via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
Postcondition of std::lock and std::try_lock:

All of Mutexes... are locked, no deadlock occurs.

Effects: All arguments are locked via a sequence of calls to lock()try_lock(), or unlock() on each argument.
 
The sequence of calls does not result in deadlock, but is otherwise unspecified.


But in an common case, when there is a type with a mutex and you need to swap it

void swap(Type& other) {
  std::scoped_lock l(this->mutex, other.mutex);
  // ... do swap ...
}

If addressof(other) == this same mutex will be locked, and there are no precondition which blocks this usage.
But in fact its undefined behavior (implementation uses try_lock on already locked mutex) (deadlock on msvc-stl, just ub on others)

There are several solutions to this, either we explicitly add precondition, or the implementation must handle this (then there could potentially be an overhead when unlocking)

Or we do nothing. The precondition already exists, whether we add it explicitly or not.

This case is the same as std::lock(m, m) which is undefined already.

Being more explicit might not hurt though.