Ошибка 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 scopehelp: 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 так делает
Заголовок раздела «Почему Rust так делает»В 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.
Как исправить
Заголовок раздела «Как исправить»Исправление 1: импортируй трейт
Заголовок раздела «Исправление 1: импортируй трейт»Выбирай этот вариант, когда подсказка говорит «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.
Исправление 3: вызови .iter() у Vec
Заголовок раздела «Исправление 3: вызови .iter() у Vec»Выбирай этот вариант, когда вызываешь .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 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 { | ++++++++++Подсказка говорит: трейт 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().
Связанные ошибки
Заголовок раздела «Связанные ошибки»- E0425: cannot find value in this scope: не видно само имя, а не метод у типа.
- E0277: trait bound not satisfied: типу не хватает трейта, который нужен функции или оператору. В обобщённом коде часто появляется рядом с E0599.
- E0308: mismatched types: у тебя
Option<T>там, где ожидалсяT, или наоборот. - E0382: use of moved value: частое продолжение после перехода с
.iter()на.into_iter(). - Все ошибки компилятора: полный список с кратким описанием каждой.
Проверь себя
Заголовок раздела «Проверь себя»Проверь себя
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
Что почитать
Заголовок раздела «Что почитать»- E0599 — Rust error codes index (на английском): официальное объяснение этой ошибки.
- Трейты: определение общего поведения — книга «Язык программирования Rust» (перевод на русский): как трейты добавляют типам методы и как работают ограничения трейтов.
- Обработка последовательности элементов с помощью итераторов — книга «Язык программирования Rust» (перевод на русский):
iter(),into_iter()и методы итераторов вродеmap. Option— стандартная библиотека Rust (на английском): все методы, чтобы достать значение изOption.- The Rust prelude — стандартная библиотека Rust (на английском): трейты, которые всегда в области видимости, и почему
Writeв их число не входит.