Hacker News new | ask | show | jobs
by direwolf20 138 days ago
This is one of those wicked language design problems that comes up again and again across languages, and they solve it in different ways.

In Haskell, you can't ever check that a type doesn't implement a type class.

In Golang, a type can only implement an interface if the implementation is defined in the same module as the type.

In C++, in typical C++ style, it's the wild west and the compiler doesn't put guard rails on, and does what you would expect it to do if you think about how the compiler works, which probably isn't what you want.

I don't know what Rust does.

1 comments

Rust's generics are entirely type-based, not syntax-based. They must declare all the traits (concepts) they need. The type system has restrictions that prevent violating ODR. It's very reliable, but some use-cases that would be basic in C++ (numeric code) can be tedious to define.

Generic code is stored in libraries as MIR, which is half way between AST and LLVM IR. It's still monomorphic and slow to optimize, but at least doesn't pay reparsing cost.

Rust gets around the shortcomings of its generics by providing an absurdly powerful macro engine.

It's a great idea when not abused too much for creating weird little DSLs that no one is able to read.

How does it handle an implementation of a trait being in scope in one compilation unit and out of scope in another? That's the wicked problem.
It’s impossible (?) due to the “coherence” rule. A type A can implement a trait B in two places: the crate where A is defined or the crate where B is defined. So if you can see A and B, you know definitely whether A implements B.

The actual rule is more complex due to generics:

https://github.com/rust-lang/rfcs/blob/master/text/2451-re-r...

and that document doesn’t actually seem to think that this particular property is critical.