about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-10-14 10:06:30 +0000
committerbors <bors@rust-lang.org>2021-10-14 10:06:30 +0000
commitc34ac8747ca96d09cb08b8f5adddead826e77c06 (patch)
tree23a25e70efd4d935b3aea4b3082baed6add97917 /src/test
parent7807a694c2f079fd3f395821bcc357eee8650071 (diff)
parent11fac09eadc3a60982e46e2fed177d6b0a686041 (diff)
downloadrust-c34ac8747ca96d09cb08b8f5adddead826e77c06.tar.gz
rust-c34ac8747ca96d09cb08b8f5adddead826e77c06.zip
Auto merge of #89247 - fee1-dead:const-eval-select, r=oli-obk
Add `const_eval_select` intrinsic

Adds an intrinsic that calls a given function when evaluated at compiler time, but generates a call to another function when called at runtime.

See https://github.com/rust-lang/const-eval/issues/7 for previous discussion.

r? `@oli-obk.`
Diffstat (limited to 'src/test')
-rw-r--r--src/test/codegen/intrinsics/const_eval_select.rs17
-rw-r--r--src/test/ui/intrinsics/const-eval-select-bad.rs36
-rw-r--r--src/test/ui/intrinsics/const-eval-select-bad.stderr65
-rw-r--r--src/test/ui/intrinsics/const-eval-select-stability.rs20
-rw-r--r--src/test/ui/intrinsics/const-eval-select-stability.stderr10
-rw-r--r--src/test/ui/intrinsics/const-eval-select-x86_64.rs39
-rw-r--r--src/test/ui/intrinsics/const-eval-select.rs26
7 files changed, 213 insertions, 0 deletions
diff --git a/src/test/codegen/intrinsics/const_eval_select.rs b/src/test/codegen/intrinsics/const_eval_select.rs
new file mode 100644
index 00000000000..34e653b4b9d
--- /dev/null
+++ b/src/test/codegen/intrinsics/const_eval_select.rs
@@ -0,0 +1,17 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(const_eval_select)]
+
+use std::intrinsics::const_eval_select;
+
+const fn foo(_: i32) -> i32 { 1 }
+
+#[no_mangle]
+pub fn hi(n: i32) -> i32 { n }
+
+#[no_mangle]
+pub unsafe fn hey() {
+    // CHECK: call i32 @hi(i32
+    const_eval_select((42,), foo, hi);
+}
diff --git a/src/test/ui/intrinsics/const-eval-select-bad.rs b/src/test/ui/intrinsics/const-eval-select-bad.rs
new file mode 100644
index 00000000000..8fbdc0c39c6
--- /dev/null
+++ b/src/test/ui/intrinsics/const-eval-select-bad.rs
@@ -0,0 +1,36 @@
+#![feature(const_eval_select)]
+
+use std::intrinsics::const_eval_select;
+
+const fn not_fn_items() {
+    const_eval_select((), || {}, || {});
+    //~^ ERROR expected a `FnOnce<()>` closure
+    const_eval_select((), 42, 0xDEADBEEF);
+    //~^ ERROR expected a `FnOnce<()>` closure
+}
+
+const fn foo(n: i32) -> i32 {
+    n
+}
+
+fn bar(n: i32) -> bool {
+    assert_eq!(n, 0, "{} must be equal to {}", n, 0);
+    n == 0
+}
+
+fn baz(n: bool) -> i32 {
+    assert!(n, "{} must be true", n);
+    n as i32
+}
+
+const fn return_ty_mismatch() {
+    const_eval_select((1,), foo, bar);
+    //~^ ERROR type mismatch
+}
+
+const fn args_ty_mismatch() {
+    const_eval_select((true,), foo, baz);
+    //~^ ERROR type mismatch
+}
+
+fn main() {}
diff --git a/src/test/ui/intrinsics/const-eval-select-bad.stderr b/src/test/ui/intrinsics/const-eval-select-bad.stderr
new file mode 100644
index 00000000000..78647e92138
--- /dev/null
+++ b/src/test/ui/intrinsics/const-eval-select-bad.stderr
@@ -0,0 +1,65 @@
+error[E0277]: expected a `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]`
+  --> $DIR/const-eval-select-bad.rs:6:34
+   |
+LL |     const_eval_select((), || {}, || {});
+   |     -----------------            ^^^^^ expected an `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]`
+   = note: wrap the `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `const_eval_select`
+  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+LL |     F: ~const FnOnce<ARG, Output = RET>,
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `{integer}`
+  --> $DIR/const-eval-select-bad.rs:8:31
+   |
+LL |     const_eval_select((), 42, 0xDEADBEEF);
+   |     -----------------         ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `{integer}`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `{integer}`
+   = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `const_eval_select`
+  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+LL |     F: ~const FnOnce<ARG, Output = RET>,
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+
+error[E0271]: type mismatch resolving `<fn(i32) -> bool {bar} as FnOnce<(i32,)>>::Output == i32`
+  --> $DIR/const-eval-select-bad.rs:27:5
+   |
+LL |     const_eval_select((1,), foo, bar);
+   |     ^^^^^^^^^^^^^^^^^ expected `i32`, found `bool`
+   |
+note: required by a bound in `const_eval_select`
+  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+LL |     G: FnOnce<ARG, Output = RET> + ~const Drop,
+   |                    ^^^^^^^^^^^^ required by this bound in `const_eval_select`
+
+error[E0631]: type mismatch in function arguments
+  --> $DIR/const-eval-select-bad.rs:32:37
+   |
+LL | const fn foo(n: i32) -> i32 {
+   | --------------------------- found signature of `fn(i32) -> _`
+...
+LL |     const_eval_select((true,), foo, baz);
+   |     -----------------               ^^^ expected signature of `fn(bool) -> _`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `const_eval_select`
+  --> $SRC_DIR/core/src/intrinsics.rs:LL:COL
+   |
+LL |     F: ~const FnOnce<ARG, Output = RET>,
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0271, E0277, E0631.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/intrinsics/const-eval-select-stability.rs b/src/test/ui/intrinsics/const-eval-select-stability.rs
new file mode 100644
index 00000000000..db2462aee59
--- /dev/null
+++ b/src/test/ui/intrinsics/const-eval-select-stability.rs
@@ -0,0 +1,20 @@
+#![feature(staged_api)]
+#![feature(const_eval_select)]
+#![stable(since = "1.0", feature = "ui_test")]
+
+use std::intrinsics::const_eval_select;
+
+fn log() {
+    println!("HEY HEY HEY")
+}
+
+const fn nothing(){}
+
+#[stable(since = "1.0", feature = "hey")]
+#[rustc_const_stable(since = "1.0", feature = "const_hey")]
+pub const unsafe fn hey() {
+    const_eval_select((), nothing, log);
+    //~^ ERROR `const_eval_select` is not yet stable as a const fn
+}
+
+fn main() {}
diff --git a/src/test/ui/intrinsics/const-eval-select-stability.stderr b/src/test/ui/intrinsics/const-eval-select-stability.stderr
new file mode 100644
index 00000000000..79641bbb46a
--- /dev/null
+++ b/src/test/ui/intrinsics/const-eval-select-stability.stderr
@@ -0,0 +1,10 @@
+error: `const_eval_select` is not yet stable as a const fn
+  --> $DIR/const-eval-select-stability.rs:16:5
+   |
+LL |     const_eval_select((), nothing, log);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: const-stable functions can only call other const-stable functions
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/intrinsics/const-eval-select-x86_64.rs b/src/test/ui/intrinsics/const-eval-select-x86_64.rs
new file mode 100644
index 00000000000..afec8e054bb
--- /dev/null
+++ b/src/test/ui/intrinsics/const-eval-select-x86_64.rs
@@ -0,0 +1,39 @@
+// run-pass
+// only-x86_64
+
+#![feature(const_eval_select)]
+use std::intrinsics::const_eval_select;
+use std::arch::x86_64::*;
+use std::mem::transmute;
+
+const fn eq_ct(x: [i32; 4], y: [i32; 4]) -> bool {
+    x[0] == y[0] && x[1] == y[1] && x[2] == y[2] && x[3] == y[3]
+}
+
+fn eq_rt(x: [i32; 4], y: [i32; 4]) -> bool {
+    unsafe {
+        let x = _mm_loadu_si128(&x as *const _ as *const _);
+        let y = _mm_loadu_si128(&y as *const _ as *const _);
+        let r = _mm_cmpeq_epi32(x, y);
+        let r = _mm_movemask_ps(transmute(r) );
+        r == 0b1111
+    }
+}
+
+const fn eq(x: [i32; 4], y: [i32; 4]) -> bool {
+    unsafe {
+        const_eval_select((x, y), eq_ct, eq_rt)
+    }
+}
+
+fn main() {
+    const X: bool = eq([0, 1, 2, 3], [0, 1, 2, 3]);
+    assert_eq!(X, true);
+    let x = eq([0, 1, 2, 3], [0, 1, 2, 3]);
+    assert_eq!(x, true);
+
+    const Y: bool = eq([0, 1, 2, 3], [0, 1, 3, 2]);
+    assert_eq!(Y, false);
+    let y = eq([0, 1, 2, 3], [0, 1, 3, 2]);
+    assert_eq!(y, false);
+}
diff --git a/src/test/ui/intrinsics/const-eval-select.rs b/src/test/ui/intrinsics/const-eval-select.rs
new file mode 100644
index 00000000000..744db2f15b0
--- /dev/null
+++ b/src/test/ui/intrinsics/const-eval-select.rs
@@ -0,0 +1,26 @@
+// run-pass
+
+#![feature(const_eval_select)]
+
+use std::intrinsics::const_eval_select;
+
+const fn yes() -> bool {
+    true
+}
+
+fn no() -> bool {
+    false
+}
+
+// not a sound use case; testing only
+const fn is_const_eval() -> bool {
+    unsafe { const_eval_select((), yes, no) }
+}
+
+fn main() {
+    const YES: bool = is_const_eval();
+    let no = is_const_eval();
+
+    assert_eq!(true, YES);
+    assert_eq!(false, no);
+}