Zum Inhalt springen

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.

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 scope
help: 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();
}

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.

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.

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 gestartet
▶ Selbst ausprobieren

Dasselbe 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: ANA
Letzter Gast: Some("CHEN")
▶ Selbst ausprobieren

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

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]
▶ Selbst ausprobieren

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 parameter
2 | 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]
▶ Selbst ausprobieren
  • Ein Tippfehler oder eine Methode aus einer anderen Sprache. tasks.push_back(...) auf einem Vec ergibt help: you might have meant to use `push`, und tasks.lenght() ergibt help: 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 mit no associated function or constant named `new` found for struct `Account`. Lösung: Ergänze impl Account { fn new(owner: &str, balance: i64) -> Self { ... } }, oder baue den Wert direkt mit Account { owner: ..., balance: ... }. Siehe Structs.
  • Eine assoziierte Funktion mit Punkt aufrufen. Hat fn new() -> Self keinen self-Parameter, schlägt acc.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().

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