This is actually possible for C++, if we add a concept of pure functions: functions that don't modify anything indirectly reachable from arguments (or globals). Basically:
* Annotate those parameters as "immutable" or as coming from the same immutable "region". Anything reached through them would also have that immutable annotation.
* Anything created during the call would not have that annotation.
The type system, basically a borrow checker, could keep them separate and make sure we don't modify anything that came from outside the function.
We're currently adding this to Vale [0], It's a way to blend shared mutability with borrow checking, and it gives us the optimization power and memory safety of borrow checking without all the constraints and learning curve problems.
[0]: https://verdagon.dev/blog/seamless-fearless-structured-concu...