Rust-Fehler E0658: use of unstable library feature (nur mit Nightly)
E0658 bedeutet: Du hast etwas benutzt, das es in Rust zwar gibt, das aber noch nicht fertig ist, deshalb lässt dich stabiles Rust es nicht benutzen. Meistens ist es eine Methode, die du in der Doku der Standardbibliothek oder in einem Blogartikel gefunden hast, wie .intersperse() oder .try_collect(), oder ein Stück Syntax wie try { ... }. Dein Code ist nicht falsch, und auf deinem Rechner ist nichts kaputt. Du hast nur zu einem Feature gegriffen, das ausschließlich mit dem Nightly-Compiler funktioniert. Fast immer gibt es einen stabilen Weg, der dasselbe in einer Zeile erledigt. (Diese Seite gehört zur Reihe Rust-Compilerfehler einfach erklärt.)
Die Fehlermeldung
Abschnitt betitelt „Die Fehlermeldung“error[E0658]: use of unstable library feature `iter_intersperse` --> src/main.rs:3:47 |3 | let joined: String = tags.iter().copied().intersperse(", ").collect(); // ❌ Methode nur für Nightly | ^^^^^^^^^^^ | = note: see issue #79524 <https://github.com/rust-lang/rust/issues/79524> for more informationAuf Deutsch: „Benutzung des instabilen Library-Features iter_intersperse.“ Die note verweist auf das Issue #79524, in dem du mehr darüber liest.
Dieses Programm erzeugt den Fehler:
fn main() { let tags = ["rust", "web", "cli"]; let joined: String = tags.iter().copied().intersperse(", ").collect(); // ❌ Methode nur für Nightly println!("{}", joined);}Was sie bedeutet
Abschnitt betitelt „Was sie bedeutet“Die ^^^^^^^^^^^ zeigen in Zeile 3 auf intersperse. Die Überschrift nennt in Backticks den Namen des Features, iter_intersperse. Unter diesem Namen führt das Rust-Team dieses unfertige Stück der Standardbibliothek. Die note: verlinkt das GitHub-Issue, in dem über das Feature diskutiert wird.
rustc hat die Methode also gefunden. Er weiß genau, was du meinst. Er kompiliert sie nur nicht, weil intersperse noch als instabil markiert ist: Name, Argumente oder Verhalten können sich ändern, bevor sie fertig ist, oder sie wird wieder entfernt.
Andere Formen der Überschrift bedeuten dasselbe, nur für Sprach-Features statt Library-Features: the `!` type is experimental (der Typ ! ist experimentell), `try` expression is experimental (der try-Ausdruck ist experimentell) oder associated type defaults are unstable (Standardwerte für assoziierte Typen sind instabil).
Das ist wie ein Laden, in dem ein neues Produkt im Regal steht, mit dem Aufkleber „Nur für Personal, noch im Test“. Du siehst es, du kannst das Etikett lesen, aber die Kasse verkauft es dir noch nicht.
Warum Rust das macht
Abschnitt betitelt „Warum Rust das macht“Rust gibt ein starkes Versprechen: Code, der heute auf stabilem Rust kompiliert, kompiliert auch auf jedem zukünftigen stabilen Rust 1.x. Um das zu halten, landen neue Features zuerst im Nightly-Kanal, wo Leute sie ausprobieren können und sich das Design noch ändern darf. Erst wenn ein Feature fertig ist, wird es stabil, meistens nach Monaten oder Jahren des Testens.
Stabiles Rust kompiliert instabile Features überhaupt nicht, damit du nicht auf etwas aufbaust, das sich unter dir ändern könnte. Willst du eins wirklich ausprobieren, kannst du es in Nightly mit #![feature(iter_intersperse)] über seinen Namen einschalten. Auf Stable ist schon diese Zeile ein Fehler (E0554).
Die Doku der Standardbibliothek zeigt beide Arten nebeneinander. Stabile Elemente haben rechts eine Versionsnummer, etwa 1.82.0: die Rust-Version, in der sie stabil wurden. Instabile Elemente haben einen Kasten mit „🔬 This is a nightly-only experimental API.“ (Das ist eine experimentelle API nur für Nightly.) An diesem Kasten erkennst du ein E0658 am schnellsten, noch bevor du eine Zeile Code schreibst. Unter Rust-Werkzeuge und Einrichtung siehst du, wie die Kanäle von Rust und rustup zusammenhängen.
So behebst du den Fehler
Abschnitt betitelt „So behebst du den Fehler“Lösung 1: Die stabile Alternative benutzen
Abschnitt betitelt „Lösung 1: Die stabile Alternative benutzen“Nimm diese Lösung fast immer. Instabile Methoden sind meistens Abkürzungen für etwas, das stabiles Rust schon kann. Um Zeichenketten mit einem Trennzeichen zusammenzukleben, macht join auf einem Slice oder einem Vec dasselbe wie intersperse(...).collect():
fn main() { let tags = ["rust", "web", "cli"]; let joined = tags.join(", "); println!("{}", joined);
// Strings aus einem Iterator: erst in einen Vec sammeln, dann join. let upper: Vec<String> = tags.iter().map(|t| t.to_uppercase()).collect(); println!("{}", upper.join(" | "));}Ausgabe:
rust, web, cliRUST | WEB | CLIWillst du lieber alles in einer Iterator-Kette lassen, hat das beliebte Crate itertools ein stabiles join und intersperse für Iteratoren. Siehe Strings und Iteratoren.
Lösung 2: In der Doku nach dem „nightly-only“-Kasten schauen
Abschnitt betitelt „Lösung 2: In der Doku nach dem „nightly-only“-Kasten schauen“Nimm diese Lösung, wenn du eine Methode aus der Doku, einer KI-Antwort oder einem Blogartikel kopiert hast. Öffne die Methode in der Doku der Standardbibliothek: Hat sie den 🔬-Kasten, such ein bisschen weiter nach dem stabilen Weg. Ein häufiger Fall ist .try_collect():
error[E0658]: use of unstable library feature `iterator_try_collect` --> src/main.rs:3:80 |3 | let numbers: Result<Vec<i32>, _> = inputs.iter().map(|s| s.parse::<i32>()).try_collect(); // ❌ nur Nightly | ^^^^^^^^^^^ | = note: see issue #94047 <https://github.com/rust-lang/rust/issues/94047> for more informationDieselbe Meldung wie oben, diesmal für das Feature iterator_try_collect.
Das fehlerhafte Programm:
fn main() { let inputs = ["3", "14", "x"]; let numbers: Result<Vec<i32>, _> = inputs.iter().map(|s| s.parse::<i32>()).try_collect(); // ❌ nur Nightly println!("{:?}", numbers);}Stabiles Rust schafft das schon mit einem einfachen collect(). Sind die Elemente Results und sammelst du sie in ein Result<Vec<_>, _>, bekommst du Ok mit allen Werten oder den ersten Err:
use std::num::ParseIntError;
fn parse_all(inputs: &[&str]) -> Result<Vec<i32>, ParseIntError> { inputs.iter().map(|s| s.parse::<i32>()).collect()}
fn main() { println!("{:?}", parse_all(&["3", "14", "15"])); println!("{:?}", parse_all(&["3", "x", "15"]));}Ausgabe:
Ok([3, 14, 15])Err(ParseIntError { kind: InvalidDigit })Weitere instabile Methoden, denen du begegnen kannst, mit dem stabilen Weg: .array_chunks() auf einem Iterator (iter_array_chunks; nimm stattdessen .as_chunks() oder .chunks() auf einem Slice) und .map_windows() (nimm .windows() auf einem Slice). Siehe Result und Slices.
Lösung 3: Rust aktualisieren, wenn das Feature erst kürzlich stabil wurde
Abschnitt betitelt „Lösung 3: Rust aktualisieren, wenn das Feature erst kürzlich stabil wurde“Nimm diese Lösung, wenn die Doku eine Versionsnummer statt des 🔬-Kastens zeigt oder derselbe Code bei einer Freundin oder im Playground kompiliert. Dann ist das Feature stabil, nur neuer als dein Compiler. Zum Beispiel wurde as_chunks für Slices in Rust 1.88 stabil. Auf einem älteren Rust bekämst du dafür E0658; auf einem aktuellen funktioniert es einfach:
fn main() { let readings = [21, 22, 19, 20, 23]; let (pairs, rest) = readings.as_chunks::<2>(); for [a, b] in pairs { println!("{} und {}", a, b); } println!("übrig: {:?}", rest);}Ausgabe:
21 und 2219 und 20übrig: [23]Prüf deine Version und aktualisiere:
rustc --versionrustup updateZeigt rustc --version danach immer noch eine alte Version, dann such in deinem Projekt nach einer Datei rust-toolchain.toml. Sie legt das Projekt auf eine bestimmte Rust-Version fest, und rustup show sagt dir, welche gerade aktiv ist. Siehe Rust-Werkzeuge und Einrichtung.
Lösung 4: Mit #![feature] auf Nightly umsteigen – nur, wenn du es wirklich willst
Abschnitt betitelt „Lösung 4: Mit #![feature] auf Nightly umsteigen – nur, wenn du es wirklich willst“Nimm diese Lösung zuletzt, und nur dann, wenn es keine stabile Alternative gibt und es dir nichts ausmacht, dass dein Code mit einem zukünftigen Nightly kaputtgehen kann. Du brauchst zwei Dinge: eine Zeile #![feature(...)] ganz oben in main.rs (oder lib.rs) mit dem Feature-Namen aus der Fehlermeldung, und den Nightly-Compiler. Auf Stable wird schon die #![feature]-Zeile abgelehnt:
error[E0554]: `#![feature]` may not be used on the stable release channel --> src/main.rs:1:1 |1 | #![feature(iter_intersperse)] // ❌ nur mit Nightly-Rust erlaubt | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Auf Deutsch: „#![feature] darf im stabilen Release-Kanal nicht benutzt werden.“
Das Programm, das nur mit Nightly baut:
#![feature(iter_intersperse)] // ❌ nur mit Nightly-Rust erlaubt
fn main() { let tags = ["rust", "web", "cli"]; let joined: String = tags.iter().copied().intersperse(", ").collect(); println!("{}", joined);}Installiere Nightly neben deinem stabilen Rust und benutze es nur für dieses Projekt oder diesen einen Befehl:
rustup toolchain install nightlycargo +nightly runSei hier ehrlich zu dir. Zum Lernen, für Tests und kleine Tools ist Nightly in Ordnung. Für eine Library, von der andere abhängen, oder für alles, was du pflegen musst, bleib bei Stable – das tun auch die meisten Crates, die du benutzt.
Wo du ihn oft siehst
Abschnitt betitelt „Wo du ihn oft siehst“Vec<i32, i32>, obwohl du eine Liste von Paaren meintest. Der zweite Parameter von Vec ist der Speicher-Allocator, und der ist instabil. Deshalb geht es im ersten Fehler um allocator_api (danach folgen noch ein paar weitere Fehler):
error[E0658]: use of unstable library feature `allocator_api` --> src/main.rs:2:26 |2 | let points: Vec<i32, i32> = vec![]; // ❌ gemeint war eine Liste von (x, y)-Paaren | -----^^^ | | | help: consider wrapping the inner types in tuple: `(i32, i32)`Die Hilfe sagt: „Pack die inneren Typen in ein Tupel: (i32, i32).“
fn main() { let points: Vec<i32, i32> = vec![]; // ❌ gemeint war eine Liste von (x, y)-Paaren println!("{} points", points.len());}Lösung: Mach, was die Hilfe sagt, Vec<(i32, i32)>. Siehe Vektoren und Tupel. Derselbe Fehler bei Option oder Result ist E0107.
Der Typ ! in deinen eigenen Signaturen. ! bedeutet „passiert nie“. Als Rückgabetyp einer Funktion, die nie zurückkehrt, funktioniert er, überall sonst ist er noch instabil:
error[E0658]: the `!` type is experimental --> src/main.rs:1:34 |1 | fn default_port() -> Result<u16, !> { // ❌ der Typ `!` geht hier nur mit Nightly | ^Auf Deutsch: „Der Typ ! ist experimentell.“
fn default_port() -> Result<u16, !> { // ❌ der Typ `!` geht hier nur mit Nightly Ok(8080)}
fn main() { println!("{:?}", default_port());}Lösung: Nimm std::convert::Infallible, den stabilen Typ für „dieser Fehler kann nicht auftreten“, oder gib einfach u16 zurück, wenn nichts schiefgehen kann.
try-Blöcke. Mit einem try { ... }-Block kannst du ? benutzen, ohne eine Funktion zu schreiben, aber er geht nur mit Nightly (`try` expression is experimental). Lösung: Verschieb den Code in eine kleine Funktion, die Result zurückgibt, und benutze dort ?, wie in Lösung 2. Siehe Result.
Verwandt, aber nicht E0658: Code für die Edition 2024, etwa if let Some(a) = age && a >= 18, ergibt in einer älteren Edition let chains are only allowed in Rust 2024 or later (Let-Ketten gibt es erst ab Rust 2024). Lösung: Setz edition = "2024" in Cargo.toml, oder verschachtle die beiden ifs.
Verwandte Fehler
Abschnitt betitelt „Verwandte Fehler“- E0554:
#![feature]may not be used on the stable release channel – der Folgefehler, wenn du Lösung 4 auf Stable versuchst. - E0599: no method found; den bekommst du stattdessen, wenn es die Methode gar nicht gibt (oder sie aus einem Crate kommt, das du nicht hinzugefügt hast).
- E0107: wrong number of generic arguments, etwa
Option<i32, i32>(der Verwandte des FallsVec<i32, i32>). - E0277: trait bound not satisfied; einer der Fehler, die auf
Vec<i32, i32>folgen. - E0463: can’t find crate, wenn du auf
itertoolsumsteigst und vergisst, es inCargo.tomleinzutragen. - Alle Compilerfehler: die vollständige Liste der Fehlerseiten.
Kurzer Check
Abschnitt betitelt „Kurzer Check“Kurzer Check
1. Die Doku einer Methode zeigt einen Kasten „This is a nightly-only experimental API“. Was passiert, wenn du sie auf stabilem Rust aufrufst?
2. .try_collect() ergibt E0658. Was ist der übliche stabile Weg, einen Iterator von Results in ein Result<Vec<_>, _> zu verwandeln?
3. Code, der im Playground kompiliert, gibt dir E0658 für eine Methode, deren Doku 1.88.0 zeigt. Was probierst du zuerst?
Punkte: 0 / 3
Weiterlesen
Abschnitt betitelt „Weiterlesen“- E0658 – Rust error codes index (auf Englisch): die offizielle Erklärung, und wie eine
#![feature]-Zeile ein Feature in Nightly einschaltet. - Anhang G: Wie Rust erstellt wird und „nightly Rust“ – Das Rust-Buch: Stable, Beta und Nightly, der Release-Zug und wie instabile Features stabil werden.
- Channels – The rustup book (auf Englisch): Nightly installieren,
cargo +nightlyund eine Toolchain pro Projekt festlegen. - The Unstable Book (auf Englisch): jeder instabile Feature-Name, den du in einem E0658 sehen kannst, jeweils mit kurzer Beschreibung.
slice::join– Doku der Standardbibliothek (auf Englisch): der stabile Weg, Zeichenketten mit einem Trennzeichen zu verbinden, die Alternative zuintersperse.