

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?
If you want guaranteed safety then the borrowing rules are the most flexible as far as we know.
Just to give a couple of examples of how your idea might be flawed, what do you consider “basic types”? Are enums basic types? Then you’ve got an issue, because you might get a reference to the contents of an enum and then replace the enum with another variant, and suddently you’ve got a dangling reference. Would you prefer to prevent creating references to the contents of an enum? Then you’re more restricting than the borrowing rules.
Allowing iterable types but not iterating over mutable references is not enough for safety unfortunately. The basic example is getting a reference to an element of a
Vec
and then callingpush
on theVec
. This seems very innocent, butpush
ing on aVec
might reallocate its backing buffer, making the previous reference dangling. Again, would you prevent taking references to elements of aVec
? Then again you become much more restricting than the borrowing rules.That was just syntax sugar for
Rc
/Arc
, and you can still use them in today’s Rust, albeit with slightly worse ergonomics (no autoclone for example).