Try a cheap bounded walk before the full occur checks
Why
Every variable link in unification runs occur, and the Tvar/Tconstr cases also run deep_occur. occur builds an AVL set of visited nodes along every path and deep_occur marks every node and walks the type again to unmark it, although almost all of these walks see a handful of nodes. On a 552 module React app they make 943k and 494k calls, about 0.5 s of 14 s single domain CPU.
Both checks now first walk the type with no visited set and no marks, giving up after 256 nodes (which also stops cycles and heavy sharing); when the walk gives up, the unchanged full walk runs. - occur in expression mode: a walk over the edges occur_rec follows that finishes without meeting the variable proves occur_rec would neither raise nor expand anything. Pattern mode, which looks types up, always runs the full walk. - deep_occur: the walk only answers "absent". It gives up on meeting the variable and on a node an enclosing walk already marked, so the marks left behind are the same as the full walk's.
Review
- Can an answer, a diagnostic or an artifact change? No: each fast walk either proves the full walk would do nothing more than it did, or gives up and the full walk runs from scratch. The new fixtures pin the errors, including one past the budget, and the corpus (5,398 artifacts and 1,147 .cmt/.cmti) is byte identical to master.