Skip to content
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

[RFC accepted] add wrapper for discriminant_value intrinsic #34785

Closed
wants to merge 1 commit into from

Conversation

durka
Copy link
Contributor

@durka durka commented Jul 12, 2016

add wrapper for discriminant_value intrinsic

Wraps the discriminant_value intrinsic under the name std::mem::discriminant. In order to avoid prematurely leaking information about the implementation of enums, the return value is an opaque type, generic over the enum type, which implements Copy, Clone, PartialEq, Eq, Hash, and Debug (notably not PartialOrd). There is currently no way to get the value out excepting printing the debug representation.

The wrapper is safe and can be stabilized soon as per discussion in #24263.

r? @brson

@durka
Copy link
Contributor Author

durka commented Jul 12, 2016

I just realized the wrapper should be safe. Another commit incoming...

pub struct TraitObject {
pub data: *mut (),
pub vtable: *mut (),
}

/// Returns the value of the discriminant for the enum variant in `v`.
Copy link
Member

@sfackler sfackler Jul 12, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is probably worth adding a warning that discriminants may not compare in the correct order if the enum is #[repr(i64)] due to overflow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do.

On Tue, Jul 12, 2016 at 1:43 PM, Steven Fackler notifications@github.com
wrote:

In src/libcore/raw.rs
#34785 (comment):

pub struct TraitObject {
pub data: *mut (),
pub vtable: *mut (),
}
+
+/// Returns the value of the discriminant for the enum variant in v.

It is probably worth adding a warning that discriminants may not compare
in the correct order if the enum is #[repr(u64)] due to overflow.


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/rust/pull/34785/files/609c17e8d0ceac437261df2c6b4231225f1faf08#r70485187,
or mute the thread
https://github.com/notifications/unsubscribe/AAC3n4IaNbDuCLcSiYjaKILI3yho7yvLks5qU9IrgaJpZM4JKnnt
.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, I don't understand. You mean if the enum is not #[repr(u64)]?

On Tue, Jul 12, 2016 at 1:46 PM, Alex Burka durka42@gmail.com wrote:

Will do.

On Tue, Jul 12, 2016 at 1:43 PM, Steven Fackler notifications@github.com
wrote:

In src/libcore/raw.rs
#34785 (comment):

pub struct TraitObject {
pub data: *mut (),
pub vtable: *mut (),
}
+
+/// Returns the value of the discriminant for the enum variant in v.

It is probably worth adding a warning that discriminants may not compare
in the correct order if the enum is #[repr(u64)] due to overflow.


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/rust/pull/34785/files/609c17e8d0ceac437261df2c6b4231225f1faf08#r70485187,
or mute the thread
https://github.com/notifications/unsubscribe/AAC3n4IaNbDuCLcSiYjaKILI3yho7yvLks5qU9IrgaJpZM4JKnnt
.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Er, yeah. Your doc change is what I was thinking of.

@alexcrichton
Copy link
Member

I might personally prefer this being located in the std::mem module as opposed to std::raw. We've almost deleted the entire std::raw module and I'd personally like to see it go out all the way!

Also, could the actual stabilization be deferred to a later date? The libs team tends to not apply stabilizations mid-cycle but instead places issues into final comment period at the end of which we decide on the stabilization outcome (as a result of the discussion, if any, that happened).

cc @rust-lang/libs, any objections on moving this to FCP though? Seems good to me!

@durka
Copy link
Contributor Author

durka commented Jul 12, 2016

OK, I had previously asked at the tracking issue if this should be insta-stable (since it is basically stabilizing the intrinsic, even though it doesn't actually do that) and @brson said yes. But I'm happy to mark it unstable for now. I'll move it to std::mem as well (though it doesn't have much if anything to do with memory).

@durka durka force-pushed the discriminant_value branch 2 times, most recently from 29e3b0d to 1001205 Compare July 12, 2016 18:16
@durka
Copy link
Contributor Author

durka commented Jul 12, 2016

@sfackler's comment was hidden, but I added a note about comparisons.

@durka durka force-pushed the discriminant_value branch 2 times, most recently from eb26969 to 3a88d88 Compare July 12, 2016 18:17
/// enum Foo { A(String), B(i32) }
///
/// # fn main() {
/// assert!(mem::discriminant(Foo::A("bar")) != mem::discriminant(Foo::A("baz")));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these examples may not compile, the discriminants should be the same here, right? Additionally, shouldn't a shared reference be passed in?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I just noticed that and fixed it.

On Tue, Jul 12, 2016 at 2:19 PM, Alex Crichton notifications@github.com
wrote:

In src/libcore/mem.rs
#34785 (comment):

+/// same order as actual enum variants would under #[derive(PartialOrd)].
+///
+/// If T is not an enum, the return value is unspecified.
+///
+/// # Example
+///
+/// This can be used to compare enums that carry data, while disregarding
+/// the actual data:
+///
+/// ```
+/// use std::mem;
+///
+/// enum Foo { A(String), B(i32) }
+///
+/// # fn main() {
+/// assert!(mem::discriminant(Foo::A("bar")) != mem::discriminant(Foo::A("baz")));

I think these examples may not compile, the discriminants should be the
same here, right? Additionally, shouldn't a shared reference be passed in?


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/rust/pull/34785/files/3a88d8811ae23af836e8ed4349e4a96656303878#r70492383,
or mute the thread
https://github.com/notifications/unsubscribe/AAC3n1nIqX5ydVTZ2ue3rNp94IPEA-khks5qU9qggaJpZM4JKnnt
.

@durka durka force-pushed the discriminant_value branch 3 times, most recently from 987979d to c35ec62 Compare July 12, 2016 18:26
@sfackler
Copy link
Member

@alexcrichton I want to stabilize type_name or something like it, so we might want to keep std::raw around for things like that.

@durka
Copy link
Contributor Author

durka commented Jul 12, 2016

Is it the case that a discriminant can never be larger than u64? (I think there is an RFC to add u128 and whatnot...)

@durka
Copy link
Contributor Author

durka commented Jul 12, 2016

For the record (on the theme of my previous comment) I still think it would be better to use the type system to make this function's return type better. But I also understand we want to stabilize something.

@durka durka changed the title add stable wrapper for discriminant_value intrinsic add soon-to-be-stable wrapper for discriminant_value intrinsic Jul 12, 2016
@alexcrichton
Copy link
Member

@sfackler hm that's a good point about type_name, but I figure we can probably figure out a better way to do that than putting it in std::raw

@brson brson added the relnotes Marks issues that should be documented in the release notes of the next release. label Jul 12, 2016
@aturon
Copy link
Member

aturon commented Jul 13, 2016

I wasn't initially a fan of std::mem for this, but I can sort of see it now. E.g. this is not so different from things like size_of, which are type-generic functions giving repr details. I could see type_name living here eventually, too.

assert_eq!(mem::discriminant(&NullablePointer::Something(&CONST)), 0);

// unlike the test for the intrinsic, there are no tests with non-enums here
// because the result is documented to be unspecified
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could still call it on a struct, just to check that it doesn't panic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@durka
Copy link
Contributor Author

durka commented Aug 1, 2016

RFC posted at rust-lang/rfcs#1696.

@bors
Copy link
Contributor

bors commented Aug 26, 2016

☔ The latest upstream changes (presumably #35906) made this pull request unmergeable. Please resolve the merge conflicts.

@durka
Copy link
Contributor Author

durka commented Aug 26, 2016

Waiting to rebase until the RFC process concludes.

@durka durka changed the title [WIP] add wrapper for discriminant_value intrinsic [RFC accepted] add wrapper for discriminant_value intrinsic Sep 16, 2016
@durka
Copy link
Contributor Author

durka commented Sep 16, 2016

Rebased and updated.

I removed the Reflect bound as per the RFC (nobody opined on it during FCP). I'm assuming that trait's FCP will end in deprecation; if not, we could revisit.

I updated the stability section of the documentation to say (again, nobody opined during FCP):

Discriminants can change if enum variants are reordered, if a new variant is addedin the middle, or (in the case of a C-like enum) if explicitly set discriminants are changed. Therefore, relying on the discriminants of enums outside of your crate may be a poor decision. However, discriminants of an identical enum should not change between subsequent compilations with the same compiler.

@aturon
Copy link
Member

aturon commented Sep 27, 2016

@nagisa Can you take over this review, given that you've already looked at the PR?

///
/// # Stability
///
/// Discriminants can change if enum variants are reordered, if a new variant is added
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the return value of this wrapper is a opaque value Discriminant<T>, this section reads weird. Namely it changing makes little sense because you aren’t supposed to be able to inspect it directly. Rather the stability and behaviour should be described in terms of PartialEq and Hash.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point.

#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")]
impl<T> fmt::Debug for Discriminant<T> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(fmt)
Copy link
Member

@nagisa nagisa Sep 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably wants to use a debug builder and output something along the lines of Discriminant(<number>), rather than outputting a plain number.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK.

pub struct Discriminant<T>(u64, PhantomData<*const T>);

#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")]
impl<T> Copy for Discriminant<T> {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not derive all these implementations?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'd get nonsense bounds on T.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I'd included a comment to this effect. I'll add one.

@durka
Copy link
Contributor Author

durka commented Sep 27, 2016

I think it's ready, just waiting for tests.

@aturon
Copy link
Member

aturon commented Sep 27, 2016

@durka OK, just give a ping once it's ready for bors and i'll send it along.

@durka
Copy link
Contributor Author

durka commented Sep 28, 2016

Tests and tidy pass locally.

@aturon
Copy link
Member

aturon commented Sep 28, 2016

Huzzah!

@bors: r=nagisa

@durka
Copy link
Contributor Author

durka commented Sep 28, 2016

@bors? you there?

@aturon
Copy link
Member

aturon commented Sep 28, 2016

@bors: r+

@aturon
Copy link
Member

aturon commented Sep 28, 2016

@bors r=nagisa

@aturon aturon closed this Sep 28, 2016
@aturon aturon reopened this Sep 28, 2016
@aturon
Copy link
Member

aturon commented Sep 28, 2016

@bors: r=nagisa

@durka
Copy link
Contributor Author

durka commented Sep 29, 2016

Should I try reopening as a new PR?

@durka
Copy link
Contributor Author

durka commented Sep 29, 2016

Moved to #36823.

bors added a commit that referenced this pull request Sep 30, 2016
add wrapper for discriminant_value, take 2

[This is #34785 reopened, since @bors apparently gave up on that thread.]

add wrapper for discriminant_value intrinsic

Implementation of [RFC 1696](https://github.com/rust-lang/rfcs/blob/master/text/1696-discriminant.md).

Wraps the `discriminant_value` intrinsic under the name `std::mem::discriminant`. In order to avoid prematurely leaking information about the implementation of enums, the return value is an opaque type, generic over the enum type, which implements Copy, Clone, PartialEq, Eq, Hash, and Debug (notably not PartialOrd). There is currently no way to get the value out excepting printing the debug representation.

The wrapper is safe and can be stabilized soon as per discussion in #24263.

cc @aturon
r? @nagisa
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
relnotes Marks issues that should be documented in the release notes of the next release. T-lang Relevant to the language team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.