Что именно считается переломным изменением библиотечного ящика?

Ящики для ржавчины используют Semantic Versioning. Как следствие, каждый выпуск с критическим изменением должен приводить к значительному увеличению версии. Разрывное изменение обычно считается чем-то, что может сломать нижележащие ящики (код зависит от рассматриваемой библиотеки).

Тем не менее, в Rust у всего есть потенциал для разрушения ящиков вниз по течению. Например, изменение (включая простое добавление) набора общедоступных символов, возможно, является критическим изменением, поскольку нижестоящие ящики могут использовать glob-import (use foo::*;) перетащить символы нашей библиотеки в их пространство имен. Таким образом, добавление символов может также сломать зависимые ящики; посмотрите этот пример.

Аналогичным образом, изменение (добавление или изменение версии) набора наших зависимостей может нарушить последующие сборки. Вы также можете себе представить, что нижняя корзина зависит от определенного размера одного из наших открытых типов. Это редко, если вообще полезно; Я просто хочу показать: все может быть серьезным изменением, если только нижняя корзина будет стараться изо всех сил.

Есть ли какие-либо рекомендации по этому поводу? Что именно считается переломным изменением, а что нет (потому что это считается "ошибкой пользователя")?

1 ответ

Решение

Существует Rust RFC на эту тему: RFC 1105: API Evolution. Это применимо к любому проекту библиотеки Rust и охватывает все виды изменений (не только прерывание изменений) и то, как они влияют на семантическое управление версиями. Я постараюсь обобщить ключевые моменты из RFC, чтобы не делать этот ответ ответом только на ссылку.:)

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

Ключевым атрибутом незначительного изменения является то, что должен быть способ, которым клиенты могут избежать поломки заранее, слегка изменив свой исходный код (например, изменить глобальный импорт на импорт без глобальных данных, устранить неоднозначность неоднозначного вызова с помощью UFCS и т. Д.).) таким образом, чтобы код был совместим с версией до изменения и с версией, которая включает изменение (при условии, что это второстепенный выпуск). Незначительное изменение также не должно заставлять нижележащие ящики вносить серьезные разрушающие изменения, чтобы устранить поломку.


Основные изменения, определенные в RFC (по состоянию 721f2d74) являются:

  • Переключение вашего проекта с совместимости со стабильным компилятором на совместимость только с ночным компилятором.
  • Переименование, перемещение или удаление любого публичного элемента в модуле.
  • Добавление приватного поля в структуру, когда все текущие поля являются открытыми.
  • Добавление открытого поля в структуру, которая не имеет закрытых полей.
  • Добавление новых вариантов в перечисление.
  • Добавление новых полей в перечислимый вариант.
  • Добавление ненастроенного предмета в черту.
  • Любое нетривиальное изменение подписи элемента черты.
  • Реализация фундаментальной черты в существующем типе.
  • Ужесточение границ существующего параметра типа.
  • Добавление или удаление аргументов для функции.
  • Любое другое критическое изменение, которое не указано как незначительное изменение в RFC.

Незначительные изменения, определенные в RFC (по состоянию на коммит 721f2d74, если не указано иное):

  • Изменение использования функций груза на ящике.
  • Добавление новых общедоступных элементов в модуль.
  • Добавление или удаление приватных полей в структуре, когда хотя бы одно из них уже существует (до и после изменения) [не нарушая].
  • Превращение структуры кортежа со всеми частными полями (по крайней мере, с одним полем) в обычную структуру или наоборот.
  • Добавление дефолтного предмета в черту.
  • Добавление параметра типа по умолчанию в черту [не ломается].
  • Реализация любой неосновной черты в существующем типе.
  • Добавление любого элемента в свойственный impl,
  • Изменение недокументированного поведения функции.
  • Ослабление границ для существующего параметра типа [не нарушая].
  • Добавление параметров типа по умолчанию к типу или признаку [не нарушается].
  • Обобщение существующего поля struct или enum путем замены его типа новым параметром типа, который по умолчанию равен предыдущему типу [прерывание до устранения проблемы 27336 ].
  • Введение нового параметра типа в существующую функцию.
  • Обобщение параметра или возвращаемого типа существующей функции путем замены типа новым параметром типа, который может быть создан для предыдущего типа.
  • Представляем новые предупреждения / ошибки.

См. RFC для объяснений и примеров.

Другие вопросы по тегам