Yeah, I'm a bit worried that Rust is raising the floor, but maybe lowering/hardening the ceiling when it comes to code safety. I mean, if you consider static (compile-time) versus dynamic (run-time) safety, Rust leans heavily toward the former, and presumably gains a performance benefit because of it. But Rust acknowledges that it is not practical to achieve memory safety completely statically and so provides dynamically checked data types as well (vectors, RefCell, etc.).
As you consider higher (application) level notions of safety, it generally becomes less practical to achieve that safety statically (at compile-time), so you'd want your language or your framework or whatever to facilitate the implementation and performance optimization of dynamic (run-time) safety. At the moment I'm thinking about automatic injection of run-time asserts (of application level invariants) at appropriate places in the code. (At the start and maybe at the end of public member functions for example.)
If you subscribe to this idea, then it sort of follows that Rust's borrow checker may be "in the wrong place". That is, rather than forcing you to write code that is memory safe in a particular statically verifiable way, Rust could have instead enforced memory safety by injecting run-time checks into the code and optimizing them out when it recognizes code that appeases the borrow checker. (Of course the optimizer could report what run-time checks it was not able to optimize out, if you wanted to self-impose static verification.)
(Statically optimized) dynamic safety is more scalable than statically verified safety. As a "systems language", Rust may be less concerned with higher/application level safety. But I think this might be a little short-sighted. The definition of "system" is expanding, and the proportion of "higher level" safety concerns along with it.
> If you subscribe to this idea, then it sort of follows that Rust's borrow checker may be "in the wrong place". That is, rather than forcing you to write code that is memory safe in a particular statically verifiable way, Rust could have instead enforced memory safety by injecting run-time checks into the code and optimizing them out when it recognizes code that appeases the borrow checker.
That kind of lack of transparency about what in the hell your code is doing at runtime is really inappropriate in a system's language.
It's an interesting idea, and it would be neat to play with in a language that wanted to restrict itself to more business-logic level safety concerns, but it would absolutely come at the cost of not being appropriate for systems-level tasks.
Hmm. Is it less transparent than vectors which use implicit run-time bounds-checks? Don't RefCells use implicit run-time checks? (Btw I don't know Rust very well, so feel free to correct me.) And what about the question mark operator for dealing with exceptions/errors? Isn't there a lot going on under the hood there?
But yeah, I can understand the sentiment of wanting to minimize that kind of thing in a lot of cases. Perhaps, like C and C++, Rust might consider bifurcating into a "high transparency" language, and a "high productivity" superset of the language. In that case, would all of the existing Rust language make it into the "high transparency" subset?
Like I said, the problem is that no one's defining what a "system" is. Haven't they written a browser rendering engine in Rust? Is that a "system"? Is there any part of the browser that does not qualify as a system?
RefCell does use run-time checks; that's it's entire reason for existing. They're "implicit" in the sense that they're inside of the functions, but that's the job of calling the function, so.
Question mark is roughly six lines of code, it's a match statement on Result, which has two cases.
So do you agree that Rust should remain a "high transparency" language? Do you have an opinion on a "high productivity"/"application level safety supporting" superset of the language? Rust seems to be creeping out of the system space and into the application space. Will/should Rust go out of its way to support application level programming? (By, among other things, facilitating enforcement of application level invariants?)
To me, this is a library concern. Rust the language should remain high transparency, but that doesn't mean that programming in it should force you to always deal with every single thing if you don't want to. Look at the recent addition of ?, for example: you can get very succinct code if you don't want to deal with the particulars, but you still have access if you want to. I think good Rust libraries will end up like that.
As you consider higher (application) level notions of safety, it generally becomes less practical to achieve that safety statically (at compile-time), so you'd want your language or your framework or whatever to facilitate the implementation and performance optimization of dynamic (run-time) safety. At the moment I'm thinking about automatic injection of run-time asserts (of application level invariants) at appropriate places in the code. (At the start and maybe at the end of public member functions for example.)
If you subscribe to this idea, then it sort of follows that Rust's borrow checker may be "in the wrong place". That is, rather than forcing you to write code that is memory safe in a particular statically verifiable way, Rust could have instead enforced memory safety by injecting run-time checks into the code and optimizing them out when it recognizes code that appeases the borrow checker. (Of course the optimizer could report what run-time checks it was not able to optimize out, if you wanted to self-impose static verification.)
(Statically optimized) dynamic safety is more scalable than statically verified safety. As a "systems language", Rust may be less concerned with higher/application level safety. But I think this might be a little short-sighted. The definition of "system" is expanding, and the proportion of "higher level" safety concerns along with it.