Ir al contenido

Error E0554 de Rust: #![feature] may not be used on the stable release channel

E0554 significa que tu código empieza con una línea #![feature(...)], y solo la versión nightly de Rust acepta esas líneas. Casi siempre te pasa con código copiado: de un artículo de un blog, de un repositorio de GitHub, de una respuesta de una IA o de una respuesta antigua de Stack Overflow. Ese código se escribió para Rust nightly, y tú estás en stable (estable), que es lo que rustup instala por defecto. Tu instalación está bien. La solución suele ser borrar una línea y hacer lo mismo de una forma estable. Forma parte de la guía de errores del compilador.

error[E0554]: `#![feature]` may not be used on the stable release channel
--> src/main.rs:1:1
|
1 | #![feature(iter_map_windows)] // ❌ copied from code written for nightly Rust
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

“#![feature] may not be used on the stable release channel” quiere decir “#![feature] no se puede usar en el canal de versiones estables”.

Este es el programa que lo produce:

#![feature(iter_map_windows)] // ❌ copied from code written for 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);
}

Los ^^^ subrayan toda la primera línea, #![feature(iter_map_windows)]. Esa línea es una petición: “por favor, activa la funcionalidad sin terminar llamada iter_map_windows”. Solo el compilador nightly acepta estas peticiones. El “stable release channel” del mensaje es el Rust normal que obtienes con rustup, y se niega.

Fíjate en lo que rustc no dice: no se queja de map_windows en la línea 5. Se detiene antes, en la línea #![feature]. Cuando quites esa línea, sabrás si el resto del código funciona en estable.

En el canal beta obtienes el mismo error. Si tu código tiene varias líneas #![feature], rustc suele mostrar solo la primera, así que revisa el principio del archivo por si hay más.

Es como un pase de “solo personal”. La cocina de pruebas (nightly) te deja entrar con él. El restaurante (stable) no acepta esos pases, por muy amablemente que lo enseñes.

Rust promete que el código que compila hoy en estable seguirá compilando en todas las futuras versiones estables 1.x. Las funcionalidades sin terminar no pueden formar parte de esa promesa: sus nombres, sus argumentos y su comportamiento todavía pueden cambiar, o pueden desaparecer. Por eso solo viven en nightly, una versión nueva del compilador que se genera cada noche, y cada una se activa por su nombre con #![feature(...)].

Rust estable no ignora la línea sin más: se detiene con un error. Así no puedes construir un proyecto sobre una funcionalidad sin terminar sin darte cuenta. Cuando una funcionalidad está terminada, pasa a formar parte de Rust estable y ya no necesita esa línea.

Así que cuando veas E0554, solo hay tres preguntas de verdad: ¿hay una forma estable de hacer esto (Solución 1)?, ¿la funcionalidad ya es estable (Solución 2)?, ¿o de verdad quieres nightly (Solución 3)? Mira Stable, beta y nightly.

Solución 1: Quita el atributo y usa la API estable

Sección titulada «Solución 1: Quita el atributo y usa la API estable»

Elige esta casi siempre. Borra la línea #![feature] y vuelve a compilar. Si ahora obtienes E0658 (use of unstable library feature `iter_map_windows` , uso de una funcionalidad inestable de la biblioteca), la funcionalidad todavía no está terminada, y necesitas una forma estable de hacer lo mismo. La mayoría de los métodos inestables son atajos para algo que Rust estable ya sabe hacer. Aquí, .windows(2) sobre un slice te da cada pareja de vecinos:

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

Salida:

[3, -2, 5]
18 -> 21
21 -> 19
19 -> 24
▶ Pruébalo tú mismo

Para encontrar la forma estable, abre el método en la documentación de la biblioteca estándar. Los elementos inestables tienen un recuadro que dice “This is a nightly-only experimental API” (esta es una API experimental solo de nightly), y el nombre de tu línea #![feature] suele coincidir con una página de The Unstable Book (en inglés). Mira Slices e Iteradores.

Solución 2: Comprueba si la funcionalidad ya es estable

Sección titulada «Solución 2: Comprueba si la funcionalidad ya es estable»

Elige esta cuando el código es algo antiguo. Muchas funcionalidades que antes necesitaban #![feature] ahora forman parte de Rust estable, y entonces la línea simplemente ya no hace falta. rustc te lo dice en un aviso (warning) justo debajo del error:

error[E0554]: `#![feature]` may not be used on the stable release channel
--> src/main.rs:2:1
|
2 | #![feature(slice_as_chunks)] // ❌ not needed any more: this feature is stable now
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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)] // ❌ not needed any more: this feature is stable now
| ^^^^^^^^^^^^^^^

El aviso dice que la funcionalidad slice_as_chunks es estable desde la versión 1.88.0 y ya no necesita un atributo para activarse. El programa con el error:

// Copiado de un tutorial antiguo
#![feature(slice_as_chunks)] // ❌ not needed any more: this feature is stable now
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);
}
}

Borra la línea #![feature] (y el comentario de encima) y el resto funciona sin cambios:

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

Salida:

r=255 g=0 b=0
r=0 g=128 b=255
▶ Pruébalo tú mismo

Con las funcionalidades del lenguaje, rustc es todavía más directo y añade help: remove the attribute (quita el atributo) debajo del error, además de una línea como the feature `async_closure` has been stable since `1.85.0` and no longer requires an attribute to enable.

¿No hay ningún aviso, pero sospechas que la funcionalidad es estable? Puede que tu Rust sea más antiguo que la versión en la que se estabilizó. Compruébalo y actualiza:

Terminal window
rustc --version
rustup update

Si después rustc --version sigue mostrando una versión antigua, probablemente el proyecto tiene un archivo rust-toolchain.toml que la fija. Mira Fijar una toolchain para un proyecto.

Elige esta en último lugar, cuando no hay una forma estable y aceptas que tu código puede romperse con un nightly futuro. Buenas razones típicas: estás probando una funcionalidad nueva, escribes un pequeño experimento o el proyecto en el que colaboras ya usa nightly. Instala nightly junto a stable y úsalo para un solo comando:

Terminal window
rustup toolchain install nightly
cargo +nightly run

O haz que todo el proyecto use nightly con un archivo rust-toolchain.toml junto a Cargo.toml. Entonces un simple cargo run elige nightly en esa carpeta, y stable en todas las demás:

[toolchain]
channel = "nightly"

Para un proyecto que también compilan otras personas, fija una fecha, como channel = "nightly-2026-10-01", para que todos usen el mismo compilador. En el Rust Playground, elige Nightly en el menú de toolchain.

Puede que encuentres el consejo de poner RUSTC_BOOTSTRAP=1 para que stable acepte #![feature]. Ese interruptor existe para compilar el propio compilador de Rust. Usarlo te da todos los riesgos de nightly mientras finges estar en estable, así que no lo hagas.

Benchmarks con #[bench]. Las guías antiguas escriben los benchmarks (pruebas de rendimiento) así, y #![feature(test)] sigue siendo solo de nightly:

error[E0554]: `#![feature]` may not be used on the stable release channel
--> src/main.rs:3:1
|
3 | #![feature(test)] // ❌ built-in benchmarks are nightly-only
| ^^^^^^^^^^^^^^^^^
//! Funciones auxiliares para precios.
//! Benchmark escrito a la antigua, para Rust nightly.
#![feature(test)] // ❌ built-in benchmarks are nightly-only
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]));
}

Solución: usa un crate de benchmarks que funcione en estable, como criterion o divan, y ejecuta cargo bench. Aquí no basta con borrar la línea #![feature]: entonces extern crate test; da E0658 (use of unstable library feature `test` ). Mira Rendimiento.

Una dependencia que necesita nightly. Si la línea --> apunta a un crate dentro de ~/.cargo/registry/ en lugar de a tu propio src/, es un crate del que dependes el que usa #![feature]. Solución: mira el README del crate; muchas veces una versión más nueva funciona en estable (por ejemplo, el framework web Rocket necesitaba nightly hasta la 0.4, y la 0.5 funciona en estable). Si no, elige otro crate. Mira Cargo y crates.

Código copiado con #![feature(let_chains)]. Las let chains (if let Some(x) = a && x > 0) se estabilizaron en Rust 1.88, pero solo en la edición 2024. Solución: borra la línea (Solución 2) y pon edition = "2024" en Cargo.toml. Si no, obtienes let chains are only allowed in Rust 2024 or later (las let chains solo se permiten en Rust 2024 o posterior).

Comprueba lo aprendido

1. Pegas un código que empieza con #![feature(try_blocks)] y obtienes E0554. ¿Qué significa?

2. Debajo del error, rustc avisa de que la funcionalidad es estable desde la 1.88.0. ¿Qué deberías hacer?

3. Sí quieres nightly para un experimento. ¿Cuál es la forma más limpia?

Puntuación: 0 / 3