This fixes a threading issue (T73593) between drivers that write to the same memory address. Driver nodes in the depsgraph now get relations to each other in order to ensure serialisation.
These relations are only added between drivers that target the same struct in RNA, which is determined by removing everything after the last period. For example, a driver with data path pose.bones["Arm_L"].rotation_euler[2] will be grouped with all other drivers on that datablock with a data path that starts with pose.bones["Arm_L"] to form a 'driver group'.
To find a suitable relation within such a driver group, say the relation (from → to), a depth-first search is performed to see whether this will create a cycle, and to see whether there already is such a connection (direct or transitive). This is done by recursively inspecting the incoming connections of the 'to' node and thereby moving it towards the 'from' node. This is an order of magnitde faster than inspecting the outgoing connections of the 'from' node.
This approach generalises the special case for array properties, so the code to support that special case has been removed from DepsgraphRelationBuilder::build_animdata_drivers().
A test on the Spring rig [1] shows that this process adds approximately 9% to the build time of the dependency graph (28 ms for this process on a total 329 ms construction time). I have experimented with a simple cache to keep track of known-connected (from, to) node pairs, but this did not significantly improve the timing.
[1] https://cloud.blender.org/p/spring/5d30a1076249366fa1939cf1
PS: Ignore the TIMEIT_START() and TIMEIT_END() calls and the corresponding #include, I'll remove those before committing to master.