I'm trying to start learning code in the solve
crate. It's super cool, but also daunting. For motivation I'm working on improving optional record fields, I made this issue for one of the error cases I'm seeing https://github.com/roc-lang/roc/issues/6101.
What's the best way to start debugging this code? Ideally I'd like to step through type unification as it's happening, but any kind of advice on pretty printing, places to start in the code, etc, would be great.
This is prob an @Ayaz Hafiz question, but I figured I'd ask in a public channel. I know you built some tooling around debugging lambda sets, but I haven't looked into how that works. Would it make sense to build a similar tool for more general type system debugging?
There's a few things I do in these cases. The first step is to cut down as small a reproduction as possible.
Then, I create a "uitest" (see for example https://github.com/roc-lang/roc/blob/a6cde11bf4183713e15198477e581b114299f709/crates/compiler/uitest/tests/solve/infer_contextual_crash.txt#L1-L6). If you annotate expressions with ^
underneath them, cargo uitest <file>.txt
will print the solved types next to the annotations. This is pretty useful to check if things look right; usually, this is enough to see the problem. You can do fancier stuff like get the specialization types.
You can trace the path unification takes by setting ROC_PRINT_UNIFICATIONS=1
. I commonly do ROC_PRINT_UNIFICATIONS=1 cargo uitest <mytest>.txt
. This is a pretty good tool and is usually the next best step.
Finally, if you need it, you can dump a unification trace by setting ROC_CHECKMATE=1
before running a uitest/compiler build. You can then load the dumped trace into https://ayazhafiz.com/checkmate/ and inspect the unification over time, and compare types at two instances in time. This is basically ROC_PRINT_UNIFICATIONS=1 on steroids. It's missing some features and has some holes, but if ROC_PRINT_UNIFICATIONS isn't enough this probably will be.
As far as understanding the actual unification algorithms, it's basically a "standard" unification algorithm for an HM system with first-order parametric polymorphism. I'm happy to elaborate in more detail on specific things if it's useful. By far the best succinct but in-depth overview of this is, in my opinion, section 4.4.4 in Mimram's Proof = Program, which is available online at https://www.lix.polytechnique.fr/Labo/Samuel.Mimram/teaching/INF551/course.pdf
Last updated: Jul 06 2025 at 12:14 UTC