-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Backwards compatibility hazard with Box
+ &mut
behaviour that cannot be replicated by a pure-library type
#14270
Comments
Box
's interactions with &mut
which cannot be implemented for a pure-library typeBox
's interactions with &mut
which cannot be implemented for a pure-library type
Learn something new every day! |
Box
's interactions with &mut
which cannot be implemented for a pure-library typeBox
+ &mut
behaviour that cannot be replicated by a pure-library type
I never considered it a priority to be able to move |
Assigning P-low. And maybe we should actually close this. cc: @nikomatsakis |
The real question is whether we will ever support other "unique" pointer types in the library. It is not entirely clear to me what the best resolution is here. |
The issue with Theoretically, borrowck could try and track whether a A more limited suggestion would be to have borrowck merely consider the results of |
Actually, thinking about it some more, |
Theoretically it can be reborrowed, i.e. it could be equivalent to (Frankly I don't think we need to preserve this behaviour if we do decide to make compiler types and library types equal in this respect, it is almost certainly a very rare edge case and can easily be fixed by adding a |
@huonw fn main() {
let mut a = 3i;
let b = box &mut a;
let c = &b;
**b = 4i;
println!("{}", c);
} Note that I can still assign to More importantly, you can't say The question is, is the current behavior worth keeping, or can all clients of the current behavior be made to work with Also I'm mildly concerned about the fact that I can mutate the boxed |
That just seems like a bug (filed as #14498 ): fn main() {
let mut a = 3i;
let b = box &mut a;
let c = &b;
let d = &***c;
**b = 4i;
println!("{} {}", c, d);
} |
Ooh, you can get a fn main() {
let mut a = 3i;
let b = box &mut a;
let c = &**b;
**b = 4i;
println!("{}", c);
} |
@kballard this is #12624 . I am increasingly of the opinion that we should just remove all special treatment of |
Oh, my mistake, I see it was not #12624. Anyway, looks like it was filed, fixed, and reviewed before I had a chance to get to this e-mail. :) |
@nikomatsakis I'd still like to see the ability to move out of |
@kballard yes to all of that. |
@kballard except the last part about telling box not to destruct its content. I'm not sure of the point of that. But if we did have that capability to move/replace from
(This would basically be the equivalent of If we did at some point add the theorized |
@nikomatsakis Yeah if you replace the value it's fine, but if you could move out without replacing and just tell |
I know that this has already had a nomination removed once before, but I'm renominating because I think the reasoning given was hasty. It is still a backcompat hazard to some degree, because if we ever want to move In the meantime, we could free ourselves of that obligation by restricting the behavior of It's fine if you want to immediately remove this nomination, just please acknowledge that it effectively amounts to a binding promise regarding future features that will be added to the language. |
I’d like to bring up RFC 130, which removes some special casing of
|
1.0 P-backcompat-lang |
I started working on this. Since the mutability checks are in terms of mem categorizations rather than loan paths, this is a bit trickier than I expected, but I think I know how to do it. |
Re-nominating. This needs to be triaged again as part of our box story for beta. |
Assigning 1.0-beta milestone. |
nominating: someone needs to own this issue for the beta. |
assigning to self. (We may or may not resolve this by the beta, but we must address whether we are fixing it by then.) |
What is the plan to fix this? |
We plan to change things to require the For now its a bug that it is not required. We plan to fix the bug as part of 1.0 polish. |
i have a potential patch for this. (It is a kludge/hack that revises the |
…akis Disallow writing through mutable pointers stored in non-mut Box. Fix rust-lang#14270 The fix works by making `cmt::freely_aliasable` result more fine-grained. Instead of encoding the aliasability (i.e. whether the cmt is uniquely writable or not) as an option, now pass back an enum indicating either: 1. freely-aliasable (thus not uniquely-writable), 2. non-aliasable (thus uniquely writable), or 3. unique but immutable (and thus not uniquely writable, according to proposal from issue rust-lang#14270.) This is all of course a giant hack that will hopefully go away with an eventually removal of special treatment of `Box<T>` (aka `ty_unique`) from the compiler.
@pnkfelix the issue isn't fixed, the following code works on rust 1.28
|
@nivkner Oh at this point I think its fair to say that we have punted, at least in the NLL work, on trying to avoid special casing of Box See for example PR #52782 I do think there is talk of eventually allowing users to express similar features in their own library data types. But I’m not sure that warrants reopening this particular ticket |
Though I am curious ... I added a test when I “fixed” this originally ... did the test not actually cover this case, or has it regressed ... |
Wow apparently the test I put in that commit didn’t actually include @huonw’s original basic example ... it jumped straight into a lot of other scenarios (that are all admitedly important to test) boy oh boy ... |
Wait no, it did include the new diagnostic I added; I Just didn’t see it at first It was on the fn borrow_in_var_from_var_via_imm_box() But still, that case has an intervening borrow |
Ah okay PR #40841 got rid of the diagnostic, and I didn’t notice (or chose not to mention it) during review of that PR (Probably should have had a legit regression test focused solely on huon’s example as written.) Okay my curiosity is satisfied. Still not planning to reopen this ticket. :) |
With
Box
built deeply into the compiler, one can currently writeThat is, one can mutate through a
&mut
stored in theBox
, even if theBox
itself is not in a mutable slot. This is (presumably) because the compiler currently understands a lot aboutBox
s behaviour, in particular, that it can act like an immutable unaliased pointer (&uniq
).There's currently no way to get this behaviour for library types, e.g.
Vec<&mut int>
is theoretically identical toBox
in terms of ownership/aliasability of its contents, but, as it is a library type, the following cannot be made to work:We would need an immutable
&uniq
pointer for this behaviour to be possible for general simply-owned types like an in-libraryBox
,Vec
,HashMap
etc.Having this behaviour for
Box
represents a possible backwards compatibility hazard if we ever decide to moveBox
more into libraries. Specifically, movingBox
into a library and preserving its current behaviour perfectly would require (at least) adding this new&uniq
pointer type.(Thanks to /u/SteveMcQwark on reddit for prompting this.)
(Nominating.)
The text was updated successfully, but these errors were encountered: