Cow statics by default


This may be a crazy idea that will never work but, has anyone considered constructing Box, RawVec (Vec, String, etc…), etc. with pointers into the rodata section and copy (to the heap) on write? Would the extra check (does the pointer point to RO data) in mutating functions add too much overhead.

In response to:

/cc @llogiq


I’d prefer to make such stuff explicit. It’s hard enough to reason about performance without such optimizations; and there may be the stray case where the additional check actually leads to a pessimization.

If you’d like it, a source-to-source converter (perhaps as a macro plugin that would work a module at a time) might work without too much effort, though. But first, I’d like to construct a lint, because that’d give me the experience to determine if automated analysis is good enough to rely on for code transformation.


For String, I don’t think this would be a problem because strings aren’t usually mutably dereferenced (this feature wasn’t even introduced until recently) and pushing onto a string always requires bounds checking. Vec and Box, however, may be problematic.

Alternatively, we could wait for static allocation and more powerful CTFE (AFAIK, this is needed for static Mutexs anyways). This isn’t quite as memory efficient but it avoids runtime allocation.


Long-term, this could be a MIR optimization pass (perhaps even with a compiler plugin); however, it would either need to perform cross crate, or leave the Stringy versions of the API intact.


Just a heads-up. I’m making some progress. I’ve got a lint that is Visitor and ExprUseVisitor (the former is used to collect all data before reporting, also to mark public API items as off-limits (for now; I may change this to just set a flag and report under a different lint, e.g. for internal crates or other scenarios where you have no qualms about changing the publicly visible API).