5 ms·
> But its stalwarts are hostile to measures to make it easier for people to pick up, even easy ones that do not alter the language at all. (E.g., allowing a deb
by aw1621107 4y ago
> But its stalwarts are hostile to measures to make it easier for people to pick up, even easy ones that do not alter the language at all. (E.g., allowing a debug build to complete despite borrow complaints.)
That seems like a rather unusual suggestion to me. Are there commonly used languages/situations where optimization level changes semantics/allowed constructs? The only thing I can think of off the top of my head is stuff that relies on tail calls be optimized in languages that don't guarantee tail call optimizations, but I think that's a relatively niche case compared to debug vs. release builds.
I also feel that that suggestion could arguably make the language harder to pick up, since something that worked in debug mode might require extensive refactoring for release mode. Given how much Rust relies on the optimizer to see through its abstractions, that seems problematic.
In addition, I suspect (but don't know for sure) that writing code that works correctly in both modes can be tricky - think of something that uses multiple threads, where "release-mode code" can rely on the lack of mutable aliasing but "debug-mode code" cannot. Either you maintain two versions of the code or you write code that doesn't rely on the borrow checker guarantees, which seems like it would defeat the purpose of having the borrow checker in the first place. This is a gut feeling, though, so I wouldn't be surprised if there were a way around this.
Finally, I'm not sure I agree with the notion that this change "[does] not alter the language at all." It's like the concept of "allowing a debug build to complete despite [type] complaints" in C++. You're going to have to change the language somehow to define the semantics of ignoring type errors, and I'm not sure how this will help newcomers or how easy such a change would be to implement.
Out of curiosity, what other measures did you have in mind? Or can you point me somewhere which discusses similar measures?
- ncmncm 4y agoAll compilers allow builds that trigger warnings to complete. Obviously code that only runs when built "debug" differs from released code, which ... doesn't run. That is the whole point. Before you ship, you will resolve all the borrow nags, and then there will be a release build, and it will run the same. In the meantime, you probably have more urgent worries to act on first. The only difference is who decides when, you or the compiler. As is, the compiler decides, period. (I confess it utterly mystifies me how this is such a difficult concept for so many. Inability to comprehend something so simple bodes ill for judgment on more weighty matters.)
- aw1621107 4y ago> All compilers allow builds that trigger warnings to complete. That is true, but I don't see how it's relevant. Violations of the borrowing rules in Rust are like type errors in C++ or C. Warnings are simply not part of the picture. > Obviously code that only runs when built "debug" differs from released code, which ... doesn't run. I honestly don't know what this wording is intended to convey. The text before the edit made more sense. But in any case, I don't really see the relevance. I asked about situations where the presence/absence of optimizations changes language semantics. As far as I know, programmers generally expect that the same code will exhibit the same observable behavior regardless of whether it was built in debug or release mode (i.e., the as-if rule, barring UB/IB/etc., of course). What you're suggesting appears to violate that - something that builds in debug mode may not compile at all in release mode, let alone run the same. How is that better for newcomers? > Before you ship, you will resolve all the borrow nags, and then there will be a release build, and it will run the same. This feels like it's doing a lot of hand-waving. By way of analogy: "Before you ship, you resolve all the type nags, and then there will be a release build, and it will run the same" If you started with a program where everything is a void*, "resolve all the type nags" is potentially a huge amount of work. There's absolutely no guarantee that you will only need to make "minor" changes to get your program working in release mode. Maybe what you wrote is good enough, maybe you need to completely restructure your program. That certainly does not sound very newcomer-friendly to me. > In the meantime, you probably have more urgent worries to act on first. The only difference is who decides when, you or the compiler. As is, the compiler decides, period. Couldn't this argument be extended to other aspects of a program that can be statically checked? Why stop at the borrow checker?
- ncmncm 4y agoYou demonstrate that anybody can fail to comprehend anything, howsoever simple, if they dedicate enough effort. What such failure indicates is obscure. (Is it really so hard to understand how a program that exists and can be executed differs from the entire lack of any such program?) It does suggest that the prospect of Rust ever being made more accessible to new users is slim to none, as, thus, is displacing C enough to move any needle, more's the pity. We will need to rely on people graduating to use of modern C++, instead.
- dllthomas 4y agoIt's a little tricky, I think, because lifetimes are a part of the type of things and can determine behavior. But you could possibly do like GHC does with "defer type errors" and panic if you encounter a situation where that might matter (including before an illegal borrow or whatnot). It doesn't really help you solve the bit that was unchecked, but if you're trying to iterate around something earlier in the code it might be useful sometimes to be able to focus on the bit you're working on and put off cleaning up stuff you're not wanting to execute yet anyway.
- aw1621107 4y ago> But you could possibly do like GHC does with "defer type errors" and panic if you encounter a situation where that might matter (including before an illegal borrow or whatnot). I honestly didn't know that capability existed. Just to make sure I'm reading the right thing, is it the technique described in Equality proofs and deferred type errors: A compiler pearl [0]? I have no training in programming language theory, so I can't give a good evaluation on how applicable this technique is to Rust. The first thing that jumps to mind is that I think it relies on Haskell's laziness to avoid evaluating the thunk (?) representing the type error if it isn't needed, but that's not to say that a different approach can't be found that doesn't require laziness (assuming I read the paper correctly). That being said, given Rust provides types which defer borrowing checks to runtime (Cell/RefCell [1]), I think it may be possible to implement something similar to -fdefer-type-errors by e.g., wrapping all references in a Cell/RefCell and inserting appropriate function calls. I would guess the main concern there is fragmenting the Rust ecosystem into code that requires a hypothetical -fdefer-borrowck-errors flag and code that works with "standard" Rust, and tying that to optimization level has its own issues. It's admittedly a bit different than what I had in mind when I first responded to ncmncm's comment (where I interpreted it as "pretend the borrowck errors didn't exist," as opposed to "use runtime checks as appropriate"), but it does make more sense. Thanks for showing me something new! [0]: https://www.microsoft.com/en-us/research/uploads/prod/2020/02/deferred-icfp12.pdf https://www.microsoft.com/en-us/research/uploads/prod/2020/0... [1]: https://doc.rust-lang.org/std/cell/ https://doc.rust-lang.org/std/cell/
- staticassertion 4y ago
- hoseja 4y agoThe MSVC implementation of STL has runtime checks in standard containers in debug builds.
- aw1621107 4y agoRight, but as far as I know those preserve language semantics and are stricter in debug mode than in release mode. The way I interpreted ncmncm's comment was that the suggested build-even-with-borrowck-errors was the opposite - different language semantics, and something that compiles in debug mode won't compile in release mode.