这是预期行为还是编译器错误?
以下代码无法编译。 MyStruct
中的 values
是一个 Option
因为 Vec::new
不是 const fn - 而是 Option::None
是常量(但它仍然无法编译)。
type MyFun = fn(input: u32) -> u32;
struct MyStruct {
values: Option<Vec<MyFun>>,
}
impl MyStruct {
pub const fn init() -> Self {
Self { values: None }
}
}
fn main() {
MyStruct::init();
}
error[E0723]: function pointers in const fn are unstable
--> src/main.rs:9:24
|
9 | Self { values: None }
| ^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
使用新类型(Wrapped
)解决了这个问题。这感觉很奇怪,因为两个示例是相同的(至少生成的二进制文件应该是相同的)。这种行为是故意的还是错误?
这个有效:
type MyFun = fn(input: u32) -> u32;
struct Wrapped(Vec<MyFun>);
struct MyStruct {
values: Option<Wrapped>,
}
impl MyStruct {
pub const fn init() -> Self {
Self { values: None }
}
}
fn main() {
MyStruct::init();
}
最佳答案
TLDR:一个错误,但不是您所暗示的错误。我们过于积极地为 const fn 的 future 功能敞开大门。
您遇到的错误是为了防止用户编写如下函数而创建的
const fn foo(f: fn()) {}
因为不可能使用f
以可调用的方式。以下功能目前是非法的。
const fn foo(f: fn()) { f() }
稳定时const fn
我们不确定它是否应该合法,所以我们先发制人地禁止 fn
const fn
中的指针.在 const fn 中创建函数指针也是如此。所以
const fn foo() {
let f: fn() = some_function;
}
是禁止的,因为我们想为允许而敞开大门
const fn foo() {
let f: fn() = some_function;
f();
}
如果你扩展你的用例代码,你会得到类似的东西
pub const fn init() -> Self {
let values: Option<fn(u32) -> u32> = None;
Self { values }
}
你是对的,这是一个错误。虽然不是由于包装和非包装版本之间的差异,但因为 None
从来没有真正创建一个函数指针。我们只是决定在检查中过于激进,以免错过任何东西。在这里创建更好的分析绝对是可能的,尽管我们可能只想在 const fn 中实现函数指针。
包装和非包装版本之间存在差异的原因是我们希望允许
const fn foo(f: fn()) { f() }
但不是
const fn foo(wrapper: Wrapper) { (wrapper.f)() }
因为后者在 API 中没有显示函数指针,所以我们不能做任何魔术来确保函数指针指向一个 const fn。
包装版本和非包装版本之间的区别可能令人困惑,足以迫使我们放弃我们可以调用 fn
的想法。 const fn 中的指针如上所述,并为 fn
提出了一个新方案。 const fn 中的指针。
关于rust - 为什么我会收到错误 "function pointers in const fn are unstable",但在用新类型包装后它会消失?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62440982/