diff options
| author | bors <bors@rust-lang.org> | 2021-10-14 10:06:30 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-10-14 10:06:30 +0000 |
| commit | c34ac8747ca96d09cb08b8f5adddead826e77c06 (patch) | |
| tree | 23a25e70efd4d935b3aea4b3082baed6add97917 /src/test | |
| parent | 7807a694c2f079fd3f395821bcc357eee8650071 (diff) | |
| parent | 11fac09eadc3a60982e46e2fed177d6b0a686041 (diff) | |
| download | rust-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.rs | 17 | ||||
| -rw-r--r-- | src/test/ui/intrinsics/const-eval-select-bad.rs | 36 | ||||
| -rw-r--r-- | src/test/ui/intrinsics/const-eval-select-bad.stderr | 65 | ||||
| -rw-r--r-- | src/test/ui/intrinsics/const-eval-select-stability.rs | 20 | ||||
| -rw-r--r-- | src/test/ui/intrinsics/const-eval-select-stability.stderr | 10 | ||||
| -rw-r--r-- | src/test/ui/intrinsics/const-eval-select-x86_64.rs | 39 | ||||
| -rw-r--r-- | src/test/ui/intrinsics/const-eval-select.rs | 26 |
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); +} |
