2 ms·
I am not well versed in Rust so I can't judge the design decisions fairly but I do find that cpp2's in, out, inout, move and forward keywords for functions argu
by cassepipe 2y ago
I am not well versed in Rust so I can't judge the design decisions fairly but I do find that cpp2's in, out, inout, move and forward keywords for functions arguments much easier to follow mentally that rust's lifetime annotations :
https://youtu.be/6lurOCdaj0Y?feature=shared&t=3076 https://youtu.be/6lurOCdaj0Y?feature=shared&t=3076
We can do the same kind of (basic?) borrow checking with those can't we ?
- CryZe 2y agoNo, from a quick glance those are only for moves of individual values. Lifetimes are something different. They are used for relating multiple (> 1) parameters / return values with each other. There is no way to have that without having a syntax for it. It's important to note that lifetimes are not just for the compiler. They are also documentation / API contracts: fn add_to_vec<'a>(element: &'a str, vec: &mut Vec<&'a str>) { ... } This documents that the vec passed into the function can't outlive the element that's passed in. That's because the string (a reference (pointer) to the string data) that's passed in gets stored in the vec. So freeing the string and then using the vec would result in a use after free. You can't have this power without a syntax for it. You could of course do some global analysis, but now you can't have API contracts like this anymore, which are important for semantic versioning. An alternative syntax a language could use would be to have arbitrary pre- and post-conditions that the compiler can verify, which would be a whole lot more powerful, but also a lot more wordy than the short lifetime "tags" that Rust uses.
- kibwen 2y agoLifetimes in Rust are about giving you the ability to say "I have a reference, and I may not know exactly how long the underlying data may live for, but I do know that it will last for at least as long as this other thing". So for example: fn get_reference_to_first_element(x: &[u8]) -> &u8 { return &x[0] } There are lifetimes here that express that the reference that is returned from this function will live as long as the reference that was passed in. In cases like this where the association is obvious, the lifetimes are implied and you don't need to write them. The desugared form looks like this: fn get_reference_to_first_element<'a>(x: &'a [u8]) -> &'a u8 { return &x[0] } Lifetimes are present on structs for the same reason. A system that is limited to annotating only function input parameters would be limited to inferring the programmer's intent everywhere, which limits its utility to simple cases (which might be fine for some languages, but I suspect will not satisfy C++). In addition, from glancing briefly at that video, it seems as though those five keywords seem to be more concerned with ensuring use-after-initialization, whereas Rust's lifetime system is about preventing use-after-free.