-
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
discriminant_value intrinsic -- tracking issue for 639 #24263
Comments
Implements an intrinsic for extracting the value of the discriminant enum variant values. For non-enum types, this returns zero, otherwise it returns the value we use for discriminant comparisons. This means that enum types that do not have a discriminant will also work in this arrangement. This is (at least part of) the work on Issue rust-lang#24263
How is the progress here? I want to use it in a package, but I don't think it will be 1.0, right? Will it be included in 1.1? |
RE the documentation issue: The value wouldn't be unstable for the case of a C-like enum, so the statement about the value being unstable should be qualified as such. And, it would also be useful to document that this feature can/should be used instead of However, the RFC says that the type is always |
I previously suggested a way to solve the return type problem: introduce a trait instead of (or in addition to) the intrinsic function. trait MagicEnumTrait {
type Repr;
fn value(&self) -> Self::Repr;
} This trait would be auto-implemented for every enum and |
For Stylo we want to build with a stable Rust compiler. For Servo’s We use it with an enum that represents a property declaration: there’s one variant per supported CSS property, and each variants has a field with the property value. (The Rust types for values can be different for each property.) During the cascade, we get an sequence of declarations ordered by precedence, and we want to only keep one per property. We use There’s already some code generation going on in this crate, so we could write a function or method that behaves similarly to |
@SimonSapin if the results of the internal function are exactly the same as |
These enums are not C-like though, otherwise I could use |
My questions at this point:
|
Given that we can always deprecate an API in favor of an improved version later, and that the functionality is working fine (and is something we definitely want to provide), I see little downside to stabilizing a wrapper function right now. (Lang team discussed this and all feel the same way.) |
OK, so the concrete next step here is to write a wrapper function with the same signature and tag it stable. What module is it exported from? What's the process? Does it need an FCP period? |
In that case, I would expect |
@briansmith agreed. Does rustc sometimes shrink enums even if you specify
|
I don't know. I just read your comment above as suggesting that the smallest type should be used, insted of the type mentioned in |
Usually unstable things undergo a "release cycle"-long FCP period, yes. |
This seems like an important point. Now, in the meantime since we added this intrinsic, we also adopted specialization, which may make the need for such a bound moot. Do we all agree we "just don't care" about a bound? |
Well, if there's no bound, what happens when you call the function on a I'll try to write an RFC for my trait idea because I think being able to On Mon, Jun 27, 2016 at 2:15 PM, Niko Matsakis [email protected]
|
Servo update: TL;DR we’re not blocked on stabilization anymore, but it’d still be nice to have it eventually for debug build performance. In servo/servo#11884 I’ve worked around this being unavailable on stable with generated code like this: impl PropertyDeclaration {
fn discriminant_value(&self) -> usize {
match *self {
PropertyDeclaration::AlignContent(..) => 0,
PropertyDeclaration::AlignItems(..) => 1,
PropertyDeclaration::AlignSelf(..) => 2,
// ...
PropertyDeclaration::ZIndex(..) => 147,
}
}
} And made a test crate to look at the generated code: #![feature(core_intrinsics)]
extern crate style;
use std::intrinsics::discriminant_value;
pub fn with_match(decl: &style::properties::PropertyDeclaration) -> usize {
decl.discriminant_value()
}
pub fn with_intrinsic(decl: &style::properties::PropertyDeclaration) -> usize {
unsafe { discriminant_value(decl) as usize }
} With
But without |
@SimonSapin your comment seems to be truncated |
There's an open ICE: #43398. Possibly just an assertion in trans needs to be removed, but I don't know anything about that code. However, as a larger point, currently |
There are like 3 types about which we provide guarantees around their size (e.g. |
The final comment period is now complete. |
New summary commentQuoting from the original checklist:
IMO the return type is currently "opaque enough". Concerns raised during FCP:
Let's get this stabilized! |
Given that we can always add an impl of |
stabilize mem::discriminant (closes #24263)
I know this issue has already been closed, and the function is on track for stabilization, but I thought I should bring this up anyway since it seems odd to me: use std::mem;
enum MyEnum {
First,
Second(i32)
}
fn main() {
println!("{:?}", mem::discriminant(&MyEnum::Second)); // prints `0`
println!("{:?}", mem::discriminant(&MyEnum::Second(2))); // prints `1`
} IMO, it'd be nice to have the discriminant of the enum constructor match the discriminant of the enum value. I'm not sure if I've missed the boat here, but this seems like it would be really valuable for getting the discriminant without having to fully construct a value (this doesn't work for struct constructors, but that's something we could revisit). |
In theory we can change that since the docs say the return value for
non-enums is unspecified. But an enum constructor is "just" a function, so
I'm not sure it's a good idea.
…On Thu, Sep 7, 2017 at 12:50 PM, Taylor Cramer ***@***.***> wrote:
I know this issue has already been closed, and the function is on track
for stabilization, but I thought I should bring this up anyway since it
seems odd to me: mem::discriminant returns 0 for all non-enums, *including
enum constructors*. That is, the following code prints 0 and then 1:
use std::mem;
enum MyEnum {
First,
Second(i32)
}
fn main() {
println!("{:?}", mem::discriminant(&MyEnum::Second)); // prints `0`
println!("{:?}", mem::discriminant(&MyEnum::Second(2))); // prints `1`
}
IMO, it'd be nice to have the discriminant of the enum constructor match
the discriminant of the enum value. I'm not sure if I've missed the boat
here, but this seems like it would be really valuable for getting the
discriminant without having to fully construct a value (this doesn't work
for struct constructors, but that's something we could revisit).
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#24263 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAC3n5_4DIAuM3s6HQ4nvkuUTBhPsIcKks5sgB66gaJpZM4D96D5>
.
|
Hmm. I agree with @durka that at first it surprised me (because I think of them as a function), though really the type of a variant is (I believe...) a zero-sized type that uniquely identifies the enum variant. (Unless of course you coerce it into a function.) So it seems like it should be possible to make it work, and I do find @cramertj's use case compelling. |
But what about "struct" variants? enum Foo { ... Bar { ... } }` |
@nikomatsakis We employ the nuclear option ( |
@eddyb I suggested that exact thing on IRC in the lang channel: fn foo { a: i32, b: i32, c: i32 } -> i32 { a + b + c }
assert_eq!(foo { a: 1, b: 2, c: 3 }, 6); |
We didn't ever close this conversation, but |
@cramertj I'm not sure what you're asking for -- it currently says "If T is
not an enum, calling this function will not result in undefined behavior,
but the return value is unspecified."
…On Thu, Sep 21, 2017 at 1:32 PM, Taylor Cramer ***@***.***> wrote:
We didn't ever close this conversation, but mem::discriminant is set to
stabilize in 1.21. Can we at least adjust the docs to say that the return
value for non-enums is unspecified?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#24263 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAC3n5Lcd-nJNePXeczKjBFfG758-02eks5skp2YgaJpZM4D96D5>
.
|
@durka Ah, I was referring to your comment above where you said
|
We could try to head off the mistake by writing "If T is not an enum (including tuple variant constructors!)" or including your example from above. |
The current |
Nope, we should impl those traits. |
Hullo, does anybody know if any discussion/work is ongoing in line with @cramertj 's suggestion regarding calling std::mem::discriminant on an enum "constructor"? |
Tracking issue for rust-lang/rfcs#639.
Some things to nail down before stabilization:
<T:Reflect>
boundT
to actually be anenum
instance?The text was updated successfully, but these errors were encountered: