Как читать ошибки компилятора
Питонист привыкает к ошибкам во время выполнения: запустил, упало, посмотрел трейсбек. В Mojo большинство ошибок вылезает до запуска, и выглядят они непривычно — иногда на пол-экрана. Пугаться не нужно: структура у них жёсткая, и читать их можно быстро.
Приятная особенность Mojo 1.0: компилятор часто пишет прямо в сообщении,
как чинить. Не «type mismatch», а «используйте x[len(x) - 1]».
Анатомия сообщения
Заголовок раздела «Анатомия сообщения»Вот типичная ошибка целиком:
main.mojo:4:15: error: invalid call to '__add__': value passed to 'rhs'cannot be converted from 'Int' to 'Float64' print(a + b) ~~~~^oss/modular/mojo/stdlib/std/builtin/simd.mojo:1034:1: note: function declared heredef __add__(self, rhs: Self) -> Self # note - synthetic signature^Разбираем по частям:
| Часть | Что означает |
|---|---|
main.mojo:4:15 | Файл, строка, колонка. Именно здесь компилятор споткнулся |
error: | Сама проблема. Читается как обычное предложение |
print(a + b) | Ваш код — чтобы не переключаться в редактор |
~~~~^ | Подчёркивание: ^ показывает точное место, ~ — участвующее выражение |
note: | Дополнительный контекст: где объявлено то, что не подошло |
Ключевое правило: note — это не отдельные ошибки. Это пояснения
к одной ошибке. Одна ошибка может тащить за собой десяток note.
Читайте первую ошибку, а не последнюю
Заголовок раздела «Читайте первую ошибку, а не последнюю»Компилятор часто выдаёт несколько ошибок подряд, но вторая и третья обычно следствия первой. Порядок действий такой:
- Найдите первое
error:в выводе. - Посмотрите на номер строки и подчёркивание.
- Почините.
- Соберите снова — и очень часто остальные ошибки исчезнут сами.
Пути вида oss/modular/... — это не ваш код
Заголовок раздела «Пути вида oss/modular/... — это не ваш код»oss/modular/mojo/stdlib/std/collections/list.mojo:428:1: note: candidate not viableТакие пути ведут в исходники стандартной библиотеки Mojo. Их упоминание означает не «сломалась стандартная библиотека», а «вот как объявлено то, что вы пытались вызвать». Ошибка при этом ваша — в строке, указанной первой.
Список кандидатов: «candidate not viable»
Заголовок раздела «Список кандидатов: «candidate not viable»»Самое пугающее с виду сообщение. Возникает, когда у функции или конструктора несколько вариантов (перегрузок), и ни один не подошёл:
main.mojo:9:37: error: no matching function in initialization var measurements = List[Float64](21.5, 23.0, 19.8, 24.2) ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~list.mojo:428:1: note: candidate not viable: unexpected argumentdef __init__(out self)list.mojo:435:1: note: candidate not viable: missing required argument: 'capacity'def __init__(out self, *, capacity: Int)list.mojo:450:1: note: candidate not viable: missing required argument: 'length'def __init__(out self, *, length: Int, fill: T)...Читается это так: «я знаю восемь способов создать List, покажу каждый
и почему он не подошёл». Дальше вы просматриваете список и ищете тот
вариант, который хотели. В примере выше подходящего конструктора
«просто перечислить значения» нет вовсе — значит, создавать список надо
иначе, литералом:
var measurements: List[Float64] = [21.5, 23.0, 19.8, 24.2]Компилятор часто пишет готовое решение
Заголовок раздела «Компилятор часто пишет готовое решение»В Mojo 1.0 многие сообщения содержат прямую инструкцию. Стоит дочитывать до конца, прежде чем лезть в поиск:
note: constraint failed: negative indexing is not supported, use e.g. `x[len(x) - 1]`
error: unparenthesized lambda arguments are not supported; write them in parentheses, with types, e.g. `lambda (x: Int, y: Int) -> Int: x + y`
error: use of unknown declaration 'Python'; did you mean to import it from 'std.python'? Add 'from std.python import Python'
Частые сообщения и что они значат
Заголовок раздела «Частые сообщения и что они значат»| Сообщение | По-русски | Что делать |
|---|---|---|
use of unknown declaration 'x' | Имя x компилятору неизвестно | Опечатка или забытый импорт |
'String' value has no attribute 'uppercase' | У типа нет такого метода | Проверьте название: upper(), а не uppercase() |
argument type must be specified | У аргумента не указан тип | Допишите аннотацию |
invalid call to 'add': unexpected argument | Лишний аргумент при вызове | Сверьтесь с сигнатурой в note ниже |
cannot be converted from 'Int' to 'Float64' | Нет неявного преобразования | Приведите явно: Float64(x) |
cannot call function that may raise in a context that cannot raise | Вызов «бросающей» функции из «небросающей» | Добавьте raises в сигнатуру или оберните в try |
value ... cannot be implicitly copied | Тип не разрешает неявное копирование | a^, a.copy() или трейт ImplicitlyCopyable |
expressions must not appear at file scope | Код вне функции | Перенесите в def main() |
classes are not supported yet | class в языке нет | Используйте struct |
failed to parse the provided Mojo source module | Итоговая строка после ошибок разбора | Игнорируйте, смотрите выше |
failed to run the pass manager | Итоговая строка после ошибок этапа компиляции | То же самое |
Предупреждения тоже читайте
Заголовок раздела «Предупреждения тоже читайте»warning: не мешает сборке, но обычно означает, что конструкция скоро
перестанет работать:
warning: implicit declaration of 'left' is deprecated;add 'var' before the assignment targetТакие предупреждения — бесплатная страховка от будущих поломок. Чините их сразу, пока это одна строка, а не сотня.
Если сообщение непонятно совсем
Заголовок раздела «Если сообщение непонятно совсем»-
Упростите пример. Выкиньте всё лишнее, пока не останется 5–10 строк, которые всё ещё не собираются. Часто на этом шаге причина становится очевидной без всякой посторонней помощи.
-
Проверьте, не устарел ли код. Если вы взяли его из статьи или у нейросети, велика вероятность, что он написан до Mojo 1.0 — см. Устаревшие конструкции.
-
Спросите. Форум Modular — там отвечают в том числе разработчики языка. Приложите минимальный пример, полный текст ошибки и вывод
mojo --version.
🎯 Проверь себя
В выводе десять строк с `note:` и одна с `error:`. Сколько у вас ошибок?
Одна. Строки note — это пояснения к ней: где объявлена функция, какие
были варианты и почему они не подошли.
Компилятор указывает на файл `oss/modular/mojo/stdlib/std/collections/list.mojo`. Значит, баг в стандартной библиотеке?
Нет. Так компилятор показывает, как объявлено то, что вы вызывали. Ошибка — в вашем файле, он указан в первой строке сообщения.
Вышло пять ошибок сразу. С какой начинать?
С первой. Остальные часто — её последствия и исчезают сами после исправления.
Что дальше
Заголовок раздела «Что дальше»Разобрались с ошибками — можно спокойно писать код: дальше начинается базовый синтаксис Mojo.
Тексты курса — CC BY-NC-SA 4.0, код примеров — Apache 2.0