This can't possibly be guaranteed to work just by disabling the checker, can it? If Rust optimizes based on borrow-checker assumptions (which I understand it can and does) then wouldn't violating them be UB, unless you also mess with the compiler to disable those optimizations?
I guess this is like putting an unsafe { } around all your code...
Rust--: Rust without the borrow checker
231–240 of 269 posts
Re: Rust--: Rust without the borrow checker
#232Earlier quoted context omitted.
I’m sure some people could tiptoe through minefields daily for years, until they fail. Nobody is perfect at real or metaphorical minefields, and hubris is probably the only reason to scoff at people suggesting alternatives.
Just FYI rust projects have CVEs as well.
Re: Rust--: Rust without the borrow checker
#233Earlier quoted context omitted.
Sometimes, you just need to know if an idea will even work or what it would look like. If you have to refactor half the codebase (true story for me once), it makes the change a much harder sell without showing some benefits. IE, it keeps you from discovering better optimizations because you have to pay the costs upfront.
> Sometimes, you just need to know if an idea will even work or what it would look like. I think what GP is trying to say is that the value of such exploration might be limited if you end up with something incompatible with "proper" Rust anyways. I suppose it depends on how frequently "transition through invalid Rust while experimenting and end up with valid Rust" happens instead of "transition through invalid Rust w…
Re: Rust--: Rust without the borrow checker
#234Earlier quoted context omitted.
>The difference is that unsafe fn's can be encapsulated in safe wrappers This is the koolaid I am not willing to drink. If you can add safety very carefully on top of unsafe stuff (without any help from compiler), why not just use `c` and add safety by just being very careful? > IO tagged type signatures viral throughout your program (and as a result annoying).. Well, that is what good type systems do. Carry informat…
> If you can add safety very carefully on top of unsafe stuff (without any help from compiler), why not just use `c` and add safety by just being very careful? Y'know people complain a lot about Rust zealots and how they come into discussions and irrationally talk about how Rust's safety is our lord and savior and can eliminate all bugs or whatever... But your take (and every one like it) is one of the weakest I've h…
1. In `c` one have to remember a few, fairly intutive things, and enforce them without fail.
2. In rust, one have to learn, remember ever increasing number of things and constantly deal with non-intutive borrow-checker shenanigans that can hit your project at any point of the development forcing you to re-architecture your project, despite doing everything to ensure "safety". But the borrow-checker can't be convinced.
I have had enough of 2. I might use rust if I want to build a critical system with careless programmers, but who would do such a thing? For open source dependencies, one will have to go by community vouching or auditing themselves. Can't count something to be "Safe" just because it is in rust, right? So what is the point. I just don't see it. I mean, if you look a bit deeper, It just does not make any sense.
Re: Rust--: Rust without the borrow checker
#235Re: Rust--: Rust without the borrow checker
#236Earlier quoted context omitted.
> It will even work fine as long as you don't write code which invokes UB (which does include code which would not pass the borrow checker, as the borrow checker necessarily rejects valid programs in order to forbid all invalid programs). To be clear, by "this" I meant "[allowing] code that would normally violate Rust's borrowing rules to compile and run successfully," which both of us seem to believe to be UB.
Not quite, there is code which fails borrow checking but is safe and sound. That is part of why a number of people have been waiting for Polonius and / or the tree borrows model, most classic are relatively trivial cases of "check then update" which fail to borrow check but are obviously non-problematic e.g. pub fn get_or_insert ( map: &'_ mut HashMap , ) -> &'_ String { if let Some(v) = map.get(&22) { return v; } ma…
You seem to be operating on some (generous) underlying assumptions about what a borrow-checker-violating Rust program really means and what optimizations the compiler has the liberty to make even when borrow-checker assumptions are violated. But are you sure that assumption is well-founded? What is it formally based on?
Re: Rust--: Rust without the borrow checker
#237Earlier quoted context omitted.
Not quite, there is code which fails borrow checking but is safe and sound. That is part of why a number of people have been waiting for Polonius and / or the tree borrows model, most classic are relatively trivial cases of "check then update" which fail to borrow check but are obviously non-problematic e.g. pub fn get_or_insert ( map: &'_ mut HashMap , ) -> &'_ String { if let Some(v) = map.get(&22) { return v; } ma…
I don't feel you're quite following what I'm saying unfortunately. In your specific example: couldn't the optimizer just optimize out all the mutations you've written, under the assumption that such a program would not have passed borrow-checking and thus isn't a case it needs to handle? Wouldn't this make it so that if you disabled borrow checking, you would get incorrect codegen vs. what you intended? This seems li…
Disagreeing with your plainly incorrect assertion is not "not following" what you're saying.
> In your specific example: couldn't the optimizer just optimize out all the mutations you've written, under the assumption that such a program would not have passed borrow-checking and thus isn't a case it needs to handle?
No. The borrow checker ensures specific rules are followed, the borrow checker is not the rules themselves, and the optimisations are based on the underlying rules not on the borrow checker.
The program above abides by the underlying rules, it's literally the sort of examples used by people working on the next generation borrow checker, but the current borrow checker is not able to understand that.
> This seems like an entirely legal and sane optimization
It's neither of those things.
> You seem to be operating on some (generous) underlying assumptions about what a borrow-checker-violating Rust program really means and what optimizations the compiler has the liberty to make even when borrow-checker assumptions are violated. But are you sure that assumption is well-founded? What is it formally based on?
They are not assumptions, or generous. They are an understanding of the gap between the capabilities of the NLL borrow checker and "Behavior considered undefined".
They are what anyone working on the borrow checker sees as limitations of the borrow checker (some fixable, others intrinsic).
Re: Rust--: Rust without the borrow checker
#238Earlier quoted context omitted.
I don't feel you're quite following what I'm saying unfortunately. In your specific example: couldn't the optimizer just optimize out all the mutations you've written, under the assumption that such a program would not have passed borrow-checking and thus isn't a case it needs to handle? Wouldn't this make it so that if you disabled borrow checking, you would get incorrect codegen vs. what you intended? This seems li…
> I don't feel you're quite following what I'm saying unfortunately. Disagreeing with your plainly incorrect assertion is not "not following" what you're saying. > In your specific example: couldn't the optimizer just optimize out all the mutations you've written, under the assumption that such a program would not have passed borrow-checking and thus isn't a case it needs to handle? No. The borrow checker ensures spe…
I'm sorry, that particular comment wasn't disagreeing so much as missing my point entirely. It gave an example that would've still suffered from the same problem I was talking about if the optimizer relied on the same borrowing assumptions (hence my subsequent comment clarifying this) and it also diverted the discussion toward explaining the basics of incompleteness and the halting problem to me, neither of which indicated a following of my point at all, and both of which indicated a misunderstanding of where my (mis)understanding was.
But your new comment tracks it now (thanks).
>> This seems like an entirely legal and sane optimization
> It's neither of those things.
Thanks for clarifying.
> They are what anyone working on the borrow checker sees as limitations of the borrow checker (some fixable, others intrinsic).
I understand this, but it (again) doesn't contradict my point. Just because something is a known limitation of an earlier stage like the borrow checker, that doesn't mean that relaxing it would never require a change to later stages of the compiler, which never had to consider other possibilities before. Just like how limitations of the type checker don't imply that relaxing them would automatically cause the backend to generate correct code. It depends how the compiler is written and what the underlying rules and assumptions are for the later stages, and what's actually tested in practice, hence this entire question.
Heck, weren't there literal bugs discovered in LLVM during Rust development (was it noalias?) simply because those patterns weren't seen or tested much prior to Rust, despite being intended to work? It feels quite... optimistic to just change the constraints in one stage and assume they will work correctly for the later stages of a compiler with zero additional work. It makes sense if there's already active work to ensure this in the later stages, and I don't know if that's the case here or not, but if there isn't, then it feels risky.
> the optimisations are based on the underlying rules not on the borrow checker
Is there a link I can follow to these underlying rules so I can see what they are?
Re: Rust--: Rust without the borrow checker
#239Earlier quoted context omitted.
> I don't feel you're quite following what I'm saying unfortunately. Disagreeing with your plainly incorrect assertion is not "not following" what you're saying. > In your specific example: couldn't the optimizer just optimize out all the mutations you've written, under the assumption that such a program would not have passed borrow-checking and thus isn't a case it needs to handle? No. The borrow checker ensures spe…
> Disagreeing with your plainly incorrect assertion is not "not following" what you're saying. I'm sorry, that particular comment wasn't disagreeing so much as missing my point entirely. It gave an example that would've still suffered from the same problem I was talking about if the optimizer relied on the same borrowing assumptions (hence my subsequent comment clarifying this) and it also diverted the discussion tow…
(Note that I am an author of that paper, and also that this is just a proposal of the rules and not yet adopted as normative.)
What you seem to be forgetting in this discussion is that unsafe code exists. The example above does not pass the borrow checker, but with a small amount of unsafe code (casting a reference to a pointer and back to erase the lifetime constraints) you can make it compile. But of course with unsafe code it is possible to write programs that have undefined behavior. The question is whether this specific program has undefined behavior, and the answer is no.
Since it does not have undefined behavior, the rest of the compiler already has to preserve its semantics. So one could also tweak the borrow checker to accept this program.
TL;DR unsafe code exists and so you can't just say all programs not passing the borrow checker are UB.
Re: Rust--: Rust without the borrow checker
#240Earlier quoted context omitted.
> If you can add safety very carefully on top of unsafe stuff (without any help from compiler), why not just use `c` and add safety by just being very careful? Y'know people complain a lot about Rust zealots and how they come into discussions and irrationally talk about how Rust's safety is our lord and savior and can eliminate all bugs or whatever... But your take (and every one like it) is one of the weakest I've h…
I think it comes down to 1. In `c` one have to remember a few, fairly intutive things, and enforce them without fail. 2. In rust, one have to learn, remember ever increasing number of things and constantly deal with non-intutive borrow-checker shenanigans that can hit your project at any point of the development forcing you to re-architecture your project, despite doing everything to ensure "safety". But the borrow-c…