Перейти к содержимому

Ошибка Rust E0599: no method named X found (метод не найден)

Ошибка E0599 значит, что ты вызвал метод, который Rust не может найти у этого типа. Она встречается очень часто, и причина обычно одна из немногих: ты не импортировал трейт, не достал значение из Option, обращался с Vec как с итератором или просто опечатался. Хорошая новость: строки help: в сообщении rustc часто подсказывают точное исправление. Эта страница — часть раздела Ошибки компилятора Rust с объяснениями.

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

Компилятор пишет: у структуры Stdout в текущей области видимости нет метода write_all. Подсказки объясняют: элементы трейтов можно использовать, только если трейт в области видимости, а трейт Write, который даёт write_all, реализован, но не импортирован.

Вот программа, которая выдала эту ошибку:

use std::io;
fn main() {
let mut out = io::stdout();
out.write_all(b"Server started\n").unwrap();
}

Текст здесь английский, потому что байтовая строка b"..." может содержать только ASCII-символы.

Значки ^^^^ отмечают имя метода, write_all, а первая строка говорит, у какого типа Rust его искал: Stdout. Так что сообщение читается как «я посмотрел у Stdout и не нашёл метода write_all, которым мне здесь разрешено пользоваться».

Тип в этой первой строке — самая полезная подсказка во всём сообщении. Если там Option<T>, Result<T, E>, Vec<_> или параметр типа T, хотя ты ожидал что-то другое, ты уже знаешь, какое исправление ниже тебе нужно.

В Rust многие методы принадлежат не самому типу. Они приходят из трейта. write_all приходит из трейта Write, и Stdout его реализует. Но методы трейта работают только в файле, где трейт находится в области видимости, — обычно благодаря строке use. Именно это значит «items from traits can only be used if the trait is in scope».

Это правило делает код предсказуемым. Два крейта могут добавить одному и тому же типу метод write_all через разные трейты. Если бы все трейты всегда были активны, нельзя было бы понять, какой из них имеется в виду при вызове. С этим правилом учитываются только те трейты, которые ты импортировал.

Остальные причины связаны со строгой типизацией Rust. Option<&str> — это не &str, поэтому методов &str у него нет. Обобщённый T может оказаться вообще любым типом, поэтому Rust позволяет вызывать только те методы, которые обещают ограничения на T.

Выбирай этот вариант, когда подсказка говорит «items from traits can only be used if the trait is in scope». Добавь строку use, которую предлагает rustc.

use std::io::{self, Write};
fn main() {
let mut out = io::stdout();
out.write_all(b"Server started\n").unwrap();
}

Вывод:

Server started
▶ Попробуй сам

То же самое бывает с крейтом rand. Без импорта rng.random_range(1..=6) не работает, и rustc говорит, какой трейт нужно подключить:

help: trait `RngExt` which provides `random_range` is implemented but not in scope; perhaps you want to import it
|
1 + use rand::RngExt;

Внимание: в rand 0.10 трейт называется RngExt. В старых учебниках написано use rand::Rng, и с rand 0.10 такой импорт даёт ровно эту же ошибку. Следуй строке help:, а не учебнику.

Исправление 2: сначала достань значение из Option или Result

Заголовок раздела «Исправление 2: сначала достань значение из Option или Result»

Выбирай этот вариант, когда в ошибке указан тип Option<T> или Result<T, E>. Нужное значение лежит внутри, и его надо достать, прежде чем вызывать его методы.

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

У перечисления Option<T> нет метода to_uppercase. first() возвращает Option, потому что список может быть пустым. rustc предлагает .expect(...), и это работает, но программа упадёт на None. Обычно лучше обработать оба случая:

fn main() {
let guests = vec!["ana", "bo", "chen"];
match guests.first() {
Some(name) => println!("Первый гость: {}", name.to_uppercase()),
None => println!("Гостей пока нет"),
}
let shout = guests.last().map(|name| name.to_uppercase());
println!("Последний гость: {:?}", shout);
}

Вывод:

Первый гость: ANA
Последний гость: Some("CHEN")
▶ Попробуй сам

.map() выполняет твой код над значением внутри и сохраняет обёртку Option. Для Result (например, из .parse()) используй match, .unwrap_or(...) или ? внутри функции, которая возвращает Result. См. Option и Result.

Выбирай этот вариант, когда вызываешь .map(), .filter() или другой метод итератора прямо у Vec. Ошибка здесь выглядит иначе:

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`

«Метод map существует для Vec<{integer}>, но ограничения трейтов не выполнены». Для некоторых методов, например filter, сообщение дружелюбнее. rustc пишет, что Vec<i32> «is not an iterator» («не итератор»), и добавляет help: call `.into_iter()` first. Причина та же, исправление то же.

Vec<{integer}>: Iterator «не выполнено», потому что Vec — это коллекция, а не итератор. Попроси у него итератор через .iter() (заимствует элементы) или .into_iter() (забирает их):

fn main() {
let scores = vec![70, 85, 92];
let curved: Vec<i32> = scores.iter().map(|s| s + 5).collect();
println!("{:?}", curved);
}

Вывод:

[75, 90, 97]
▶ Попробуй сам

Исправление 4: добавь ограничение трейта к обобщённому T

Заголовок раздела «Исправление 4: добавь ограничение трейта к обобщённому T»

Выбирай этот вариант, когда ошибка говорит, что метод не найден «for type parameter T» («для параметра типа T»). Внутри обобщённой функции Rust знает только то, что обещают ограничения на T. Голый T ничего не обещает, поэтому методов у него нет.

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

Подсказка говорит: трейт ToString определяет to_string, возможно, стоит ограничить им параметр T. Добавь ограничение, которое предлагает rustc. Теперь функция принимает только типы, которые можно превратить в строку:

fn describe<T: ToString>(item: T) -> String {
format!("[{}]", item.to_string())
}
fn main() {
println!("{}", describe(42));
println!("{}", describe("готово"));
}

Вывод:

[42]
[готово]
▶ Попробуй сам
  • Опечатка или метод из другого языка. tasks.push_back(...) у Vec даёт help: you might have meant to use `push`, а tasks.lenght() — help: there is a method `len` with a similar name. Исправление: используй имя, которое предлагает rustc.
  • Вызов Type::new(), который ты не написал. Бесплатных конструкторов в Rust нет: Account::new("Ana", 100) падает с no associated function or constant named `new` found for struct `Account`. Исправление: добавь impl Account { fn new(owner: &str, balance: i64) -> Self { ... } } или создай значение напрямую: Account { owner: ..., balance: ... }. См. Структуры.
  • Вызов связанной функции через точку. Если у fn new() -> Self нет параметра self, acc.new() падает с сообщением «this is an associated function, not a method» («это связанная функция, а не метод»). Исправление: вызывай её у типа: Account::new().

Проверь себя

1. rustc пишет "items from traits can only be used if the trait is in scope". Что делать?

2. names.first().to_uppercase() падает с E0599 для Option<&&str>. Почему?

3. Ты вызываешь scores.filter(...) у Vec<i32>, и rustc пишет "Vec<i32> is not an iterator". Как исправить?

Результат: 0 / 3