Rust-Compilerfehler einfach erklärt
Der Rust-Compiler zeigt dir einen roten Fehler, und du weißt nicht genau, was er von dir will? Dann bist du hier richtig. Jeder Rust-Entwickler sieht diese Fehler, oft mehrmals am Tag. Die gute Nachricht: Es gibt nur eine Handvoll, die dir immer wieder begegnen. Sobald du sie kennst, verlieren sie ihren Schrecken.
Jede Seite unten nimmt sich einen Fehlercode vor. Sie zeigt dir die echte Meldung, erklärt sie in einfachen Worten und gibt dir Lösungen, die du direkt im Browser ausprobieren kannst.
Die häufigsten Fehler
Abschnitt betitelt „Die häufigsten Fehler“Die mittlere Spalte bleibt auf Englisch – genau so steht die Meldung in deinem Terminal.
| Fehler | Was der Compiler sagt | In einfachen Worten |
|---|---|---|
| E0382 | borrow of moved value | Du hast einen Wert weggegeben und willst ihn danach noch benutzen |
| E0502 | cannot borrow as mutable because it is also borrowed as immutable | Du änderst etwas, während es noch jemand liest |
| E0499 | cannot borrow as mutable more than once at a time | Zwei Stellen wollen gleichzeitig dasselbe ändern |
| E0308 | mismatched types | Du hast einen Typ übergeben, wo ein anderer erwartet wird |
| E0277 | the trait bound is not satisfied | Ein Typ kann etwas nicht, das du von ihm verlangst (ausgeben, vergleichen, addieren …) |
| E0106 | missing lifetime specifier | Rust weiß nicht, wie lange eine zurückgegebene Referenz gültig bleibt |
| E0425 | cannot find value in this scope | Ein Name ist falsch geschrieben oder wird außerhalb seines Blocks benutzt |
| E0599 | no method named … found | Die Methode gibt es für diesen Typ nicht, oder ihr Trait ist nicht importiert |
| E0384 | cannot assign twice to immutable variable | Du hast eine Variable geändert, die nicht mit mut deklariert ist |
| E0596 | cannot borrow as mutable, as it is not declared as mutable | Du willst etwas über eine Variable oder Referenz ändern, die nicht mut ist |
| E0597 | borrowed value does not live long enough | Eine Referenz wird noch benutzt, obwohl ihr Wert schon weg ist |
| E0515 | cannot return reference to local variable | Du gibst eine Referenz auf etwas zurück, das am Ende der Funktion aufgeräumt wird |
| E0373 | closure may outlive the current function, but it borrows … | Ein Closure (oft ein Thread) leiht sich eine lokale Variable, die vielleicht schon weg ist, wenn es läuft |
| E0369 | binary operation == cannot be applied to type … |
Dein Typ unterstützt ==, <, + und Co. (noch) nicht |
| E0432 | unresolved import | Eine use-Zeile zeigt auf ein Crate, Modul oder Element, das es nicht gibt |
| E0433 | cannot find type … in this scope (older: failed to resolve) | Ein Pfad wie HashMap::new() benutzt einen Namen, der nicht importiert ist oder nicht existiert |
| E0424 | self value is a keyword only available in methods with a self parameter |
Du hast self in einer Funktion benutzt, die kein self bekommt |
| E0061 | this function takes N arguments but M arguments were supplied | Du hast zu viele oder zu wenige Argumente übergeben (Rust kennt keine optionalen Argumente) |
| E0594 | cannot assign to p.hp, as p is not declared as mutable |
Du hast ein Feld oder einen Wert hinter & geändert, ohne mut-Zugriff zu haben |
| E0004 | non-exhaustive patterns: X not covered |
Dein match behandelt nicht jeden möglichen Wert |
| E0507 | cannot move out of x which is behind a shared reference |
Du willst etwas besitzen, das du dir nur geliehen hast |
| E0603 | function x is private |
Du benutzt eine Funktion, ein Struct oder ein Modul, das nicht pub ist |
| E0716 | temporary value dropped while borrowed | Du hältst eine Referenz auf einen Wert, der am Ende der Zeile weggeworfen wird |
| E0463 | can’t find crate for x |
Ein Crate (oder die Standardbibliothek für ein Ziel) ist nicht installiert |
| E0368 | binary assignment operation += cannot be applied to type … |
Dein Typ unterstützt +=, -= und Co. nicht |
| E0057 | this function takes N arguments but M were supplied (note: closure defined here) | Du hast einen Closure mit zu vielen oder zu wenigen Argumenten aufgerufen |
| E0282 | type annotations needed | Rust kann einen Typ nicht selbst herausfinden, also musst du ihn angeben |
| E0609 | no field x on type T |
Der Feldname ist falsch geschrieben, oder der Wert ist eingepackt (z. B. in Option) |
| E0593 | closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments | Ein Closure nimmt einzelne Argumente, wo ein Tupel (oder eine andere Anzahl) erwartet wird |
| E0631 | type mismatch in closure arguments | Der Parametertyp eines Closures passt nicht zu dem, was es bekommt (oft i32 statt &i32) |
| E0005 | refutable pattern in local binding | let Some(x) = … kann fehlschlagen, deshalb akzeptiert ein einfaches let es nicht |
| E0615 | attempted to take value of method len on type String |
Du hast s.len statt s.len() geschrieben |
| E0610 | {integer} is a primitive type and therefore doesn’t have fields |
Du hast .feld auf einer Zahl, einem bool oder einem char benutzt |
| E0560 | struct User has no field named nmae |
Ein Struct-Literal benutzt einen Feldnamen, den das Struct nicht hat |
| E0616 | field balance of struct Account is private |
Du liest ein Feld, das nicht pub ist, von außerhalb seines Moduls |
| E0451 | field x of struct Y is private |
Du hast ein Struct per Literal erzeugt, obwohl einige seiner Felder privat sind |
| E0624 | method x is private |
Du hast eine Methode oder assoziierte Funktion aufgerufen, die nicht pub ist |
| E0283 | type annotations needed (cannot infer type … multiple impls satisfy this bound) | Mehrere Typen kommen infrage (z. B. bei .collect(), .sum()), also musst du einen wählen |
| E0284 | type annotations needed: cannot satisfy <_ as FromStr>::Err == _ |
"42".parse() weiß nicht, in welchen Typ es parsen soll |
| E0790 | cannot call associated function on trait without specifying the corresponding impl type |
Du hast Default::default() oder Trait::new() geschrieben, ohne zu sagen, welcher Typ gemeint ist |
| E0559 | variant Shape::Circle has no field named r |
Ein Literal einer Enum-Variante benutzt einen Feldnamen, den die Variante nicht hat |
| E0063 | missing field email in initializer of User |
Du hast ein Struct erzeugt, aber ein oder mehrere Felder weggelassen |
| E0689 | can’t call method pow on ambiguous numeric type {integer} |
2.pow(10) oder 2.0.sqrt() braucht einen konkreten Zahlentyp wie i32 oder f64 |
| E0034 | multiple applicable items in scope | Zwei Traits geben deinem Typ eine gleichnamige Methode, und Rust kann sich nicht entscheiden |
| E0412 | cannot find type X in this scope (Rust 1.93+ prints E0425) |
Ein Typname ist falsch geschrieben, nicht importiert oder nicht deklariert |
| E0428 | the name area is defined multiple times |
Zwei Elemente teilen sich einen Namen; Rust kennt kein Überladen von Funktionen |
| E0026 | variant Shape::Circle does not have a field named r |
Ein Pattern nennt ein Feld, das es im Struct oder in der Variante nicht gibt |
| E0027 | pattern does not mention fields id, paid |
Einem Struct-Pattern fehlen Felder; ergänze sie oder schließ mit .. ab |
| E0533 | expected unit struct, unit variant or constant, found struct variant Shape::Circle |
Eine Struct-Variante (oder eine Funktion) steht dort, wo ein einfacher Name erwartet wird; ergänze { .. } |
| E0592 | duplicate definitions with name reset |
Zwei impl-Blöcke definieren eine Methode mit demselben Namen |
| E0255 | the name Error is defined multiple times |
Ein use-Import hat denselben Namen wie dein eigener Typ oder deine eigene Funktion |
| E0252 | the name Result is defined multiple times |
Zwei use-Zeilen holen denselben Namen; benenn einen mit as um |
| E0411 | cannot find type Self in this scope |
Du hast Self außerhalb eines impl-Blocks oder Traits benutzt |
| E0405 | cannot find trait Display in this scope |
Ein Trait-Name ist falsch geschrieben oder nicht importiert (z. B. use std::fmt::Display;) |
| E0532 | expected unit struct, unit variant or constant, found tuple variant Shape::Circle |
Ein Muster nennt eine Tupel-Variante (oder ein Struct) ohne ihre ( ), oder setzt ( ), wo keine hingehören |
| E0164 | expected tuple struct or tuple variant, found struct variant Shape::Circle |
Ein Muster setzt ( ) an eine Struct-Variante oder ein assoziiertes Element; nimm { } oder einen Guard |
| E0404 | expected trait, found derive macro Debug |
Du hast impl X for oder T: X geschrieben, und X ist ein Struct, ein Alias oder ein nicht importiertes Derive-Makro |
| E0401 | can’t use generic parameters from outer item | Ein inneres fn benutzt das T oder Self der äußeren Funktion; gib ihm eigene Generics oder nimm ein Closure |
| E0107 | enum takes 2 generic arguments but 1 generic argument was supplied | Result<u32>, HashMap<String> und Co.: zu wenige oder zu viele Argumente in < > |
| E0530 | match bindings cannot shadow tuple variants | Ein nackter Variantenname wie Circle => (nach use Shape::*) kann keine neue Variable sein |
| E0434 | can’t capture dynamic environment in a fn item | Ein inneres fn sieht keine lokalen Variablen der äußeren Funktion; nimm ein Closure oder übergib sie |
| E0601 | main function not found in crate main |
Das Programm hat kein fn main() (fehlt, falsch geschrieben, steckt in einem mod oder ist eigentlich eine Library) |
| E0658 | use of unstable library feature iter_intersperse |
Du hast eine Nightly-API auf Stable-Rust benutzt; nimm die stabile Alternative oder aktualisiere Rust |
| E0614 | type u32 cannot be dereferenced |
Du hast *x geschrieben, aber x ist schon ein normaler Wert, keine Referenz |
| E0435 | attempt to use a non-constant value in a constant | Ein const, eine Array-Länge oder ein static benutzt eine let-Variable; mach einen const daraus oder nimm einen Vec |
| E0554 | #![feature] may not be used on the stable release channel |
Kopierter Code nur für Nightly; entferne das Attribut und nimm die stabile API, oder benutz bewusst Nightly |
So liest du eine Rust-Fehlermeldung
Abschnitt betitelt „So liest du eine Rust-Fehlermeldung“Die Fehlermeldungen von Rust sind berühmt dafür, wie hilfreich sie sind. Aber sie enthalten auch eine Menge Informationen. Hier ist eine echte:
fn main() { let name = String::from("Ferris"); let greeting = name; println!("{name}");}error[E0382]: borrow of moved value: `name` --> src/main.rs:4:16 |2 | let name = String::from("Ferris"); | ---- move occurs because `name` has type `String`, which does not implement the `Copy` trait3 | let greeting = name; | ---- value moved here4 | println!("{name}"); | ^^^^ value borrowed here after move |help: consider cloning the value if the performance cost is acceptable |3 | let greeting = name.clone(); | ++++++++Die Meldung sagt: name wurde in Zeile 3 verschoben („moved“) und in Zeile 4 trotzdem noch benutzt. Lies sie in dieser Reihenfolge:
- Die erste Zeile ist die Zusammenfassung: der Fehlercode (
E0382) und eine kurze Beschreibung. - Die Pfeilzeile (
--> src/main.rs:4:16) nennt dir Datei, Zeile und Spalte, wo es schiefgegangen ist. - Die
^^^^-Markierungen zeigen genau auf die Fehlerstelle. Die-----Markierungen erzählen die Vorgeschichte. Hier sagen sie: Der Wert wurde in Zeile 2 erzeugt, in Zeile 3 verschoben und in Zeile 4 benutzt. help:ist der Lösungsvorschlag des Compilers, oft mit genau dem Code, den du ergänzen sollst (die++++-Markierungen zeigen neue Zeichen). Das ist nicht immer die beste Lösung, aber ein super Ausgangspunkt.
Fang beim ersten Fehler an. Ein einziger Fehler kann eine ganze Kette von Folgefehlern auslösen. Behebst du den ersten, verschwinden die anderen oft von allein.
Drei Gewohnheiten, die helfen
Abschnitt betitelt „Drei Gewohnheiten, die helfen“-
Frag den Compiler nach mehr. Zu jedem Fehlercode gibt es eine längere, eingebaute Erklärung. Führe das in einem Terminal aus:
Terminal window rustc --explain E0382Du bekommst eine kurze Beschreibung, ein fehlerhaftes und ein korrigiertes Beispiel (auf Englisch).
-
Prüf oft.
cargo checkfindet Fehler, ohne das ganze Programm zu bauen. Es ist also viel schneller alscargo build. Wenn du es nach ein paar Zeilen immer wieder ausführst, triffst du die Fehler einzeln – nicht zwanzig auf einmal. Siehe Cargo und Crates. -
Lass dir Fehler schon beim Tippen anzeigen. Mit der Erweiterung rust-analyzer erscheinen die Fehler direkt in deinem Code, mit denselben Hilfetexten. Siehe Rust-Werkzeuge und Einrichtung.
Warum Rust so viele Fehler meldet
Abschnitt betitelt „Warum Rust so viele Fehler meldet“Die meisten dieser Fehler gibt es, weil Rust schon vor dem Start deines Programms Dinge prüft, die andere Sprachen erst zur Laufzeit entdecken (oder nie): Zugriff auf bereits freigegebenen Speicher, zwei Threads, die gleichzeitig dieselben Daten ändern, eine vergessene null-Prüfung. Jeder Fehler, den du behebst, ist ein Bug, der nie bei deinen Nutzern ankommt.
Deshalb sagen viele: In Rust kämpfst du beim Kompilieren – und danach läuft das Programm einfach. Die Regeln hinter den häufigsten Fehlern erklären wir in Ownership, Borrowing und Lifetimes.
Kurzer Check
Abschnitt betitelt „Kurzer Check“Kurzer Check
1. Eine Rust-Fehlermeldung zeigt mehrere Probleme. Welches behebst du zuerst?
2. Was macht rustc --explain E0382?
3. Was zeigen die ^^^^-Markierungen in einer Fehlermeldung?
Punkte: 0 / 3
Weiterlesen
Abschnitt betitelt „Weiterlesen“- Rust Compiler Error Index (auf Englisch): die offizielle Liste aller Fehlercodes, jeweils mit einem fehlerhaften und einem korrigierten Beispiel.
- Eigentümerschaft verstehen – Das Rust-Buch: die Regeln hinter den häufigsten Fehlern rund um Borrowing und Moves.
- Fehlerbehandlung – Das Rust-Buch: wie Rust mit Fehlern in deinen eigenen Programmen umgeht (
Resultundpanic!), nicht nur mit Compilerfehlern. - What is rustc? – The rustc Book (auf Englisch): wie der Compiler arbeitet, inklusive seiner Optionen und Lint-Stufen.