> To summarize, enforcing [Rust's] borrowing rule in C++ is unfortunately not so simple because there is a lot of existing code that creates multiple non-const pointers or references to the same object, intentionally violating the borrowing rule. At this point we don’t have a plan of how we could incrementally roll out the borrowing rule to existing C++ code, but it is a very interesting direction for future work.<p>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:<p>* Annotate those parameters as "immutable" or as coming from the same immutable "region". Anything reached through them would also have that immutable annotation.<p>* Anything created during the call would not have that annotation.<p>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.<p>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.<p>[0]: <a href="https://verdagon.dev/blog/seamless-fearless-structured-concurrency" rel="nofollow">https://verdagon.dev/blog/seamless-fearless-structured-concu...</a>
This reminds me of the -Wlifetime proposal, which provides similar checks but requires annotation of ownership at struct level (hence the check only applies to new structs):<p>An example: <a href="https://github.com/llvm/llvm-project/blob/main/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp" rel="nofollow">https://github.com/llvm/llvm-project/blob/main/clang/test/Se...</a><p>More details can be found at <a href="https://herbsutter.com/2018/09/20/lifetime-profile-v1-0-posted/" rel="nofollow">https://herbsutter.com/2018/09/20/lifetime-profile-v1-0-post...</a><p>Unfortunately it was never upstreamed according to <a href="https://github.com/mgehre/llvm-project/issues/98" rel="nofollow">https://github.com/mgehre/llvm-project/issues/98</a>
I tend to think that the ROI for large legacy codebases is in static analysis and instrumented tooling like the sanitizers.<p>I’m grudgingly coming around to the idea that Rust is probably a rock-solid FFI story away from being a serious part of my kit (pybind11 good, not like anything we have now).<p>But there is this in-between place where first-class linear/affine typing could be bootstrapped off of move semantics.
Looks like at least some of the authors are working for Google (if not everyone), with compiler backgrounds. I wonder if this is a strategical investment from Google to make cxx like approach more robust? Chrome team showed some interests on using Rust but not sure if there's any significant code written in Rust from then. Benefit from using Rust beside well isolated library might be quite limited without this kind of lifetime annotation while interop itself is additional cognitive overheads for programmers.
From <a href="https://discourse.llvm.org/t/rfc-lifetime-annotations-for-c/61377" rel="nofollow">https://discourse.llvm.org/t/rfc-lifetime-annotations-for-c/...</a> :<p>> <i>We are designing, implementing, and evaluating an attribute-based annotation scheme for C++ that describes object lifetime contracts. It allows relatively cheap, scalable, local static analysis to find many common cases of heap-use-after-free and stack-use-after-return bugs. It allows other static analysis algorithms to be less conservative in their modeling of the C++ object graph and potential mutations done to it. Lifetime annotations also enable better C++/Rust and C++/Swift interoperability.</i><p>> <i>This annotation scheme is inspired by Rust lifetimes, but it is adapted to C++ so that it can be incrementally rolled out to existing C++ codebases. Furthermore, the annotations can be automatically added to an existing codebase by a tool that infers the annotations based on the current behavior of each function’s implementation.</i><p>> <i>Clang has existing features for detecting lifetime bugs</i> [...]
I think this is a good idea, mostly because I've been of the opinion that much of the rust "safety" could be done with a linter pass in C++. These annotations should help solve the edge cases that aren't deterministic.<p>I've not generally been a big fan of where C++ has been going in the last couple revisions, mostly because it seems the newer features aren't fully thought out when it comes to how they interact with other features (reminds me of javascript in that regard) leaving a bunch of new footguns, looks at lambda's.<p>I think i've said this here before, that C++ needs its own version of "use strict;" that basically kills off some of the syntactically odd corner cases that lead to those footguns.
Sounds awesome. After the initial hurdle of getting used to lifetimes in rust it was really an enjoyable time and I would love to see the same feature in c++.
Maybe a C++ person can help me out, I am staring at this C++ translation of Rust's elision rules:<p>> If there are multiple input lifetimes but one of them applies to the implicit this parameter, that lifetime is assigned to all elided output lifetimes.<p>In Rust we have <i>self</i> rather than <i>this</i> in methods, but importantly we sometimes don't take a reference here, and that's <i>still</i> a method, and you still have the <i>self</i> parameter, but the lifetime elision rules don't apply. They don't apply because if you've actually got self, not some reference to self, the lifetime of self is going to end when the function finishes, so returning things with that lifetime is nonsense.<p>This can make sense in Rust for transformative methods. If there's a method on a God that turns them into a Mortal, the God doesn't exist any more when that method exits, the Mortal is the return type, and if you just drop it then I guess sucks to be them. (In Rust, and I think in C++ you can label something as must-use and cause a warning or error if the programmer forgets to use it).<p>It seems though, as if this C++ rule would hit such methods too. Can you distinguish in C++ between "a reference to me" and "me" when it comes to methods? If you had a method on a God class in C++ that transforms the God into a Mortal and returns the Mortal, what does that look like? Does this elision rule make sense to you for such a scenario?
10 years from now, there will be nobody on earth able to say "i know c++" because each codebase will use a completely different set of bazillion optional features making each codebase look like an entirely different language from each other.<p>but maybe thats how we'll finally get rid of c++.
What happens if you make an annotation mistake? Could the compiler generated code then have a security vulnerability, just like when you use undefined behaviour and the compiler is then allowed to optimize safety checks away?
It's a bad sign that I can't tell if someone spent a lot of time on an elaborate April's Fool joke or if it's a serious C++ proposal.