diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 7cc1e634cf812..795721f3b3f28 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -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(); } } diff --git a/src/test/ui/consts/const-eval/const_fn_ptr.rs b/src/test/ui/consts/const-eval/const_fn_ptr.rs new file mode 100644 index 0000000000000..498f801db81b8 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_fn_ptr.rs @@ -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); +} diff --git a/src/test/ui/consts/const-eval/const_fn_ptr.stderr b/src/test/ui/consts/const-eval/const_fn_ptr.stderr new file mode 100644 index 0000000000000..41452ee59eb94 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_fn_ptr.stderr @@ -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 + diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail.rs b/src/test/ui/consts/const-eval/const_fn_ptr_fail.rs new file mode 100644 index 0000000000000..14bd6558e7f89 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail.rs @@ -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() {} diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs new file mode 100644 index 0000000000000..74c60f9a2a58d --- /dev/null +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs @@ -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 +} diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr new file mode 100644 index 0000000000000..611cc5313c057 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr @@ -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`.