Skip to content

Commit 9cf9030

Browse files
committed
Allow using fn pointers in const fn behind const_fn_ptr gate
1 parent ea3ba36 commit 9cf9030

File tree

10 files changed

+148
-4
lines changed

10 files changed

+148
-4
lines changed

src/librustc_mir/transform/qualify_consts.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -1407,11 +1407,23 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
14071407
}
14081408
}
14091409
ty::FnPtr(_) => {
1410+
let unleash_miri = self
1411+
.tcx
1412+
.sess
1413+
.opts
1414+
.debugging_opts
1415+
.unleash_the_miri_inside_of_you;
1416+
let const_fn_ptr = self.tcx.features().const_fn_ptr;
14101417
if self.mode.requires_const_checking() {
1411-
let mut err = self.tcx.sess.struct_span_err(
1412-
self.span,
1413-
&format!("function pointers are not allowed in const fn"));
1414-
err.emit();
1418+
if !(unleash_miri || const_fn_ptr) {
1419+
emit_feature_err(
1420+
&self.tcx.sess.parse_sess,
1421+
sym::const_fn_ptr,
1422+
self.span,
1423+
GateIssue::Language,
1424+
"function pointers in const fn are unstable",
1425+
);
1426+
}
14151427
}
14161428
}
14171429
_ => {

src/libsyntax/feature_gate/active.rs

+3
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,9 @@ declare_features! (
405405
/// Allows macro invocations in `extern {}` blocks.
406406
(active, macros_in_extern, "1.27.0", Some(49476), None),
407407

408+
/// Allows calling function pointers inside `const` functions.
409+
(active, const_fn_ptr, "1.27.0", Some(51909), None),
410+
408411
/// Allows accessing fields of unions inside `const` functions.
409412
(active, const_fn_union, "1.27.0", Some(51909), None),
410413

src/libsyntax_pos/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ symbols! {
198198
const_compare_raw_pointers,
199199
const_constructor,
200200
const_fn,
201+
const_fn_ptr,
201202
const_fn_union,
202203
const_generics,
203204
const_indexing,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// run-pass
2+
#![feature(const_fn)]
3+
#![feature(const_fn_ptr)]
4+
5+
const fn double(x: usize) -> usize { x * 2 }
6+
const X: fn(usize) -> usize = double;
7+
8+
const fn bar(x: usize) -> usize {
9+
X(x)
10+
}
11+
12+
const fn foo(x: fn(usize) -> usize, y: usize) -> usize {
13+
x(y)
14+
}
15+
16+
fn main() {
17+
const Y: usize = bar(2);
18+
assert_eq!(Y, 4);
19+
const Z: usize = foo(double, 2);
20+
assert_eq!(Z, 4);
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-pass
2+
3+
// FIXME: this should not pass
4+
5+
#![feature(const_fn)]
6+
#![feature(const_fn_ptr)]
7+
8+
fn double(x: usize) -> usize { x * 2 }
9+
const X: fn(usize) -> usize = double;
10+
11+
const fn bar(x: usize) -> usize {
12+
X(x)
13+
}
14+
15+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
warning: function is never used: `double`
2+
--> $DIR/const_fn_ptr_fail.rs:8:1
3+
|
4+
LL | fn double(x: usize) -> usize { x * 2 }
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(dead_code)]` on by default
8+
9+
warning: constant item is never used: `X`
10+
--> $DIR/const_fn_ptr_fail.rs:9:1
11+
|
12+
LL | const X: fn(usize) -> usize = double;
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
15+
warning: function is never used: `bar`
16+
--> $DIR/const_fn_ptr_fail.rs:11:1
17+
|
18+
LL | const fn bar(x: usize) -> usize {
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#![feature(const_fn)]
2+
#![feature(const_fn_ptr)]
3+
4+
fn double(x: usize) -> usize { x * 2 }
5+
const X: fn(usize) -> usize = double;
6+
7+
const fn bar(x: fn(usize) -> usize, y: usize) -> usize {
8+
x(y)
9+
}
10+
11+
const Y: usize = bar(X, 2);
12+
//~^ ERROR any use of this value will cause an error
13+
14+
const Z: usize = bar(double, 2);
15+
//~^ ERROR any use of this value will cause an error
16+
17+
18+
fn main() {
19+
assert_eq!(Y, 4);
20+
assert_eq!(Z, 4);
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
error: any use of this value will cause an error
2+
--> $DIR/const_fn_ptr_fail2.rs:8:5
3+
|
4+
LL | x(y)
5+
| ^^^^
6+
| |
7+
| calling non-const function `double`
8+
| inside call to `bar` at $DIR/const_fn_ptr_fail2.rs:11:18
9+
...
10+
LL | const Y: usize = bar(X, 2);
11+
| ---------------------------
12+
|
13+
= note: `#[deny(const_err)]` on by default
14+
15+
error: any use of this value will cause an error
16+
--> $DIR/const_fn_ptr_fail2.rs:8:5
17+
|
18+
LL | x(y)
19+
| ^^^^
20+
| |
21+
| calling non-const function `double`
22+
| inside call to `bar` at $DIR/const_fn_ptr_fail2.rs:14:18
23+
...
24+
LL | const Z: usize = bar(double, 2);
25+
| --------------------------------
26+
27+
error: aborting due to 2 previous errors
28+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(const_fn)]
2+
3+
fn main() {}
4+
5+
const fn foo() {}
6+
const X: fn() = foo;
7+
8+
const fn bar() {
9+
X()
10+
//~^ ERROR function pointers in const fn are unstable
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0658]: function pointers in const fn are unstable
2+
--> $DIR/feature-gate-const_fn_ptr.rs:9:5
3+
|
4+
LL | X()
5+
| ^^^
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/51909
8+
= help: add `#![feature(const_fn_ptr)]` to the crate attributes to enable
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)