-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Freezing &mut only works for locals. #8124
Comments
I think that this is a legit error, although perhaps the error message could be improved. The problem is that the compiler doesn't know what The error message makes you think that That's also why the first case works, it's because the compiler knows exactly what's been borrowed |
That's true. However, I still think it would be completely safe to allow for passing the immutable reference to |
10 brownie points to @alexcrichton for saying exactly what I wanted to say @michaelwoerister -- Before 'pure' was removed, the old borrow-checker used to be able to reason about what @nikomatsakis, is this a motivating use case for keeping &const in the language? |
@bblum I think the compiler can still do some reasoning about that now (although it may not be exactly the same as was possible with 'pure'). An From (1) and (2) follows that: An So if I have a function taking only A function not returning any references ( From (8) and (9) follows that a function not returning a reference and taking only immutable reference cannot violate any of '&mut' guarantees (5, 6, 7). I am not sure how all this relates to The reason for my longwinded argumentation is that this is a pretty common case and I think it might be off-putting to people if they can't do something that they know to be safe and that is no problem in other languages. Concerning |
Hmm, I think your reasoning is right (and the motivation to make the borrow-checker more permissible is definitely right). The best counterexample I came up with would be something like:
But the catch is that the closure captures a mutable borrow in its environment, so is secretly a mutable borrow itself. (And we are already planning to track whether stack closures are 'secretly mutable borrows', so we would be able to notice this case.) |
The risk with adding this sort of permissiveness is that, while it allows more cases, it makes the set of cases that are allowed defined by more complicated rules and hence more difficult to fully understand. (I think the same has come up regarding making the borrow-checker more flow-sensitive.) As I see it the tradeoff is between confusing people earlier by forbidding seemingly-legal code and confusing people later with a more complex overall model. (Personally I am fine with this suggested rule, but others may see it differently?) |
@bblum Thanks for taking the time to think about this. I am aware of the trade off. However, I think this case could be okay because it is kind of intuitive ("I hold the exclusive right to modify something right now, I should be able to temporarily give somebody else the right to read from it") and all information needed is available statically (no need to know the current runtime state of something) and locally (no need to look anywhere else but the current function body to know what's going on---well, except one has to know that the return type of the function does not contain any references). Regarding your example: This would be a different case from the one above because the mutable and the immutable reference are both accessible at the same time, while in my example the mutable reference would not be accessible during the execution of the function taking the immutable reference (which is the crucial condition for making this safe). But I do hear you about making the overall ruleset more complicated. |
There are certainly ways we could make the compiler smarter. In this particular case, one issue is that we have generally tried to draw the line at "alias analysis"---that is, we make no effort to determine what set of values is "reachable" from a called function, but instead assume that it can somehow connive its way into accessing everything. I am not opposed to extending the borrow checker to make it smarter, but I am wary of doing so now, since we are still finishing up the corner cases on the current set of rules. |
I thought about this a bit more. The big challenge here is that (1) we do not currently treat borrows for calls differently than other borrows in the borrow checker and (2) we do not track nor know of the connection between
Here I made the implicit stuff more explicit. What winds up happening from the borrow checker's point of view is that So now what would have to happen is that when What we could do in such a situation is, in lieu of reporting an error, just go and effectively freeze everything, since we can't know for sure what we need to freeze. This is effectively what the old purity rules did. We'd want to think hard about the precise mechanism for doing this. We can of course get away with not freezing some stuff, and we'd have to decide where to draw the line. This is what I meant before by "alias analysis", since effectively we're trying to write some rules to decide what might and might not alias |
Yes, this probably is the hole in my argumentation. I thought we statically knew--- by construction ---that the initial If it were necessary to add another restriction, that no |
@michaelwoerister Your model was a bit simplistic, but it is not the problem here. You were correct that The problem is more in the details of how much information the borrow checker has. At the point where, in your example, you do |
Or at least block write access, I should say. |
@nikomatsakis says this is a wontfix. |
make unwrap_used also trigger on .get().unwrap() fixes rust-lang#8124 changelog: make the [unwrap_used] lint trigger for code of the form such as `.get(i).unwrap()` and `.get_mut(i).unwrap()`
The following is an example program that shows what I mean:
The compiler error is:
I think the borrow checker should allow both cases. During the execution of
copy_out_of_immutable()
no mutable alias to neitherstuff
norstuff.y
is accessible, so it is guaranteed that the data behind the immutable reference won't change.This might be the same as #6268 (although I think it is a bit different).
The text was updated successfully, but these errors were encountered: