If I'm understanding correct, the major change here for Rust users (rather than people who hack on the compiler) is that mutable references will not be considered to be "interfering" with other references being made at the same time until they're actually written to for the first time. This makes intuitive sense to me, but I suspect that there may be a bit of concern that this will make things more confusing when rea…
To be clear, this doesn't change what programs get accepted by the borrow checker, so for most rust users it changes absolutely nothing. It changes the abstract rules behind rust's safety model, which impacts which unsafe functions are considered sound, and which optimizations the compiler is allowed to perform.
From Stacks to Trees: A new aliasing model for Rust
21–30 of 43 posts
Re: From Stacks to Trees: A new aliasing model for Rust
#22If I'm understanding correct, the major change here for Rust users (rather than people who hack on the compiler) is that mutable references will not be considered to be "interfering" with other references being made at the same time until they're actually written to for the first time. This makes intuitive sense to me, but I suspect that there may be a bit of concern that this will make things more confusing when rea…
To be clear, this doesn't change what programs get accepted by the borrow checker, so for most rust users it changes absolutely nothing. It changes the abstract rules behind rust's safety model, which impacts which unsafe functions are considered sound, and which optimizations the compiler is allowed to perform.
This is what the footnote of the bit about &(i32, Cell) clarifies (which footnote was added due to this misunderstanding, discussed in https://old.reddit.com/r/rust/comments/13y8a9b/from_stacks_t...).
> In particular, for &(i32, Cell), TB allows mutating both fields, including the first field which is a regular i32, since it just treats the entire reference as “this allows aliasing”.¹
> ¹ This does not mean that we bless such mutation! It just means that the compiler cannot use immutability of the first field for its optimizations. Basically, immutability of that field becomes a safety invariant instead of a validity invariant […]
This matter of safety versus validity invariants is key (https://www.ralfj.de/blog/2018/08/22/two-kinds-of-invariants...).
Re: From Stacks to Trees: A new aliasing model for Rust
#23Earlier quoted context omitted.
> Compiler being obtuse and not being able to figure when it is safe to "break rules" is the problem. Compiler afaik will never be able to correctly 100% identify you are or aren't breaking some properties due to Rice's Theorem. That said, you're committing a Nirvana fallacy. Perfect doesn't prevent improvement. E.g. seatbelts don't prevent being stabbed by a large metal pole, ergo it's useless. Every week I see newb…
>"Compiler afaik will never be able to correctly 100% identify" Nobody here is talking about 100%. I responded to a post that has left me with the impression that it is up to the user to bend backwards and make their brains work as a compiler rather than try to improve compiler.
What do you mean? You always have to track lifetimes and what outlives what (i.e. work of a compiler). Especially in C++. Not doing that results in UB.
In Rust you have a compiler double checking you. And it errs on side of caution. And no, errors aren't horrible, they come with suggestions for fixing them.
Re: From Stacks to Trees: A new aliasing model for Rust
#24> ...by the time x.len() gets executed, arg0 already exists... So, I realize that this is the way that Java does it--and, presumably, one still doesn't get fired for doing whatever Java does ;P--but, would it not actually make more sense for the arguments to be evaluated before the target reference, making the argument order more like Haskell/Erlang (but very sadly not Elixir, which makes it awkwardly incompatible wi…
Re: From Stacks to Trees: A new aliasing model for Rust
#25fn two_phase(mut x: Vec ) { let arg0 = &mut x; let arg1 = Vec::len(&x); Vec::push(arg0, arg1); } > This code clearly violates the regular borrow checking rules since x is mutably borrowed to arg0 when we call x.len()! And yet, the compiler will accept this code Does anybody else wish the compiler wouldn't and would be even more verbose? I know one of the biggest learning curves (personally) for Rust is the borrow che…
>"Does anybody else wish the compiler wouldn't" Compiler being obtuse and not being able to figure when it is safe to "break rules" is the problem. Not twisting brain of the programmer into being "safe compiler". This sounds like a Stockholm syndrome. >"you should be following immutable practices" No I should not. I should do what makes sense in particular situation and not bending over for some zealots trying to enf…
Lifetimes don't go away just because there isn't a borrow checker or way to define them in the source code.
Re: From Stacks to Trees: A new aliasing model for Rust
#26Earlier quoted context omitted.
I think one measurable outcome here is what kind of error message you get when you do violate a rule and whether rust users know what to do to fix their code. As a person who loves to explore the complexity behind seemingly simple interfaces, this stuff is really cool. On the other hand, I don't relish having people break their brains to understand why similar code is accepted vs not. I'm not a rust user myself, but…
>"so maybe the complexity is not going to affect too many people" I think this approach shows a high level of disrespect for users.
Re: From Stacks to Trees: A new aliasing model for Rust
#27Once you get the &mut reference, you have your tree, which then looks to me like you have created a transaction. An in this transaction context you do your things.
Re: From Stacks to Trees: A new aliasing model for Rust
#28> ...by the time x.len() gets executed, arg0 already exists... So, I realize that this is the way that Java does it--and, presumably, one still doesn't get fired for doing whatever Java does ;P--but, would it not actually make more sense for the arguments to be evaluated before the target reference, making the argument order more like Haskell/Erlang (but very sadly not Elixir, which makes it awkwardly incompatible wi…
interesting. Can you expand on Elixir incompatibility? How is it different?
Enum.map(list, func)
This is backwards to how partial application works: def mapper(func), do: Enum.map(func)
incrementer = mapper(fn x -> x + 1 end)
incrementer(list)
It's not the end of the world to not have it this way, but it removes a lot of patterns that are common in other functional languages.Re: From Stacks to Trees: A new aliasing model for Rust
#29I have not programmed Rust, yet. But this article gives me a feeling that this looks similar to database transactions. This might be wildly wrong but for me I see an analogy: Once you get the &mut reference, you have your tree, which then looks to me like you have created a transaction. An in this transaction context you do your things.
Re: From Stacks to Trees: A new aliasing model for Rust
#30Earlier quoted context omitted.
To be clear, this doesn't change what programs get accepted by the borrow checker, so for most rust users it changes absolutely nothing. It changes the abstract rules behind rust's safety model, which impacts which unsafe functions are considered sound, and which optimizations the compiler is allowed to perform.
Ah, I guess I did misunderstand then. I see now rereading that the "don't treat as a mutable borrow until first write" is already how things behave today and have since NLL.
fn main() {
let mut x = [1,2,3,4,5];
let y = &mut x[0];
let z = &x[1];
println!("y {}... z {} ", y, z);
}
But it doesn't.