-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add Rvalue-static-promotion RFC #1414
Conversation
[motivation]: #motivation | ||
|
||
Right now, when dealing with constant values, you have to explicitly define | ||
`const` or `static` items to create references with `'static` lifetime, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would I believe actually be a bit more powerful than the current workaround with consts and statics since those can't be parameterized over type parameters of the e.g. function they're defined in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, indeed, you can do stuff like &None::<T>
with this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example, &None::<T>
could be returned even if T
were a type parameter, or &[T; 0]
(but the array case is actually hardcoded from before any attempts at rvalue promotions).
In the MIR, rvalues end up in temporary "lvalues" (as opposed to variable lvalues). |
There are two ways this could be taken further with zero-sized types: | ||
|
||
1. Remove the `UnsafeCell` restriction if the type of the rvalue is zero-sized. | ||
2. The above, but also remove the __constexpr__ restriction, applying to any zero-sized rvalue instead. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The restriction about not having a destructor should probably stay even for zero-sized types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently types with destructors are not zero-sized but that will change and I agree - there is no reason not to be conservative, for now, IMHO.
For the specific case of destructors, remember that the following are more or less equal:
let x = &EmptyDestructible;
...
let temp = EmptyDestructible;
{
let x = &temp;
...
}
Drop::drop(&mut temp)
Thus, rvalue drops can be considered "mutable accesses".
And even if the destructor doesn't have any bytes to actually mutate, it has to run.
So you would be changing behavior if you remove the destructor call, and otherwise you kind of make a mess out of borrow semantics by allowing the resulting &'static EmptyDestructible
to escape the scope its destructor ran in.
In the end, no UB can actually occur, but it still seems troubling to do this dance around destructors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to use value-destructor-freedom rather than type-destructor-freedom here.
I am concerned about this being breaking behavior; I'm not sure what would cause it, exactly, but |
Consider this function:
What type does
The pointer to |
@steveklabnik AFAIK no stable (1.x) Rust version has been released where |
I cannot find what I'm thinking of now, but I remember having arguments
related to this issue on the bugtracker at some point.
|
@petrochenkov In the existing (1.x stable and current nightly) compilers, It goes deeper than that: I assume your performance concerns are about the following scenarios (represented in pseudo-machine-code):
You are correct that in variable-length encodings, storing a byte to memory and doing a register-to-register copy can be shorter than placing a constant pointer into a register. But is it faster? Even if the stack is in cache (which it should be), the memory store is not free. AFAIK LLVM doesn't do that kind of escape analysis at this moment. |
@eddyb |
@petrochenkov That's because you're loading the value and not actually using the pointer itself. |
@eddyb |
Isn't "promoting to (This also feels eerily similar to "overlapping |
On Fri, Dec 18, 2015 at 03:02:03PM -0800, Eduard-Mihai Burtescu wrote:
It seems to me that the purpose of this RFC (and i've not had time to |
On Sat, Dec 19, 2015 at 06:06:14AM -0800, Gábor Lehel wrote:
Indeed, this kind of special-case reasoning around zero-sized types |
@nikomatsakis My point is that there won't be any surprise because the compiler already does this promotion so unsafe code couldn't have relied on |
On Tue, Dec 22, 2015 at 09:09:40AM -0800, Eduard-Mihai Burtescu wrote:
Sure, though conceivably it might rely on |
You're referring to the same thing as my previous comment, right? Something along the lines of: let value = 5;
do_something_with(&value); // fine even if promoted
unsafe {
// happens to work now, page fault if promoted
*transmute::<&i32, &mut i32>(&value) = 6;
} |
FWIW, in two (1 and 2) places in |
What is the status of this? |
cc @rust-lang/lang -- I'd like to see this RFC go forward! Most of the infrastructure in the compiler is laid, and I think the core idea is sound. The key is that when you borrow a constant (e.g., Reading the thread, I think the major concerns have to do with the runtime guarantees. Since the runtime behavior does not (and should not) depend on lifetime inference, this implies that That said, I still haven't had time to do a detailed review of the rules -- I have the printout here in front of me though and plan to do it now. But my feeling is that while we may find some minor detail to correct, we should go forward with the general idea. @rfcbot fcp merge |
Ah, one thought I had that I should raise. This text in the RFC itself:
Seems to suggest we ought to also just enable generic statics/constants already. I used to think "that makes no sense!" -- at least for statics -- but now I realize it's just another case of monomorphization of course. That said, it's prob better to defer this to a second RFC. |
Team member @nikomatsakis has proposed to merge this. The next step is review by the rest of the tagged teams: Concerns:
Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
create a `&'static mut` to a zero-sized type without involving unsafe code: | ||
|
||
```rust | ||
fn return_fn_mut_or_default(&mut self) -> &FnMut(u32, u32) -> u32 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this signature a typo? In particular, did you mean to write that the return value is a &mut FnMut(u32, u32) -> u32
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, that's a typo!
(update: sorry for repeating myself; I'm still trying to figure out how to use the rfcbot...; I put a properly constructed comment down below.) |
@pnkfelix I agree, in fact, the way it's implemented right now we don't take advantage of it in most cases. |
@rfcbot resolved basis-for-static-mut (@dikaiosune does this work yet?) |
@eddyb I think only the original comment author can resolve their concern. |
@rfcbot resolved basis-for-static-mut |
@rfcbot reviewed |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
This has been in FCP for 16 days and there have been no new comments. Merging. |
Does the |
|
Atomic types use |
Add feature gate for rvalue-static-promotion Probably needs more tests (which ones?) and there may be other things that need to be done. Also not sure whether the version that introduces the flag is really `1.15.1`. See rust-lang/rfcs#1414. Updates rust-lang#38865.
Add feature gate for rvalue-static-promotion Probably needs more tests (which ones?) and there may be other things that need to be done. Also not sure whether the version that introduces the flag is really `1.15.1`. See rust-lang/rfcs#1414. Updates rust-lang#38865.
Add feature gate for rvalue-static-promotion Probably needs more tests (which ones?) and there may be other things that need to be done. Also not sure whether the version that introduces the flag is really `1.15.1`. See rust-lang/rfcs#1414. Updates rust-lang#38865.
Add feature gate for rvalue-static-promotion Probably needs more tests (which ones?) and there may be other things that need to be done. Also not sure whether the version that introduces the flag is really `1.15.1`. See rust-lang/rfcs#1414. Updates rust-lang#38865.
Promote constexpr rvalues to values in static memory instead of stack slots, and expose those in the language by being able to directly create
'static
references to them.This would allow code like
let x: &'static u32 = &42
to work.Rendered
Credit for idea and impl goes to @nikomatsakis and @eddyb ;)
Closes #827