• 0 Posts
  • 2 Comments
Joined 2 years ago
cake
Cake day: July 1st, 2023

help-circle
  • Sure, but that doesn’t mean it can’t be better.

    It’s surely interesting though that people continuously complain about them and then praise a language whose equivalent feature is much more restrictive!

    Surely the compiler could delay optimizations until the entire project is built, no? Then it knows what implementations exist, and the developer could then decide how to deal with that

    It’s not really about optimizations but rather:

    • when checking some impls for overlap, the compiler assumes that impls that the orphan rules block will never exist. You thus need to either disallow them (which would make the compiler more restrictive for non-application crates!) or a way to track them (which is easier said than done since coherence and trait checking is very complex)

    • when generating code where specialization and/or vtables are involved. This could be delayed until the last crate is compiled, but at the expense of longer compile times and worse incremental compilation performance.

    Sure, and ideally those cases would be accounted for,

    AFAIK there’s nothing yet that can account for them without allocating everything on the heap.

    or at the very least the dev could annotate each use to turn the borrow checker off for each instance, and that could print something at build time and a linter could flag over it. Unsafe blocks aren’t feasible for everything here.

    You want some annotations to break out of the safe subset of the language but aren’t unsafe blocks basically that? Or perhaps you want something more ergonomic, at the expense of safety?


  • dreaded orphan rule

    Yeah, that always struck me as stupid.

    It is necessary to guarantee consistency in the trait system, otherwise it could lead to memory unsafety. Even relaxing it in cases where overlapping implementations could always be catched is still problematic because the compiler sometimes performs negative reasoning about traits that it know cannot be implemented downstream due to the the orphan rule.

    And if you think about it the orphan rule is not worse than what other languages allow. For example C# only allow implementing an interface when defining a type, while the orphan rule also allows you to implement a trait when defining the trait itself. Not to mention being able to implement a trait only when a generic parameter implements another trait.

    Yeah, the borrow checker is a bit too strict IMO. Ideally, the borrow checker would only trigger on things that could be run in parallel, such as with threads or async.

    You can still trivially violate memory safety without multithreading or concurrency. The article touches on this a bit (they mention e.g. iterator invalidation) but they fail to address all issues.

    https://manishearth.github.io/blog/2015/05/17/the-problem-with-shared-mutability/