-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Allow using fn pointers in const fn with unleash miri #64635
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -1407,11 +1407,23 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { | |||||
} | ||||||
} | ||||||
ty::FnPtr(_) => { | ||||||
let unleash_miri = self | ||||||
.tcx | ||||||
.sess | ||||||
.opts | ||||||
.debugging_opts | ||||||
.unleash_the_miri_inside_of_you; | ||||||
let const_fn_ptr = self.tcx.features().const_fn_ptr; | ||||||
if self.mode.requires_const_checking() { | ||||||
let mut err = self.tcx.sess.struct_span_err( | ||||||
self.span, | ||||||
&format!("function pointers are not allowed in const fn")); | ||||||
err.emit(); | ||||||
if !(unleash_miri || const_fn_ptr) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the feature is inherently broken, maybe just do the unleash part and no feature gate? |
||||||
emit_feature_err( | ||||||
&self.tcx.sess.parse_sess, | ||||||
sym::const_fn_ptr, | ||||||
self.span, | ||||||
GateIssue::Language, | ||||||
"function pointers in const fn are unstable", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The other errors do not follow this style. cc @oli-obk There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The other errors are wrong then. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, but I'd rather not touch them before #64470 is merged There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that PR also enables function pointer calling behind unleash |
||||||
); | ||||||
} | ||||||
} | ||||||
} | ||||||
_ => { | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// run-pass | ||
#![feature(const_fn)] | ||
#![feature(const_fn_ptr)] | ||
|
||
const fn double(x: usize) -> usize { x * 2 } | ||
const X: fn(usize) -> usize = double; | ||
|
||
const fn bar(x: usize) -> usize { | ||
X(x) | ||
} | ||
|
||
const fn foo(x: fn(usize) -> usize, y: usize) -> usize { | ||
x(y) | ||
} | ||
|
||
fn main() { | ||
const Y: usize = bar(2); | ||
assert_eq!(Y, 4); | ||
const Z: usize = foo(double, 2); | ||
assert_eq!(Z, 4); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// run-pass | ||
|
||
// FIXME: this should not pass | ||
|
||
#![feature(const_fn)] | ||
#![feature(const_fn_ptr)] | ||
|
||
fn double(x: usize) -> usize { x * 2 } | ||
const X: fn(usize) -> usize = double; | ||
|
||
const fn bar(x: usize) -> usize { | ||
X(x) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @oli-obk this is the issue that we chatted about. Note that I'm not sure how to generate an error in this case. Right now it generates a constant-evaluation error when used in const-context, but it would be nice to generate a better error message. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. XD welcome to RFC territory. This needs an RFC, because we need surface language changes in order to differentiate between callable and not callable function pointers. This is what I meant by "we can do it behind a feature gate for experimentation, but we'll never be able to stabilize it.". For all intents and purposes, this is const unsound just like casting pointers to usize or comparing pointers. The pointer ops have been made unsafe for this reason, so maybe we make this unsafe, too? Idk. Seems all fishy without an RFC but as an experimental unstable feature seems fine There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @oli-obk I've updated the OP with a description of the semantics that this PR implements. I'm not sure why this would be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, that would be one way to do it, it would mean you can't pass any function pointers, because there are no const function pointers. Not compiling is the current semantics and is totally sound. This is all discussed in my RFC and needs its own RFC. I'm 🤧 right now and my brain is mush. I'd prefer not to write out an explanation right now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I see what you mean now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure if we need language syntax for this initially, e.g., we could just add a type that users cannot write, add coercions to it from Either way, the intent of this PR was never to go through all that trouble. |
||
} | ||
|
||
fn main() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
warning: function is never used: `double` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The dead_code warnings are off-topic and shouldn't be here. |
||
--> $DIR/const_fn_ptr_fail.rs:8:1 | ||
| | ||
LL | fn double(x: usize) -> usize { x * 2 } | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: `#[warn(dead_code)]` on by default | ||
|
||
warning: constant item is never used: `X` | ||
--> $DIR/const_fn_ptr_fail.rs:9:1 | ||
| | ||
LL | const X: fn(usize) -> usize = double; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
warning: function is never used: `bar` | ||
--> $DIR/const_fn_ptr_fail.rs:11:1 | ||
| | ||
LL | const fn bar(x: usize) -> usize { | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#![feature(const_fn)] | ||
#![feature(const_fn_ptr)] | ||
|
||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This and Z should not type-check. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the same issue mentioned in the OP and here and should be fixed by fixing that as well. |
||
//~^ ERROR any use of this value will cause an error | ||
|
||
const Z: usize = bar(double, 2); | ||
//~^ ERROR any use of this value will cause an error | ||
|
||
|
||
fn main() { | ||
assert_eq!(Y, 4); | ||
assert_eq!(Z, 4); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
error: any use of this value will cause an error | ||
--> $DIR/const_fn_ptr_fail2.rs:8:5 | ||
| | ||
LL | x(y) | ||
| ^^^^ | ||
| | | ||
| calling non-const function `double` | ||
| inside call to `bar` at $DIR/const_fn_ptr_fail2.rs:11:18 | ||
... | ||
LL | const Y: usize = bar(X, 2); | ||
| --------------------------- | ||
| | ||
= note: `#[deny(const_err)]` on by default | ||
|
||
error: any use of this value will cause an error | ||
--> $DIR/const_fn_ptr_fail2.rs:8:5 | ||
| | ||
LL | x(y) | ||
| ^^^^ | ||
| | | ||
| calling non-const function `double` | ||
| inside call to `bar` at $DIR/const_fn_ptr_fail2.rs:14:18 | ||
... | ||
LL | const Z: usize = bar(double, 2); | ||
| -------------------------------- | ||
|
||
error: aborting due to 2 previous errors | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#![feature(const_fn)] | ||
|
||
fn main() {} | ||
|
||
const fn foo() {} | ||
const X: fn() = foo; | ||
|
||
const fn bar() { | ||
X() | ||
//~^ ERROR function pointers in const fn are unstable | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
error[E0658]: function pointers in const fn are unstable | ||
--> $DIR/feature-gate-const_fn_ptr.rs:9:5 | ||
| | ||
LL | X() | ||
| ^^^ | ||
| | ||
= note: for more information, see https://github.com/rust-lang/rust/issues/51909 | ||
= help: add `#![feature(const_fn_ptr)]` to the crate attributes to enable | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0658`. |
Uh oh!
There was an error while loading. Please reload this page.