about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-03-11 10:36:28 +0100
committerGitHub <noreply@github.com>2020-03-11 10:36:28 +0100
commitdfbbd5d6ead535de08ff8d10e320194ac7585457 (patch)
tree152f1a34df4b39a12e134541f5ffc6eaaac212a2 /src
parent452c147fba6f15478b25ab24c9b3077a5b1ebfbc (diff)
parent7b3e3ff39aa45103a6f8432466f8078970866142 (diff)
downloadrust-dfbbd5d6ead535de08ff8d10e320194ac7585457.tar.gz
rust-dfbbd5d6ead535de08ff8d10e320194ac7585457.zip
Rollup merge of #69825 - lcnr:discriminant, r=oli-obk
make `mem::discriminant` const

implements #69821, which could be used as a tracking issue for `const_discriminant`.

Should this be added to the meta tracking issue #57563?
@Lokathor
Diffstat (limited to 'src')
-rw-r--r--src/libcore/intrinsics.rs1
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/mem/mod.rs3
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs5
-rw-r--r--src/librustc_span/symbol.rs1
-rw-r--r--src/test/ui/consts/const_discriminant.rs40
6 files changed, 50 insertions, 1 deletions
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 721a2d26a71..3c060cc6e84 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1862,6 +1862,7 @@ extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is
     /// [`std::mem::discriminant`](../../std/mem/fn.discriminant.html)
+    #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
     pub fn discriminant_value<T>(v: &T) -> u64;
 
     /// Rust's "try catch" construct which invokes the function pointer `f` with
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index f4874c77213..a1dde1d51ef 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -72,6 +72,7 @@
 #![feature(concat_idents)]
 #![feature(const_ascii_ctype_on_intrinsics)]
 #![feature(const_alloc_layout)]
+#![feature(const_discriminant)]
 #![feature(const_if_match)]
 #![feature(const_loop)]
 #![feature(const_checked_int_methods)]
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs
index 8add875dcbe..7d9a8bcd05b 100644
--- a/src/libcore/mem/mod.rs
+++ b/src/libcore/mem/mod.rs
@@ -870,6 +870,7 @@ impl<T> fmt::Debug for Discriminant<T> {
 /// assert_ne!(mem::discriminant(&Foo::B(3)), mem::discriminant(&Foo::C(3)));
 /// ```
 #[stable(feature = "discriminant_value", since = "1.21.0")]
-pub fn discriminant<T>(v: &T) -> Discriminant<T> {
+#[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
+pub const fn discriminant<T>(v: &T) -> Discriminant<T> {
     Discriminant(intrinsics::discriminant_value(v), PhantomData)
 }
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 891afbf437f..1e5ed76c467 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -216,6 +216,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 };
                 self.write_scalar(val, dest)?;
             }
+            sym::discriminant_value => {
+                let place = self.deref_operand(args[0])?;
+                let discr_val = self.read_discriminant(place.into())?.0;
+                self.write_scalar(Scalar::from_uint(discr_val, dest.layout.size), dest)?;
+            }
             sym::unchecked_shl
             | sym::unchecked_shr
             | sym::unchecked_add
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 1e09cd79dbe..d8ce9bbdfb3 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -265,6 +265,7 @@ symbols! {
         derive,
         diagnostic,
         direct,
+        discriminant_value,
         doc,
         doc_alias,
         doc_cfg,
diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs
new file mode 100644
index 00000000000..1ad5134e71c
--- /dev/null
+++ b/src/test/ui/consts/const_discriminant.rs
@@ -0,0 +1,40 @@
+// run-pass
+#![feature(const_discriminant)]
+#![allow(dead_code)]
+
+use std::mem::{discriminant, Discriminant};
+
+// `discriminant(const_expr)` may get const-propagated.
+// As we want to check that const-eval is equal to ordinary exection,
+// we wrap `const_expr` with a function which is not const to prevent this.
+#[inline(never)]
+fn identity<T>(x: T) -> T { x }
+
+enum Test {
+    A(u8),
+    B,
+    C { a: u8, b: u8 },
+}
+
+const TEST_A: Discriminant<Test> = discriminant(&Test::A(5));
+const TEST_A_OTHER: Discriminant<Test> = discriminant(&Test::A(17));
+const TEST_B: Discriminant<Test> = discriminant(&Test::B);
+
+enum Void {}
+
+enum SingleVariant {
+    V,
+    Never(Void),
+}
+
+const TEST_V: Discriminant<SingleVariant> = discriminant(&SingleVariant::V);
+
+fn main() {
+    assert_eq!(TEST_A, TEST_A_OTHER);
+    assert_eq!(TEST_A, discriminant(identity(&Test::A(17))));
+    assert_eq!(TEST_B, discriminant(identity(&Test::B)));
+    assert_ne!(TEST_A, TEST_B);
+    assert_ne!(TEST_B, discriminant(identity(&Test::C { a: 42, b: 7 })));
+
+    assert_eq!(TEST_V, discriminant(identity(&SingleVariant::V)));
+}