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)