Zum Inhalt springen

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

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` trait
3 | let greeting = name;
| ---- value moved here
4 | 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:

  1. Die erste Zeile ist die Zusammenfassung: der Fehlercode (E0382) und eine kurze Beschreibung.
  2. Die Pfeilzeile (--> src/main.rs:4:16) nennt dir Datei, Zeile und Spalte, wo es schiefgegangen ist.
  3. 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.
  4. 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.

  • 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 E0382

    Du bekommst eine kurze Beschreibung, ein fehlerhaftes und ein korrigiertes Beispiel (auf Englisch).

  • Prüf oft. cargo check findet Fehler, ohne das ganze Programm zu bauen. Es ist also viel schneller als cargo 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.

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

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