Faster compilation by trusting a 3rd party for type-checking information

One of the things I hate the most when programming is how much resources are wasted doing the same thing that has been done already thousands of times. We all know that if you do cargo check for tokio v1 with features = ["full"], there will be no errors, but the compiler has no way to know that so it has to repeat the process yet again for the millionth time.

I've been thinking of having a registry that you can ask if a crate with certain configuration type-checks:

Does tokio v1.0.0 with features = ["full"] for target x86_64-unknown-linux-gnu type-checks?

Yes.

Ok. Skipping local type-checking for tokio.

or

I don't know. Let me type-check it for the next person.

Ok. Type-checking tokio locally.

We already have something that does something like this: docs.rs. So this is not too crazy.

This is a lightweight alternative to hosting pre-compiled crates for every possible combination of features of a crate.

I'm not sure what should be taken into account so that we can trust that the same program type-checks correctly in any N environments (should we exclude crates with build.rs?, crates that use include! or any other proc-macro?, etc) I'm not even sure if this is a good idea...

The issue is that it's not just a matter of "skipping tyck." Basically all of the parts of cargo check that take any time are prerequisites to compilation. So even if you know ahead of time that all of the types line up, you still have to do type inference and method lookup and trait resolution and all of the interesting parts anyway in order to compile the crate.

If you want to skip work, what you need is pretty much exactly the incremental compilation cache. And that's deliberately unstable between compiler versions so that the compiler can evolve.


Rather than the full incremental cache you could hold the elaborated MIR for the cfg set, but this is still something that undergoes significant changes between compiler versions.

4 Likes

I see now. Thanks and sorry, I didn't mean to undermine the effort that something like this would take.

I was thinking something along the lines of

// crate A
struct Foo<T: Bounds>(T);
// crate B
fn bar() {
  let n = age(); // inferred to be i32 by the type-checker
  let foo = Foo(n); // assume it's well-formed, don't type check
}

but now I see that that's too naive as most typing information is not available before type-checking.