|
15 | 15 |
|
16 | 16 | #![stable(feature = "rust1", since = "1.0.0")]
|
17 | 17 |
|
| 18 | +use clone; |
| 19 | +use cmp; |
| 20 | +use fmt; |
| 21 | +use hash; |
18 | 22 | use intrinsics;
|
| 23 | +use marker::{Copy, PhantomData, Sized}; |
19 | 24 | use ptr;
|
20 | 25 |
|
21 | 26 | #[stable(feature = "rust1", since = "1.0.0")]
|
@@ -647,3 +652,80 @@ pub fn drop<T>(_x: T) { }
|
647 | 652 | pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
|
648 | 653 | ptr::read(src as *const T as *const U)
|
649 | 654 | }
|
| 655 | + |
| 656 | +/// Opaque type representing the discriminant of an enum. |
| 657 | +/// |
| 658 | +/// See the `discriminant` function in this module for more information. |
| 659 | +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] |
| 660 | +pub struct Discriminant<T>(u64, PhantomData<*const T>); |
| 661 | + |
| 662 | +// N.B. These trait implementations cannot be derived because we don't want any bounds on T. |
| 663 | + |
| 664 | +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] |
| 665 | +impl<T> Copy for Discriminant<T> {} |
| 666 | + |
| 667 | +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] |
| 668 | +impl<T> clone::Clone for Discriminant<T> { |
| 669 | + fn clone(&self) -> Self { |
| 670 | + *self |
| 671 | + } |
| 672 | +} |
| 673 | + |
| 674 | +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] |
| 675 | +impl<T> cmp::PartialEq for Discriminant<T> { |
| 676 | + fn eq(&self, rhs: &Self) -> bool { |
| 677 | + self.0 == rhs.0 |
| 678 | + } |
| 679 | +} |
| 680 | + |
| 681 | +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] |
| 682 | +impl<T> cmp::Eq for Discriminant<T> {} |
| 683 | + |
| 684 | +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] |
| 685 | +impl<T> hash::Hash for Discriminant<T> { |
| 686 | + fn hash<H: hash::Hasher>(&self, state: &mut H) { |
| 687 | + self.0.hash(state); |
| 688 | + } |
| 689 | +} |
| 690 | + |
| 691 | +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] |
| 692 | +impl<T> fmt::Debug for Discriminant<T> { |
| 693 | + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
| 694 | + fmt.debug_tuple("Discriminant") |
| 695 | + .field(&self.0) |
| 696 | + .finish() |
| 697 | + } |
| 698 | +} |
| 699 | + |
| 700 | +/// Returns a value uniquely identifying the enum variant in `v`. |
| 701 | +/// |
| 702 | +/// If `T` is not an enum, calling this function will not result in undefined behavior, but the |
| 703 | +/// return value is unspecified. |
| 704 | +/// |
| 705 | +/// # Stability |
| 706 | +/// |
| 707 | +/// The discriminant of an enum variant may change if the enum definition changes. A discriminant |
| 708 | +/// of some variant will not change between compilations with the same compiler. |
| 709 | +/// |
| 710 | +/// # Examples |
| 711 | +/// |
| 712 | +/// This can be used to compare enums that carry data, while disregarding |
| 713 | +/// the actual data: |
| 714 | +/// |
| 715 | +/// ``` |
| 716 | +/// #![feature(discriminant_value)] |
| 717 | +/// use std::mem; |
| 718 | +/// |
| 719 | +/// enum Foo { A(&'static str), B(i32), C(i32) } |
| 720 | +/// |
| 721 | +/// assert!(mem::discriminant(&Foo::A("bar")) == mem::discriminant(&Foo::A("baz"))); |
| 722 | +/// assert!(mem::discriminant(&Foo::B(1)) == mem::discriminant(&Foo::B(2))); |
| 723 | +/// assert!(mem::discriminant(&Foo::B(3)) != mem::discriminant(&Foo::C(3))); |
| 724 | +/// ``` |
| 725 | +#[unstable(feature = "discriminant_value", reason = "recently added, follows RFC", issue = "24263")] |
| 726 | +pub fn discriminant<T>(v: &T) -> Discriminant<T> { |
| 727 | + unsafe { |
| 728 | + Discriminant(intrinsics::discriminant_value(v), PhantomData) |
| 729 | + } |
| 730 | +} |
| 731 | + |
0 commit comments