I recommend everyone to spend 50 minutes watching this talk: https://www.youtube.com/watch?v=Gdx6by6tcvw.
It describes the Stripe's type checker for ruby. In particular, it describes the ideal incremental compiler pipeline:
It's very instructive to reflect on how this is different from rust-analyzer's architecture.
There are two differences:
there's also a recent blogpost about it https://blog.nelhage.com/post/why-sorbet-is-fast/ (part of an ongoing series on Sorbet)