Run time, link time, per-crate compile time

Is we look at the static type vs dynamic type debate, it is often structured as "compile time" vs "run time" catching of errors. Here, "compile time" encompasses the entire build process.

If we look at the way Rust traits / impl / generics interact, would it be accurate to say the focus is:

(1) "conservatively eliminate potential link-time errors at per-crate compile time"
rather than
(2) "catch conflicts at link time"

If we look at things like: orphan rule, avoiding potential conflicting impls, etc ... it seems Rust is taking a very "strict/conservative" approach of "at per crate compile time, prevent POTENTIAL bad things at link time" ; whereas alternatively, in a different world, we could bed "more relaxed" at per-crate-compile-time, at the cost of potentially more conflicts at "link time" ?

Does this make sense? Or am I getting the fundamentals wrong here ?

1 Like

I think your description sounds accurate, matching my own interpretation.

Regarding orphan rule, besides avoiding link-time errors (which on its own serves a similar purpose as compile-time errors do over run-time errors: it helps make the errors more likely be seen earlier and by the right person that can fix it), orphan rules also play a role in Rust’s story of crates’ semantic versioning, making the addition of new trait implementations clearly not a breaking change in many cases.

3 Likes

Link time errors are bad because they're nobody's fault. In the imaginary world where conflicts are detected at link time, if a conflict arose between two popular crates in the Cargo ecosystem, it wouldn't be clear who should change their code to resolve it. The only way for any package to avoid causing such conflicts would be to adopt the orphan rule voluntarily. So I think it ends up just like the world we are in, but a little worse.

It would also become possible for new impls in the standard library to cause link-time conflicts with existing programs, and I don't see any way to resolve that.

(C++ has a still worse version of all this: the One Definition Rule. It's not enforced in the compiler. The linker can't enforce it, particularly around inline functions and templates, and different translation units that saw different definitions. If you break it, you get undefined behavior.)

EDIT - In hindsight, looks like i just repeated what @steffahn said, but opinionated :smiley:

2 Likes

Another possible concern is that Rust doesn't control the linker, so it's not possible to provide a really nice user experience, with detailed error messages, for linker errors. For that matter, the portable subset of linker features, across all the platforms Rust supports, might be rather limited.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.