Which works by creating two named pipes and feeding them to diff and pumping your processes data into them. Process substitution is built on named pipes, they are the enabling mechanism that makes it work. Try this in a terminal:
echo <(true)
And you'll see the anonymous named pipe created by the subshell and passed to echo.