Rust-Fehler E0599: no method named X found (Methode nicht gefunden)
Fehler E0599 bedeutet: Du hast eine Methode aufgerufen, die Rust für diesen Typ nicht finden kann. Der Fehler ist sehr häufig, und die Ursache ist meistens eine von wenigen: ein Trait (Eigenschaft), den du nicht importiert hast, eine Option, die du nicht ausgepackt hast, ein Vec, den du wie einen Iterator behandelst, oder ein einfacher Tippfehler. Die gute Nachricht: Die help:-Zeilen von rustc verraten dir oft schon die genaue Lösung. Diese Seite gehört zur Reihe Rust-Compilerfehler einfach erklärt.
Die Fehlermeldung
Abschnitt betitelt „Die Fehlermeldung“error[E0599]: no method named `write_all` found for struct `Stdout` in the current scope --> src/main.rs:5:9 |5 | out.write_all(b"Server started\n").unwrap(); | ^^^^^^^^^ | = note: the method is available for `Stdout` here | = help: items from traits can only be used if the trait is in scopehelp: trait `Write` which provides `write_all` is implemented but not in scope; perhaps you want to import it |1 + use std::io::Write; |Auf Deutsch heißt das ungefähr: „Für das Struct Stdout gibt es hier keine Methode namens write_all.“ Dieses Programm erzeugt die Meldung:
use std::io;
fn main() { let mut out = io::stdout(); out.write_all(b"Server started\n").unwrap();}Was sie bedeutet
Abschnitt betitelt „Was sie bedeutet“Die ^^^^ markieren den Namen der Methode, write_all, und die erste Zeile nennt den Typ, bei dem Rust gesucht hat: Stdout. Die Meldung heißt also: „Ich habe bei Stdout nachgesehen und keine Methode write_all gefunden, die ich hier benutzen darf.“
Der Typ in dieser ersten Zeile ist der wichtigste Hinweis auf der ganzen Seite. Steht da Option<T>, Result<T, E>, Vec<_> oder ein Typparameter T, obwohl du etwas anderes erwartet hast, weißt du schon, welche Lösung unten du brauchst.
Warum Rust das macht
Abschnitt betitelt „Warum Rust das macht“In Rust gehören viele Methoden gar nicht zum Typ selbst. Sie kommen aus einem Trait. write_all stammt aus dem Trait Write, und Stdout implementiert ihn. Die Methoden eines Traits funktionieren aber nur in einer Datei, in der der Trait sichtbar ist – meistens durch eine use-Zeile. Genau das sagt „items from traits can only be used if the trait is in scope“ (Elemente aus Traits kannst du nur benutzen, wenn der Trait sichtbar ist).
Diese Regel hält deinen Code vorhersehbar. Zwei Crates können demselben Typ über verschiedene Traits jeweils eine Methode namens write_all hinzufügen. Wäre jeder Trait immer aktiv, könntest du nicht erkennen, welche gemeint ist. Mit der Regel zählen nur die Traits, die du importiert hast.
Die anderen Ursachen kommen von Rusts strengen Typen. Eine Option<&str> ist kein &str, also hat sie auch keine &str-Methoden. Ein generisches T kann jeder beliebige Typ sein. Deshalb erlaubt Rust nur Methoden, die die Bounds (Einschränkungen) von T versprechen.
So behebst du den Fehler
Abschnitt betitelt „So behebst du den Fehler“Lösung 1: Den Trait importieren
Abschnitt betitelt „Lösung 1: Den Trait importieren“Nimm diese Lösung, wenn die Hilfe sagt: „items from traits can only be used if the trait is in scope“. Ergänze die use-Zeile, die rustc vorschlägt.
use std::io::{self, Write};
fn main() { let mut out = io::stdout(); out.write_all(b"Server gestartet\n").unwrap();}Ausgabe:
Server gestartetDasselbe passiert mit dem Crate rand. Ohne Import schlägt rng.random_range(1..=6) fehl, und rustc sagt dir, welchen Trait du hereinholen musst:
help: trait `RngExt` which provides `random_range` is implemented but not in scope; perhaps you want to import it |1 + use rand::RngExt;Rust schlägt hier vor, den Trait RngExt zu importieren, der random_range bereitstellt. Achtung: In rand 0.10 heißt der Trait RngExt. Ältere Tutorials schreiben use rand::Rng, und mit rand 0.10 bekommst du mit diesem Import genau denselben Fehler. Folge der help:-Zeile, nicht dem Tutorial.
Lösung 2: Den Wert zuerst aus der Option oder dem Result holen
Abschnitt betitelt „Lösung 2: Den Wert zuerst aus der Option oder dem Result holen“Nimm diese Lösung, wenn der Typ im Fehler Option<T> oder Result<T, E> ist. Der Wert, den du willst, steckt darin, und du musst ihn herausholen, bevor du seine Methoden aufrufst.
error[E0599]: no method named `to_uppercase` found for enum `Option<T>` in the current scope --> src/main.rs:4:39 |4 | println!("First guest: {}", first.to_uppercase()); | ^^^^^^^^^^^^ method not found in `Option<&&str>`Die Methode to_uppercase gibt es nicht für Option<&&str>. first() liefert eine Option, weil die Liste leer sein könnte. rustc schlägt .expect(...) vor. Das funktioniert, stürzt aber bei None ab. Meistens ist es besser, beide Fälle zu behandeln:
fn main() { let guests = vec!["ana", "bo", "chen"];
match guests.first() { Some(name) => println!("Erster Gast: {}", name.to_uppercase()), None => println!("Noch keine Gäste"), }
let shout = guests.last().map(|name| name.to_uppercase()); println!("Letzter Gast: {:?}", shout);}Ausgabe:
Erster Gast: ANALetzter Gast: Some("CHEN").map() führt deinen Code auf dem inneren Wert aus und lässt die Option drumherum bestehen. Bei einem Result (zum Beispiel von .parse()) nimmst du match, .unwrap_or(...) oder ? in einer Funktion, die selbst ein Result zurückgibt. Mehr dazu unter Option und Result.
Lösung 3: .iter() auf dem Vec aufrufen
Abschnitt betitelt „Lösung 3: .iter() auf dem Vec aufrufen“Nimm diese Lösung, wenn du .map(), .filter() oder eine andere Iterator-Methode direkt auf einem Vec aufrufst. Der Fehler sieht hier anders aus:
error[E0599]: the method `map` exists for struct `Vec<{integer}>`, but its trait bounds were not satisfied --> src/main.rs:3:35 |3 | let curved: Vec<i32> = scores.map(|s| s + 5).collect(); | ^^^ | = note: the following trait bounds were not satisfied: `Vec<{integer}>: Iterator`Auf Deutsch: Die Methode map gibt es zwar, aber Vec<{integer}> erfüllt die nötigen Trait Bounds nicht. Bei manchen Methoden, etwa filter, ist die Meldung freundlicher. Dann sagt rustc, dass Vec<i32> „is not an iterator“ (kein Iterator ist), und ergänzt help: call `.into_iter()` first. Gleiche Ursache, gleiche Lösung.
Vec<{integer}>: Iterator ist „not satisfied“ (nicht erfüllt), weil ein Vec eine Sammlung ist und kein Iterator. Bitte ihn mit .iter() (leiht die Elemente aus) oder .into_iter() (übernimmt sie) um einen Iterator:
fn main() { let scores = vec![70, 85, 92]; let curved: Vec<i32> = scores.iter().map(|s| s + 5).collect(); println!("{:?}", curved);}Ausgabe:
[75, 90, 97]Lösung 4: Dem generischen T einen Trait Bound geben
Abschnitt betitelt „Lösung 4: Dem generischen T einen Trait Bound geben“Nimm diese Lösung, wenn der Fehler sagt, dass die Methode „for type parameter T“ (für den Typparameter T) nicht gefunden wurde. In einer generischen Funktion weiß Rust nur das über T, was seine Bounds versprechen. Ein einfaches T verspricht gar nichts – also hat es auch keine Methoden.
error[E0599]: no method named `to_string` found for type parameter `T` in the current scope --> src/main.rs:2:26 |1 | fn describe<T>(item: T) -> String { | - method `to_string` not found for this type parameter2 | format!("[{}]", item.to_string()) | ^^^^^^^^^ method cannot be called on `T` due to unsatisfied trait bounds |help: the following trait defines an item `to_string`, perhaps you need to restrict type parameter `T` with it: |1 | fn describe<T: ToString>(item: T) -> String { | ++++++++++Die Hilfe sagt: Der Trait ToString definiert to_string, schränke T damit ein. Ergänze den Bound, den rustc vorschlägt. Jetzt werden nur noch Typen angenommen, die sich in eine Zeichenkette umwandeln lassen:
fn describe<T: ToString>(item: T) -> String { format!("[{}]", item.to_string())}
fn main() { println!("{}", describe(42)); println!("{}", describe("bereit"));}Ausgabe:
[42][bereit]Wo du ihn oft siehst
Abschnitt betitelt „Wo du ihn oft siehst“- Ein Tippfehler oder eine Methode aus einer anderen Sprache.
tasks.push_back(...)auf einemVecergibthelp: you might have meant to use `push`, undtasks.lenght()ergibthelp: there is a method `len` with a similar name. Lösung: Nimm den Namen, den rustc vorschlägt. Type::new()aufrufen, obwohl du es nie geschrieben hast. Rust schenkt dir keine Konstruktoren:Account::new("Ana", 100)schlägt fehl mitno associated function or constant named `new` found for struct `Account`. Lösung: Ergänzeimpl Account { fn new(owner: &str, balance: i64) -> Self { ... } }, oder baue den Wert direkt mitAccount { owner: ..., balance: ... }. Siehe Structs.- Eine assoziierte Funktion mit Punkt aufrufen. Hat
fn new() -> Selfkeinenself-Parameter, schlägtacc.new()fehl mit „this is an associated function, not a method“ (das ist eine assoziierte Funktion, keine Methode). Lösung: Ruf sie über den Typ auf,Account::new().
Verwandte Fehler
Abschnitt betitelt „Verwandte Fehler“- E0425: cannot find value in this scope: Der Name selbst ist nicht sichtbar – nicht bloß eine Methode eines Typs.
- E0277: trait bound not satisfied: Einem Typ fehlt ein Trait, den eine Funktion oder ein Operator braucht. Taucht in generischem Code oft zusammen mit E0599 auf.
- E0308: mismatched types: Du hast eine
Option<T>, wo einTerwartet wird, oder umgekehrt. - E0382: use of moved value: ein häufiger Folgefehler, nachdem du von
.iter()auf.into_iter()umgestiegen bist. - Alle Compilerfehler: die vollständige Liste, mit einer kurzen Zusammenfassung zu jedem Fehler.
Kurzer Check
Abschnitt betitelt „Kurzer Check“Kurzer Check
1. rustc sagt „items from traits can only be used if the trait is in scope“. Was solltest du tun?
2. names.first().to_uppercase() schlägt mit E0599 für Option<&&str> fehl. Warum?
3. Du rufst scores.filter(...) auf einem Vec<i32> auf, und rustc sagt „Vec<i32> is not an iterator“. Wie behebst du das?
Punkte: 0 / 3
Weiterlesen
Abschnitt betitelt „Weiterlesen“- E0599 – Rust error codes index (auf Englisch): die offizielle Erklärung dieses Fehlers.
- Gemeinsames Verhalten definieren mit Traits – Das Rust-Buch: wie Traits Typen um Methoden erweitern und wie Trait Bounds funktionieren.
- Eine Reihe von Elementen mit Iteratoren verarbeiten – Das Rust-Buch:
iter(),into_iter()und Iterator-Methoden wiemap. Option– Rust standard library (auf Englisch): alle Methoden, mit denen du einen Wert aus einerOptionherausholst.- The Rust prelude – Rust standard library (auf Englisch): die Traits, die immer sichtbar sind, und warum
Writenicht dazugehört.