Threads and queues are different things. When you enqueue a block on a queue, Dispatch arranges to have a thread run it at some point.
So, difference between queue.sync and DisptachQueue.main.sync in my case is that when using queue.sync, Dispatch sees that some work needs to be executed on a serial queue and wants to be executed synchronously, it knows that now we are on the main thread and that thread is not going to be doing anything useful which waiting for that block to complete, so it schedules this work on main thread after all existed work on this thread is complete. And because of that - there is no deadlock.
On the other hands, when use DisptachQueue.main.sync directly, Dispatch do not wait work to complete on main thread and try to add this block to execute right now - and this cause a deadlock.
How far my conclusions from truth?