Salta ai contenuti

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

E0554 significa: il tuo codice inizia con una riga #![feature(...)], e solo la versione nightly di Rust la accetta. Quasi sempre arriva da codice che hai copiato: un articolo, un repository su GitHub, una risposta di un’IA, una vecchia risposta su Stack Overflow. Quel codice era scritto per Rust nightly, e tu usi la versione stabile, che è quella che rustup installa di default. Nella tua configurazione non c’è niente di sbagliato. Di solito la correzione è cancellare una riga e usare un modo stabile per fare la stessa cosa. (Questa pagina fa parte di Errori del compilatore Rust spiegati.)

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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Il compilatore dice: #![feature] non si può usare sul canale di rilascio stabile. Questo è il programma che produce l’errore:

#![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);
}

Il ^^^ sottolinea tutta la prima riga, #![feature(iter_map_windows)]. Quella riga è una richiesta: «per favore, attiva la funzionalità non ancora finita chiamata iter_map_windows». Solo il compilatore nightly accetta richieste del genere. Lo «stable release channel» (canale di rilascio stabile) nel messaggio è il normale Rust che ottieni da rustup, e lui rifiuta.

Nota di che cosa rustc non si lamenta: map_windows alla riga 5. Si ferma prima alla riga #![feature]. Quando togli quella riga, scoprirai se il resto del codice funziona su stabile.

Ottieni lo stesso errore sul canale beta. Se il tuo codice ha più righe #![feature], di solito rustc segnala solo la prima, quindi controlla se ce ne sono altre in cima al file.

È come un pass «solo personale». La cucina sperimentale (nightly) ti fa entrare con quello. Il ristorante (stabile) non accetta proprio quei pass, per quanto gentilmente tu lo mostri.

Rust promette che il codice che oggi compila su stabile continua a compilare con ogni futura versione stabile 1.x. Le funzionalità non finite non possono far parte di questa promessa: nomi, argomenti e comportamento possono ancora cambiare, o possono essere rimosse. Per questo vivono solo su nightly, una nuova build del compilatore fatta ogni notte, e le attivi una per una per nome con #![feature(...)].

Rust stabile non si limita a ignorare la riga: si ferma con un errore. Così non puoi costruire un progetto su una funzionalità non finita senza accorgertene. Quando una funzionalità è finita, entra in Rust stabile e non ha più bisogno della riga.

Quindi quando vedi E0554 le domande vere sono solo tre: c’è un modo stabile per farlo (soluzione 1), la funzionalità è già stabile (soluzione 2), oppure vuoi davvero nightly (soluzione 3)? Vedi Strumenti Rust e installazione.

Soluzione 1: togli l’attributo e usa l’API stabile

Sezione intitolata “Soluzione 1: togli l’attributo e usa l’API stabile”

Scegli questa quasi sempre. Cancella la riga #![feature] e compila di nuovo. Se adesso ottieni E0658 (use of unstable library feature `iter_map_windows` ), la funzionalità non è ancora finita, e ti serve un modo stabile per fare la stessa cosa. La maggior parte dei metodi instabili sono scorciatoie per qualcosa che Rust stabile sa già fare. Qui .windows(2) su una slice ti dà ogni coppia di elementi vicini:

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

Output:

[3, -2, 5]
18 -> 21
21 -> 19
19 -> 24
▶ Provalo tu

Per trovare il modo stabile, apri il metodo nella documentazione della libreria standard. Gli elementi instabili hanno un riquadro che dice «This is a nightly-only experimental API», e il nome della funzionalità nella tua riga #![feature] di solito corrisponde a una pagina di The Unstable Book (in inglese). Vedi Slice in Rust e Iteratori in Rust.

Soluzione 2: controlla se ora la funzionalità è stabile

Sezione intitolata “Soluzione 2: controlla se ora la funzionalità è stabile”

Scegli questa quando il codice è un po’ vecchio. Molte funzionalità che una volta richiedevano #![feature] ora fanno parte di Rust stabile, e allora la riga semplicemente non serve più. rustc te lo dice in un warning proprio sotto l’errore:

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
| ^^^^^^^^^^^^^^^

Il programma che non compila:

// Copied from an older tutorial
#![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);
}
}

Il warning dice che la funzionalità slice_as_chunks è stabile dalla 1.88.0 e non ha più bisogno di un attributo. Cancella la riga #![feature] (e il commento sopra) e il resto funziona senza modifiche:

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

Output:

r=255 g=0 b=0
r=0 g=128 b=255
▶ Provalo tu

Per le funzionalità del linguaggio, rustc è ancora più diretto e aggiunge help: remove the attribute (togli l’attributo) sotto l’errore, più una riga come the feature `async_closure` has been stable since `1.85.0` and no longer requires an attribute to enable.

Nessun warning, ma sospetti che la funzionalità sia stabile? Forse il tuo Rust è semplicemente più vecchio della versione in cui è diventata stabile. Controlla e aggiorna:

Terminal window
rustc --version
rustup update

Se dopo rustc --version mostra ancora una versione vecchia, probabilmente il progetto ha un file rust-toolchain.toml che la blocca. Vedi Strumenti Rust e installazione.

Scegli questa per ultima, quando non c’è un modo stabile e accetti che il codice si possa rompere con un futuro nightly. Buoni motivi tipici: stai provando una funzionalità nuova, scrivi un piccolo esperimento, oppure il progetto a cui contribuisci usa già nightly. Installa nightly accanto a stabile e usalo per un singolo comando:

Terminal window
rustup toolchain install nightly
cargo +nightly run

Oppure fai usare nightly a tutto il progetto con un file rust-toolchain.toml accanto a Cargo.toml. Allora in quella cartella un semplice cargo run sceglie nightly, e ovunque altrove stabile:

[toolchain]
channel = "nightly"

Per un progetto che compilano anche altre persone, fissa una data, come channel = "nightly-2026-10-01", così tutti hanno lo stesso compilatore. Sul Rust Playground, scegli Nightly nel menu della toolchain.

Potresti trovare il consiglio di impostare RUSTC_BOOTSTRAP=1 per far accettare #![feature] a stabile. Quell’interruttore esiste per compilare il compilatore Rust stesso. Usarlo ti dà tutti i rischi di nightly facendo finta di essere su stabile, quindi non farlo.

Benchmark con #[bench]. Le guide vecchie scrivono i benchmark così, e #![feature(test)] funziona ancora solo su 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
| ^^^^^^^^^^^^^^^^^
//! Price helpers.
//! Benchmark written the old way, for nightly Rust.
#![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]));
}

Correzione: usa un crate per i benchmark che funziona su stabile, come criterion o divan, ed esegui cargo bench. Qui non basta cancellare solo la riga #![feature]: poi extern crate test; dà E0658 (use of unstable library feature `test` ). Vedi Prestazioni in Rust.

Una dipendenza che richiede nightly. Se la riga --> indica un crate dentro ~/.cargo/registry/ invece del tuo src/, è un crate da cui dipendi che usa #![feature]. Correzione: controlla il README del crate; spesso una versione più recente funziona su stabile (per esempio, il framework web Rocket richiedeva nightly fino alla 0.4, e la 0.5 gira su stabile). Altrimenti scegli un altro crate. Vedi Cargo e crate in Rust.

Codice copiato con #![feature(let_chains)]. Le let chain (if let Some(x) = a && x > 0) sono diventate stabili in Rust 1.88, ma solo nell’edizione 2024. Correzione: cancella la riga (soluzione 2) e imposta edition = "2024" in Cargo.toml. Senza, ottieni let chains are only allowed in Rust 2024 or later.

Verifica veloce

1. Incolli del codice che inizia con #![feature(try_blocks)] e ottieni E0554. Che cosa significa?

2. Sotto l'errore, rustc avverte che la funzionalità è stabile dalla 1.88.0. Che cosa dovresti fare?

3. Vuoi davvero nightly per un esperimento. Qual è il modo più pulito?

Punteggio: 0 / 3