-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Allow references to interior mutable data behind a feature gate #80418
Allow references to interior mutable data behind a feature gate #80418
Conversation
The job Click to see the possible cause of the failure (guessed by this bot)
|
That's only a partial solution though, right? It means we cannot support any getter-style methods such as fn fst_ref<T, U>(x: &(T, U)) -> &T { &x.0 } (and same for So, I am not sure if this is worth it, since it seems rather restrictive. (I have no idea what your previous plan was in #80373 since I hadn't gotten around to reading it before you closed it.) |
Uh... no. If the feature gate is active, we only error on locals that have no |
This comment has been minimized.
This comment has been minimized.
Note that we can just outright not check anything in |
I think I am lost, I have no idea what this means. Having no And how does the referent matter, isn't if the reference for which we care if it ends up in the final value? When we see an expression Unless you mean we are checking the Some examples could help. :) |
Oh, I think I get it -- if the referent has a But I am a bit worried about drawing ourselves into a corner here, since it doesn't work for reborrowing getters. |
That said, that is a concern for stabilization -- for experimentation, this approach seems fine. I hope I'll have tome to review the code changes tomorrow. |
Afaict, in constants, that's not an issue, and even if it were, all that would mean is that our check forbids more things than we want. That's ok, we can be more permissive later.
Heh, ok, yea, I see the misunderstanding, and it is exactly the problem I had with building a static analyis for this until eddyb gave me the enlightening clue. Let's start with an example: const FOO: &Cell<i32> = &Cell::new(42); expands to something like the following MIR: StorageLive(_2)
_2 = 42;
StorageLIve(_1)
_1 = Cell::new(42) -> bb2
bb2:
StorageDead(_2)
_0 = &_1
return Now, you are right, So with this new analysis, you either get a hard error because you tried to take a reference to a local that has interior mutability and lives forever, or you get a validation error later because you created a dangling pointer. We can talk about dangling pointers independently, they are entirely orthogonal to preventing references to interior mutable data in constants. You can create the easily without having to do anything related to (interior) mutability. |
I added this to a test, and it works. We don't actually need to check for such borrows in |
Uh, I don't see the obvious argument for why this is sound. The returned reference could come from various places, including things like I also saw this in the code:
The soundness argument above only works if |
For a The only places other than a heap allocation that you can return references to is things that the function arguments point to (if function arguments are references or pointers), or static items.
I... don't know how we could have MIR like that. It's a valid concern that we can resolve by adding MIR validation checks I believe. It should never happen afaik. We can additionally count the number of assignments to the local, and if there is only one assignment and only one |
I think there is something that could possibly be problematic: a
Ah I see. That argument makes sense, but it very fundamentally relies on "no heap allocations". So if we stabilize this we say goodbye to some ways of supporting heap allocations -- IOW, we shouldn't stabilize this before having figured out the heap allocation story.
I don't follow this argument. "By construction" sounds very similar to "by the possible shapes of a MIR body" to me. |
Oop, I meant by mir building ("mir construction"), not the formal "by construction".
I can absolutely live with that. We should probably explore this feature with heap on nightly. Actually, this PR is necessary to even be able to experiment with generic heap abstractions, as that requires borrowing generic types. |
Hm, that still seems like a rather fragile invariant. At the very least, the code (and tracking issue) should explicitly spell out what we are relying on: if a |
Added to the unresolved questions in the tracking issue. |
yes, but that's what I mean. right now there is no way to write such a |
☔ The latest upstream changes (presumably #80459) made this pull request unmergeable. Please resolve the merge conflicts. |
9e9fe1d
to
9c9b605
Compare
Co-authored-by: Ralf Jung <post@ralfj.de>
Co-authored-by: Ralf Jung <post@ralfj.de>
Beautiful, thanks for taking care of my nitpicking. :) |
📌 Commit 90b56b9 has been approved by |
⌛ Testing commit 90b56b9 with merge d3bc943b9a4dfe86ea7c56c5b4af86a1aba1b08b... |
The job Click to see the possible cause of the failure (guessed by this bot)
|
💔 Test failed - checks-actions |
@bors retry I just ran the wasm tests locally and they passed, so I call spurious |
☀️ Test successful - checks-actions |
supercedes #80373 by simply not checking for interior mutability on borrows of locals that have
StorageDead
and thus can never be leaked to the final value of the constanttracking issue: #80384
r? @RalfJung