Mojo 1.0 закрепляет совместимость ветки 1.x и меняет правила работы с памятью

Mojo 1.0.0 вышел 11 августа 2026 года и впервые закрепил правила стабильности для языка и стандартной библиотеки. Релиз одновременно завершает крупную чистку синтаксиса перед эпохой 1.x: появились lambda, единый тип Pointer, более строгая проверка времени жизни ссылок и небольшой набор API с гарантией исходной совместимости.

Mojo 1.0
Mojo 1.0

Mojo дошёл до версии 1.0 спустя три года после первого публичного релиза, и самый интересный момент здесь связан со словом «стабильный». Modular объявила язык готовой основой для долгоживущих проектов, хотя стартовый набор API стандартной библиотеки со статусом stable пока специально оставлен небольшим. Вдобавок сама версия 1.0 содержит больше несовместимых изменений, чем обычный релиз: команда использовала последнюю возможность привести названия, правила и границы безопасности к единой модели до фиксации ветки 1.x.

Поэтому выпуск Mojo 1.0.0 интересен сразу с двух сторон. Для новых проектов появляется обещание более предсказуемой эволюции языка, а существующий код получает заметный пакет миграций, большинство из которых сопровождается устаревшими псевдонимами и автоматическими подсказками fix-it от компилятора.

Mojo 1.0 вводит правила стабильности для ветки 1.x

До версии 1.0 Mojo менялся очень быстро. Такая скорость помогала Modular проверять идеи языка на собственных продуктах MAX и Modular Cloud, но создавала постоянную нагрузку на авторов библиотек: очередной релиз мог потребовать переименований, переделки типов или обновления сигнатур.

С 1.0 команда вводит более формальную модель совместимости. API стандартной библиотеки, отмеченные как stable, не должны удаляться или меняться так, чтобы ломалась исходная совместимость. В рамках ветки 1.x развитие языка планируется в основном через добавление возможностей и осторожное управление изменениями.

Здесь есть существенная деталь: статус 1.0 пока не распространяется автоматически на всю стандартную библиотеку. Modular начала с ограниченного набора интерфейсов, для которых команда уже готова давать долгосрочные гарантии. Остальные части библиотеки продолжат развиваться и будут получать стабильный статус постепенно.

Разработчики Modular называют Mojo 1.0 «stable, production-ready language foundation». Это формулировка про базовые гарантии языка и его использование внутри инфраструктуры компании, а не обещание полной заморозки всех библиотечных API.

Стабильными стали базовые трейты и часть ключевых контейнеров

В первом стабильном наборе целиком зафиксированы трейты Deinitable, Movable, Copyable и ImplicitlyCopyable. Отдельные стабильные API появились у Array, List, Span, String, Bool и Optional.

Трейт в Mojo можно представить как контракт типа: он описывает набор возможностей, которым должен соответствовать объект. Стабилизация таких базовых контрактов особенно заметна для библиотек, потому что обобщённый код часто строится именно вокруг них.

Modular решила маркировать стабильность на уровне конкретных API. Один и тот же тип может содержать уже зафиксированные методы и интерфейсы, а рядом — элементы, которые ещё способны измениться в следующих выпусках 1.x. Такая схема оставляет команде пространство для развития стандартной библиотеки без обещания неизменности для всего её содержимого сразу.

lambda и обязательный var делают синтаксис Mojo более последовательным

Mojo 1.0 добавляет выражения lambda для коротких анонимных замыканий. Синтаксис напоминает Python, при этом параметры остаются типизированными в стиле Mojo.

Пример из официальных release notes:

var increment = lambda (x: Int) {} -> Int: x + 1

Такая lambda разворачивается в вложенную функцию def. Пустой список захватов {} указывает, что замыкание ничего не захватывает из внешней области видимости. Для захватывающих замыканий Mojo сохраняет собственную модель владения и времени жизни данных.

Другой заметный сдвиг связан с объявлениями переменных. Первая запись в новое имя теперь должна явно использовать var:

var x = 0

Старая форма x = 0 пока компилируется с предупреждением и подсказкой исправления. Для языка, который сочетает знакомый Python-подобный синтаксис с системным управлением ресурсами, такое правило убирает неоднозначность между созданием переменной и присваиванием уже существующей.

Ещё одно изменение касается литералов списков. Выражение вроде [1, 2, 3] по умолчанию создаёт Array[Int, 3], тогда как раньше использовался List. Array хранит фиксированное число элементов и позволяет избежать неявного выделения памяти в куче для простых литералов.

Единый Pointer переносит признак опасности на конкретную операцию

До 1.0 в Mojo существовали Pointer и UnsafePointer. Теперь они объединены в один тип Pointer, а потенциально опасные действия явно получают префикс unsafe_.

Например, прежние операции load(), store() и free() переходят к формам unsafe_load(), unsafe_store() и unsafe_free(). Старые имена пока сохранены как устаревшие псевдонимы и вызывают предупреждение компилятора. 

Сам факт хранения адреса памяти больше не делает весь объект отдельным «опасным» типом. Граница риска видна именно в месте, где код выполняет операцию без обычных гарантий проверки границ, владения или корректности адреса.

Одновременно Modular ужесточила работу с UnsafeAnyOrigin. Этот механизм позволяет отбросить информацию о происхождении указателя и тем самым ослабляет проверки времени жизни. Неявные расширения к UnsafeAnyOrigin выводятся из употребления, а некоторые формы больше не разрешены. Для низкоуровневого кода это делает обход проверок более заметным в исходнике.

Проверка времени жизни теперь видит ссылки внутрь контейнеров

Одна из самых технически интересных частей Mojo 1.0 — экспериментальный механизм interior origins. Он позволяет компилятору отслеживать ссылку на конкретный элемент внутри List, Dict, String и ряда других контейнеров.

Проблема знакома по системному программированию. Код получает ссылку на элемент динамического массива, затем добавляет новый элемент. Контейнер может перераспределить память, и прежняя ссылка начинает указывать в уже освобождённую область.

Release notes показывают такой сценарий:

var list = [1, 2, 3]
ref elem = list[0]

list.append(4)
print(elem)

После append() ссылка elem считается недействительной, если операция могла изменить внутреннее размещение контейнера. Компилятор отвергает последующее обращение вместо того, чтобы пропустить потенциально висячую ссылку.

Для Mojo это заметный шаг к более строгой модели памяти. Язык сохраняет низкоуровневый доступ, но расширяет объём ошибок, которые можно обнаружить во время компиляции.

Строки теперь итерируются по воспринимаемым символам

В 1.0 изменилось поведение обычного цикла по String. Итерация теперь идёт по графемным кластерам — последовательностям кодовых точек Unicode, которые человек воспринимает как один отображаемый символ.

Разница проявляется на эмодзи, символах с комбинируемыми диакритическими знаками и некоторых письменностях. Один визуальный знак способен состоять из нескольких кодовых точек Unicode, поэтому обход по байтам или отдельным code point может разрезать его на части.

Вместе с этим некорректный непрерывный срез больше не «подправляется» молча: при ошибочных границах программа завершает работу. range() отвергает неподходящие типы и формы с плавающей точкой, которые могли приводить к бесконечным циклам. В size_of() исправлен расчёт размера для типов с повышенными требованиями к выравниванию — прежнее поведение могло привести к повреждению памяти внутри List.

Python-интероперабельность ускорилась на горячих операциях

Mojo сохраняет связь с экосистемой Python через PythonObject, и в версии 1.0 команда переработала выполнение арифметики, сравнений и проверки принадлежности.

Раньше такие операции могли проходить через поиск Python-атрибута и вызов связанного метода. Теперь Mojo обращается к абстрактным протоколам CPython напрямую. По данным официального changelog, этот путь примерно в 12 раз быстрее на соответствующих interop-операциях.

Речь идёт именно о накладных расходах слоя взаимодействия с Python для перечисленных операторов. Цифра 12× не описывает ускорение произвольной программы целиком: итог зависит от того, сколько времени конкретное приложение проводит внутри таких переходов между Mojo и Python.

Граница между Mojo и MAX стала заметнее

В 1.0 часть API для программирования ускорителей переместилась из стандартной библиотеки Mojo в отдельный пакет max. В частности, переехали части std.gpu.compute, std.gpu.host, std.gpu.memory и std.gpu.sync; пакет layout теперь поставляется вместе с MAX.

Некоторые низкоуровневые GPU-интерфейсы при этом остаются в стандартной библиотеке Mojo. Разделение показывает архитектурную линию Modular: сам язык развивается как системный и общего назначения, а более специализированная инфраструктура ускорителей группируется вокруг MAX.

Изменились и допустимые типы для передачи в GPU-ядра. Int и UInt больше не соответствуют DevicePassable, поскольку их размер зависит от платформы. Если хост и ускоритель используют разную ширину такого типа, код способен получить неверную интерпретацию данных. Для границы CPU–GPU теперь нужны фиксированные типы вроде Int32.

Mojo 1.0 завершает большую волну переименований

Перед фиксацией ветки 1.x команда привела к общей системе несколько терминов, которые накопились за предыдущие версии.

Среди заметных изменений:

  • InlineArray переименован в Array;
  • StringSlice получил имя StringSpan;
  • ImplicitlyDestructible заменён на Deinitable;
  • деструктор теперь пишется как __deinit__() вместо __del__();
  • во многих API size заменяется на length;
  • соглашение аргумента read переименовано в imm;
  • Int теперь является псевдонимом Scalar[DType.int];
  • разные семейства range() сведены к одной модели, параметризованной dtype.

Большинство старых имён пока остаются в виде deprecated-алиасов. Компилятор сопровождает многие случаи fix-it-подсказками, поэтому значительная часть миграции сводится к механическим заменам. Разработчики проекта прямо предупреждают, что 1.0 содержит больше breaking changes, чем типичный выпуск.

LSP стал надёжнее, а диагностика ограничений — понятнее

Вместе с языком команда доработала mojo-lsp-server, который отвечает за подсветку ошибок, навигацию и другие функции редакторов вроде VS Code. Modular описывает LSP в 1.0 как заметно более стабильный и надёжный.

Одна из причин — отключение проверки фрагментов кода внутри docstring по умолчанию. Этот механизм давал ложные диагностические сообщения и опирался на нестабильные части LSP. Его можно включить отдельным параметром -check-docstrings.

У where-ограничений появился строковый текст ошибки. Библиотека или обобщённая функция может связать условие с конкретным пояснением, которое компилятор покажет при нарушении ограничения:

def foo[sc: Int]() where (sc > 1, "scaling factor must be greater than 1"):
    ...

Такой механизм особенно заметен в шаблонном и обобщённом коде, где раньше сообщение компилятора могло показывать длинную цепочку несоответствий типов без объяснения исходного требования автора API.

Компилятор Mojo обещают открыть в 2026 году

Релиз 1.0 не завершает план Modular по открытию исходного кода. Стандартная библиотека уже развивается открыто: по данным компании, почти 200 участников сообщества внесли более 1100 pull request и изменили свыше 200 тысяч строк.

Для компилятора и toolchain компания сохраняет отдельное обещание — открыть их исходный код в течение 2026 года. Точная дата в анонсе 1.0 не названа. Дополнительные планы по Mojo, MAX и open source Modular собирается обсуждать на ModCon 18 августа.

За пределами 1.0 в дорожной карте остаются асинхронная модель, pattern matching, unions и другие возможности. Часть будущих изменений сможет появляться внутри 1.x с сохранением совместимости, а более глубокие изменения языка компания связывает с будущей веткой 2.0.

Mojo 1.0 фиксирует основу языка, а стабильная поверхность ещё будет расти

На 11 августа 2026 года Mojo получил финальную версию 1.0.0, правила совместимости для стабильных API и крупную последнюю волну упорядочивания синтаксиса перед развитием 1.x. В одном релизе сошлись lambda, явные объявления var, единый Pointer, interior origins, переработанные строки, ускоренный Python interop и перенос части GPU-инфраструктуры в MAX.

При этом объём API стандартной библиотеки со статусом stable пока ограничен несколькими базовыми трейтами и частями ключевых типов. Следующие выпуски 1.x должны постепенно расширять эту поверхность.

Компания Modular пока не раскрыла точные сроки публикации исходного кода компилятора и toolchain. Согласно их информации, это должно произойти не раньше 2026 года. Следующий раз, когда они планируют поделиться новыми деталями, — это ModCon, который состоится 18 августа.

При использовании материалов сайта необходимо указывать ссылку на TGLand.ru. Если вы копируете фрагменты текста в интернете, прямая гиперссылка, доступная для индексации поисковыми системами, должна быть размещена в начале материала.