跳转到内容

Rust 错误 E0554:#![feature] may not be used on the stable release channel(稳定版不能用)

E0554 的意思是:你的代码开头有一行 #![feature(...)],而只有 nightly 版的 Rust 才接受这种写法。 它几乎总是来自你复制的代码:博客文章、GitHub 仓库、AI 的回答、一条老旧的 Stack Overflow 回复。那些代码是为 nightly Rust 写的,而你用的是稳定版(stable),也就是 rustup 默认安装的版本。你的环境没有任何问题。修复通常是删掉一行,再用一种稳定的写法做同样的事。这个系列的其他错误,请看 Rust 编译错误详解。

error[E0554]: `#![feature]` may not be used on the stable release channel
--> src/main.rs:1:1
|
1 | #![feature(iter_map_windows)] // ❌ 从为 nightly Rust 写的代码里复制来的
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

第一行的意思是“#![feature] 不能在稳定版发布渠道上使用”。

产生这个错误的程序是这样的:

#![feature(iter_map_windows)] // ❌ 从为 nightly Rust 写的代码里复制来的
fn main() {
let temps = [18, 21, 19, 24];
let changes: Vec<i32> = temps.iter().map_windows(|[a, b]| *b - *a).collect();
println!("{:?}", changes);
}

^^^ 划出了整个第一行 #![feature(iter_map_windows)]。这一行是一个请求:“请打开那个叫 iter_map_windows 的未完成特性。”只有 nightly 编译器接受这种请求。错误信息里的“stable release channel”(稳定版发布渠道)就是你用 rustup 装的普通 Rust,它会拒绝这个请求。

注意 rustc 没有抱怨的地方:第 5 行的 map_windows。它在 #![feature] 这一行就先停下了。等你删掉这一行,才会知道剩下的代码能不能在稳定版上运行。

在 beta 渠道上你也会得到同样的错误。如果代码里有好几行 #![feature],rustc 通常只报告第一行,所以要检查一下文件顶部还有没有别的。

就像一张“员工专用”通行证。试验厨房(nightly)凭它就能进去。而餐厅(stable)根本不认这种通行证,不管你出示得多客气。

Rust 承诺:今天能在稳定版上编译的代码,在以后每一个 1.x 稳定版上也都能编译。未完成的特性不可能纳入这个承诺:它们的名字、参数和行为都还可能改变,甚至可能被删掉。所以它们只存在于 nightly 里,nightly 是每晚都会重新构建的编译器,而你要用 #![feature(...)] 按名字逐个打开它们。

稳定版 Rust 并不会默默忽略这一行,而是报错停下。这样你就不会在不知不觉中把项目建立在一个未完成的特性上。等某个特性完成后,它就成了稳定版 Rust 的一部分,再也不需要这一行了。

所以看到 E0554 时,真正要问的只有三个问题:有没有稳定的写法(修复 1)?这个特性是不是已经稳定了(修复 2)?你是不是真的想用 nightly(修复 3)?参见 stable、beta 和 nightly。

修复 1:删掉这个属性,改用稳定的 API

Section titled “修复 1:删掉这个属性,改用稳定的 API”

几乎每次都选这个。删掉 #![feature] 这一行,然后重新编译。如果现在得到 E0658(use of unstable library feature `iter_map_windows` ),说明这个特性还没完成,你需要一种稳定的写法来做同样的事。大多数不稳定的方法只是捷径,稳定版 Rust 早就能做到同样的事。这里,在 slice 上调用 .windows(2) 就能拿到每一对相邻的元素:

fn main() {
let temps = [18, 21, 19, 24];
let changes: Vec<i32> = temps.windows(2).map(|w| w[1] - w[0]).collect(); // ✅ 稳定版可用
println!("{:?}", changes);
for w in temps.windows(2) {
println!("{} -> {}", w[0], w[1]);
}
}

输出:

[3, -2, 5]
18 -> 21
21 -> 19
19 -> 24
▶ 动手试一试

要找到稳定的写法,就在标准库文档里打开这个方法。不稳定的条目有一个框,写着“This is a nightly-only experimental API”(这是只有 nightly 才有的实验性 API),而你 #![feature] 行里的特性名,通常能在 The Unstable Book(英文)里找到对应的页面。参见 slice 和迭代器。

修复 2:检查这个特性现在是不是已经稳定了

Section titled “修复 2:检查这个特性现在是不是已经稳定了”

当代码有点年头时,选这个。很多曾经需要 #![feature] 的特性如今已经是稳定版 Rust 的一部分,这时这一行就根本不需要了。rustc 会在错误下面紧接着用一条警告告诉你:

error[E0554]: `#![feature]` may not be used on the stable release channel
--> src/main.rs:2:1
|
2 | #![feature(slice_as_chunks)] // ❌ 已经不需要了:这个特性现在是稳定的
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: the feature `slice_as_chunks` has been stable since 1.88.0 and no longer requires an attribute to enable
--> src/main.rs:2:12
|
2 | #![feature(slice_as_chunks)] // ❌ 已经不需要了:这个特性现在是稳定的
| ^^^^^^^^^^^^^^^

警告的意思是:“slice_as_chunks 这个特性从 1.88.0 起就已经稳定了,不再需要用属性来打开”。

出错的程序:

// 从一篇旧教程里复制来的
#![feature(slice_as_chunks)] // ❌ 已经不需要了:这个特性现在是稳定的
fn main() {
let pixels = [255, 0, 0, 0, 128, 255];
let (rgb, _rest) = pixels.as_chunks::<3>();
for [r, g, b] in rgb {
println!("r={} g={} b={}", r, g, b);
}
}

删掉 #![feature] 这一行(以及它上面的注释),剩下的代码不用改就能运行:

fn main() {
let pixels = [255, 0, 0, 0, 128, 255];
let (rgb, _rest) = pixels.as_chunks::<3>(); // ✅ 从 Rust 1.88 起就是稳定的
for [r, g, b] in rgb {
println!("r={} g={} b={}", r, g, b);
}
}

输出:

r=255 g=0 b=0
r=0 g=128 b=255
▶ 动手试一试

对于语言特性,rustc 说得更直接:它会在错误下面加上 help: remove the attribute(删掉这个属性),以及类似 the feature `async_closure` has been stable since `1.85.0` and no longer requires an attribute to enable 的一行。

没有警告,但你怀疑这个特性已经稳定了?可能只是你的 Rust 比它变成稳定的那个版本还老。查看版本并升级:

Terminal window
rustc --version
rustup update

如果之后 rustc --version 显示的仍然是旧版本,项目里多半有一个 rust-toolchain.toml 文件把版本固定住了。参见为单个项目固定工具链。

最后才选这个:没有稳定的写法,而且你能接受代码在将来某个 nightly 上失效。典型的正当理由有:你想试用一个新特性、在写一个小实验,或者你参与的项目本来就用 nightly。在稳定版旁边装一个 nightly,只在某条命令里用它:

Terminal window
rustup toolchain install nightly
cargo +nightly run

或者在 Cargo.toml 旁边放一个 rust-toolchain.toml 文件,让整个项目都用 nightly。这样在这个文件夹里,普通的 cargo run 就会用 nightly,而在其他地方仍然用稳定版:

[toolchain]
channel = "nightly"

如果别人也要构建这个项目,就固定一个日期,比如 channel = "nightly-2026-10-01",这样大家用的都是同一个编译器。在 Rust Playground 上,在工具链菜单里选择 Nightly 即可。

你可能会看到有人建议设置 RUSTC_BOOTSTRAP=1,让稳定版也接受 #![feature]。这个开关是为构建 Rust 编译器本身准备的。用了它,你承担着 nightly 的所有风险,却假装自己在用稳定版,所以别这么做。

用 #[bench] 写的基准测试。 老教程会这样写基准测试,而 #![feature(test)] 至今仍然只有 nightly 才能用:

error[E0554]: `#![feature]` may not be used on the stable release channel
--> src/main.rs:3:1
|
3 | #![feature(test)] // ❌ 内置的基准测试只有 nightly 才有
| ^^^^^^^^^^^^^^^^^
//! 价格相关的辅助函数。
//! 基准测试用的是老写法,只能在 nightly Rust 上运行。
#![feature(test)] // ❌ 内置的基准测试只有 nightly 才有
extern crate test;
fn total(prices: &[u32]) -> u32 {
prices.iter().sum()
}
#[bench]
fn bench_total(b: &mut test::Bencher) {
let prices: Vec<u32> = (1..1000).collect();
b.iter(|| total(&prices));
}
fn main() {
println!("{}", total(&[3, 4, 5]));
}

修复:改用能在稳定版上运行的基准测试 crate,比如 criterion 或 divan,然后运行 cargo bench。这里只删掉 #![feature] 这一行还不够:接下来 extern crate test; 会报 E0658(use of unstable library feature `test` )。参见性能。

依赖的 crate 需要 nightly。 如果 --> 那一行指向的是 ~/.cargo/registry/ 下的某个 crate,而不是你自己的 src/,那就是你依赖的某个 crate 用了 #![feature]。修复:看看这个 crate 的 README;通常更新的版本就能在稳定版上运行(比如 Rocket 这个 Web 框架在 0.4 及以前需要 nightly,而 0.5 可以在稳定版上运行)。否则就换一个 crate。参见 Cargo 和 crate。

复制来的代码里有 #![feature(let_chains)]。 let 链(if let Some(x) = a && x > 0)在 Rust 1.88 变成了稳定的,但只能用在 2024 版次(edition)里。修复:删掉这一行(修复 2),并在 Cargo.toml 里设置 edition = "2024"。不这样做的话,你会得到 let chains are only allowed in Rust 2024 or later(let 链只能在 Rust 2024 或更新的版次中使用)。

小测验

1. 你粘贴了一段以 #![feature(try_blocks)] 开头的代码,结果得到 E0554。这是什么意思?

2. 在错误下面,rustc 警告说这个特性从 1.88.0 起就已经稳定了。你应该怎么做?

3. 你确实想在一个实验里用 nightly。最干净的做法是什么?

得分: 0 / 3