Rollup merge of #64635 - gnzlbg:const_fn_ptr, r=oli-obk
Allow using fn pointers in const fn with unleash miri This allows using function pointers in const fns when `-Zunleash-the-miri-within-you` is enabled. If the call to the `const fn` happens in a `const`-context, the function pointer is required to point to a `const fn`: ```rust fn non_const_fn() -> i32 { 42 } const fn const_fn() -> i32 { 42 } const fn foo(x: fn() -> i32) -> i32 { x() } let x: i32 = foo(non_const_fn_ptr); // OK let y: i32 = foo(const_fn_ptr); // OK const X: i32 = foo(non_const_fn_ptr); // ERROR: `non_const_fn` is not `const fn` const Y: i32 = foo(const_fn_ptr); // OK ``` r? @oli-obk
This commit is contained in:
commit
25bdd76a54
@ -1407,10 +1407,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
ty::FnPtr(_) => {
|
||||
if self.mode.requires_const_checking() {
|
||||
let unleash_miri = self
|
||||
.tcx
|
||||
.sess
|
||||
.opts
|
||||
.debugging_opts
|
||||
.unleash_the_miri_inside_of_you;
|
||||
if self.mode.requires_const_checking() && !unleash_miri {
|
||||
let mut err = self.tcx.sess.struct_span_err(
|
||||
self.span,
|
||||
&format!("function pointers are not allowed in const fn"));
|
||||
"function pointers are not allowed in const fn"
|
||||
);
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
37
src/test/ui/consts/const-eval/const_fn_ptr.rs
Normal file
37
src/test/ui/consts/const-eval/const_fn_ptr.rs
Normal file
@ -0,0 +1,37 @@
|
||||
// run-pass
|
||||
// compile-flags: -Zunleash-the-miri-inside-of-you
|
||||
#![feature(const_fn)]
|
||||
|
||||
fn double(x: usize) -> usize { x * 2 }
|
||||
const fn double_const(x: usize) -> usize { x * 2 }
|
||||
|
||||
const X: fn(usize) -> usize = double;
|
||||
const X_const: fn(usize) -> usize = double_const;
|
||||
|
||||
const fn bar(x: usize) -> usize {
|
||||
X(x)
|
||||
}
|
||||
|
||||
const fn bar_const(x: usize) -> usize {
|
||||
X_const(x)
|
||||
}
|
||||
|
||||
const fn foo(x: fn(usize) -> usize, y: usize) -> usize {
|
||||
x(y)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const Y: usize = bar_const(2);
|
||||
assert_eq!(Y, 4);
|
||||
let y = bar_const(2);
|
||||
assert_eq!(y, 4);
|
||||
let y = bar(2);
|
||||
assert_eq!(y, 4);
|
||||
|
||||
const Z: usize = foo(double_const, 2);
|
||||
assert_eq!(Z, 4);
|
||||
let z = foo(double_const, 2);
|
||||
assert_eq!(z, 4);
|
||||
let z = foo(double, 2);
|
||||
assert_eq!(z, 4);
|
||||
}
|
152
src/test/ui/consts/const-eval/const_fn_ptr.stderr
Normal file
152
src/test/ui/consts/const-eval/const_fn_ptr.stderr
Normal file
@ -0,0 +1,152 @@
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:25:5
|
||||
|
|
||||
LL | assert_eq!(Y, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:25:5
|
||||
|
|
||||
LL | assert_eq!(Y, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:25:5
|
||||
|
|
||||
LL | assert_eq!(Y, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:27:5
|
||||
|
|
||||
LL | assert_eq!(y, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:27:5
|
||||
|
|
||||
LL | assert_eq!(y, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:27:5
|
||||
|
|
||||
LL | assert_eq!(y, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:29:5
|
||||
|
|
||||
LL | assert_eq!(y, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:29:5
|
||||
|
|
||||
LL | assert_eq!(y, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:29:5
|
||||
|
|
||||
LL | assert_eq!(y, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:32:5
|
||||
|
|
||||
LL | assert_eq!(Z, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:32:5
|
||||
|
|
||||
LL | assert_eq!(Z, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:32:5
|
||||
|
|
||||
LL | assert_eq!(Z, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:34:5
|
||||
|
|
||||
LL | assert_eq!(z, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:34:5
|
||||
|
|
||||
LL | assert_eq!(z, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:34:5
|
||||
|
|
||||
LL | assert_eq!(z, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:36:5
|
||||
|
|
||||
LL | assert_eq!(z, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:36:5
|
||||
|
|
||||
LL | assert_eq!(z, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr.rs:36:5
|
||||
|
|
||||
LL | assert_eq!(z, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: constant `X_const` should have an upper case name
|
||||
--> $DIR/const_fn_ptr.rs:9:7
|
||||
|
|
||||
LL | const X_const: fn(usize) -> usize = double_const;
|
||||
| ^^^^^^^ help: convert the identifier to upper case: `X_CONST`
|
||||
|
|
||||
= note: `#[warn(non_upper_case_globals)]` on by default
|
||||
|
13
src/test/ui/consts/const-eval/const_fn_ptr_fail.rs
Normal file
13
src/test/ui/consts/const-eval/const_fn_ptr_fail.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// run-pass
|
||||
// compile-flags: -Zunleash-the-miri-inside-of-you
|
||||
#![feature(const_fn)]
|
||||
#![allow(unused)]
|
||||
|
||||
fn double(x: usize) -> usize { x * 2 }
|
||||
const X: fn(usize) -> usize = double;
|
||||
|
||||
const fn bar(x: usize) -> usize {
|
||||
X(x) // FIXME: this should error someday
|
||||
}
|
||||
|
||||
fn main() {}
|
26
src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
Normal file
26
src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// compile-flags: -Zunleash-the-miri-inside-of-you
|
||||
#![feature(const_fn)]
|
||||
#![allow(const_err)]
|
||||
|
||||
fn double(x: usize) -> usize { x * 2 }
|
||||
const X: fn(usize) -> usize = double;
|
||||
|
||||
const fn bar(x: fn(usize) -> usize, y: usize) -> usize {
|
||||
x(y)
|
||||
}
|
||||
|
||||
const Y: usize = bar(X, 2); // FIXME: should fail to typeck someday
|
||||
const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday
|
||||
|
||||
fn main() {
|
||||
assert_eq!(Y, 4);
|
||||
//~^ ERROR evaluation of constant expression failed
|
||||
//~^^ WARN skipping const checks
|
||||
//~^^^ WARN skipping const checks
|
||||
//~^^^^ WARN skipping const checks
|
||||
assert_eq!(Z, 4);
|
||||
//~^ ERROR evaluation of constant expression failed
|
||||
//~^^ WARN skipping const checks
|
||||
//~^^^ WARN skipping const checks
|
||||
//~^^^^ WARN skipping const checks
|
||||
}
|
71
src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
Normal file
71
src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
Normal file
@ -0,0 +1,71 @@
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr_fail2.rs:16:5
|
||||
|
|
||||
LL | assert_eq!(Y, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr_fail2.rs:16:5
|
||||
|
|
||||
LL | assert_eq!(Y, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr_fail2.rs:16:5
|
||||
|
|
||||
LL | assert_eq!(Y, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr_fail2.rs:21:5
|
||||
|
|
||||
LL | assert_eq!(Z, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr_fail2.rs:21:5
|
||||
|
|
||||
LL | assert_eq!(Z, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
warning: skipping const checks
|
||||
--> $DIR/const_fn_ptr_fail2.rs:21:5
|
||||
|
|
||||
LL | assert_eq!(Z, 4);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
error[E0080]: evaluation of constant expression failed
|
||||
--> $DIR/const_fn_ptr_fail2.rs:16:5
|
||||
|
|
||||
LL | assert_eq!(Y, 4);
|
||||
| ^^^^^^^^^^^-^^^^^
|
||||
| |
|
||||
| referenced constant has errors
|
||||
|
|
||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
error[E0080]: evaluation of constant expression failed
|
||||
--> $DIR/const_fn_ptr_fail2.rs:21:5
|
||||
|
|
||||
LL | assert_eq!(Z, 4);
|
||||
| ^^^^^^^^^^^-^^^^^
|
||||
| |
|
||||
| referenced constant has errors
|
||||
|
|
||||
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
Loading…
x
Reference in New Issue
Block a user