Способ настройки сообщений об ошибках Rust

Перевод | Автор оригинала: Pascal Hertleif

Сообщения об ошибках в Rust просто потрясающие. Однако нет возможности форматировать ошибки, относящиеся к конкретной библиотеке. Я предлагаю способ реализовать это в стабильной версии Rust.

Предшественник

Если вы никогда не видели ни одного из сообщений об ошибках, которые выдает Rust, вот некоторые (в реальной жизни они даже цветные):

error[E0507]: cannot move out of indexed content
  --> tests/migration_generate.rs:42:21
   |
42 |     let migration = migrations[0];
   |         ---------   ^^^^^^^^^^^^^ cannot move out of indexed content
   |         |
   |         hint: to prevent move, use `ref migration` or `ref mut migration`

error: cannot borrow immutable local variable `down` as mutable
  --> src/main.rs:98:13
   |
97 |             let down = fs::File::create(down_path).unwrap();
   |                 ---- use `mut down` here to make mutable
98 |             down.write_all(b"hello").unwrap();
   |             ^^^^ cannot borrow mutably

Тем не менее, есть и некоторые ошибки, менее полезные для новичков, например, эта (отрывок):

19 |     let results = users::table.load::<UserModel>(&connection);
   |                                ^^^^ the trait `diesel::types::FromSqlRow<(diesel::types::Uuid, diesel::types::Timestamp, diesel::types::Timestamp, diesel::types::Text, diesel::types::Text), _>` is not implemented for `(uuid::Uuid, std::string::String, std::string::String)`

Эта ошибка на самом деле хочет вам сказать:

diesel::types::FromSqlRow нельзя использовать для преобразования типов SQL

(Uuid, Timestamp, Timestamp, Text, Text)

к этим типам Rust

(Uuid, String, String)

Который в основном хочет сказать: «В вашей таблице есть два столбца (с отметками времени в них), которые вы забыли добавить в свою структуру Rust».

Я опустил пространства имен, когда добавил аннотации «Типы SQL» и «Типы Rust». Это упрощает чтение, но также напоминает людям о том, что делает FromSqlRow. (Однако следует отметить, что эти два типа Uuid не совпадают.)

Когда проблема связана с типами столбцов (вместо того, чтобы забыть о некоторых столбцах), мы можем даже отобразить что-то вроде этого:

Доступны следующие преобразования типа SQL в тип Rust:

SQL typeRust type
diesel::type::Uuiduuid::Uuid
diesel::type::Textstd::string::String
diesel::types::Timestampchrono::NaiveDateTime

Добавление перехватчиков и фильтров в вывод ошибок Rust

Вы должны знать: помимо удобочитаемых сообщений об ошибках, которые я показал выше, Rust также может выводить ту же информацию, что и JSON. Я предлагаю создать новый инструмент CLI, который использует вывод JSON Rust (и, возможно, также Cargo), чтобы разрешить настраиваемые фильтры.

  1. Создайте библиотеку для анализа вывода JSON Rust (это структуры).
  2. Вытащите удобочитаемое форматирование ошибок из репозитория rust-lang / rust (я думаю, что оно живет здесь) и превратите его в библиотеку.
  3. Создайте инструмент (назовем его пока полировальным), который работает как сборка cargo --message-format json | полировка, то есть он читает JSON и отображает удобочитаемое представление.
  4. Добавьте аргумент --filter , который можно использовать (несколько раз), например, burnish --filter diesel_errors --filter clippy_explainer, который направляет JSON в предоставленный двоичный файл () перед тем, как сделать его доступным для чтения человеком.
  5. Автоматическое обнаружение библиотек, используемых в текущем проекте, а также автоматическая установка и применение полезных фильтров.

Вместо двух последних шагов можно также интегрировать все фильтры в сам инструмент.

Фильтры могут быть такими же простыми, как сопоставление с обычным выражением, и такими же сложными, как анализ исходного файла, на который имеется ссылка в JSON.

Очевидным недостатком этого подхода является необходимость постоянно обновлять диагностические данные Rust (насколько мне известно, ни JSON, ни удобочитаемое представление не стабильны), а также ошибки, которые фильтры должны распознавать.

Спасибо за чтение.