Додаток G - як робиться Rust і "щонічний Rust"

Цей додаток розповідає про те, як робиться Rust і як це впливає на вас як на розробника на Rust.

Стабільність без застою

Як мова, Rust багато піклується про стабільність вашого коду. Ми хочемо, щоб Rust був якомога надійнішим фундаментом, на якому ви зможете будувати, і якби все постійно змінювалося, це було б неможливо. У той самий час ми, якщо ми не зможемо експериментувати з новим функціоналом, то можемо пропустити важливі недоліки аж до їхнього релізу, коли ми вже не зможемо це змінити.

Наше розв'язання цієї проблеми - це те, що ми звемо "стабільність без застою", і наш керівний принцип такий: ви ніколи не маєте боятися оновлення до нової версії стабільного Rust. Кожне оновлення має бути безболісним, але також має приносити нові можливості, менше помилок і швидший час компіляції.

Ту-туу! Канали оновлення і залізничний розклад

Розробка Rust відбувається за залізничним розкладом. Тобто вся розробка робиться в гілці master репозиторію Rust. Релізи слідують залізничній моделі випусків програмного забезпечення (software release train model), яку використовують Cisco IOS та інші проєкти програмного забезпечення. Існують три канали релізів Rust:

  • Щонічний (nightly)
  • Бета (beta)
  • Стабільний (stable)

Більшість розробників Rust в переважно використовують стабільний канал, але ті, хто хоче спробувати експериментальні нові функції, можуть використовувати щонічний або бету.

Ось приклад того, як працює процес розробки та релізів: припустімо, що команда Rust працює над релізом Rust 1.5. Цей реліз відбувся у грудні 2015 року, але він забезпечить нам реалістичні номери версій. У Rust додається новий функціонал: новий коміт з'являється у гілці master. Кожної ночі виробляється нова щонічна версія Rust. Кожен день відбувається реліз, і ці релізи створюються автоматично нашою інфраструктурою релізів. Тож із плином часу наші релізи виглядають ось так, по одному за ніч:

nightly: * - - * - - *

Кожні шість тижнів настає час підготувати новий реліз! Гілка beta у репозиторію Rust відгалужується від гілки master, що належить щонічній версії. Тепер є два релізи:

nightly: * - - * - - *
                     |
beta:                *

Більшість користувачів Rust не використовують бета-релізи активно, а лише тестують на беті у своїх системах неперервної інтеграції (CI), щоб допомогти Rust знайти можливі регресії. Тим часом нові щонічні релізи з'являються кожної ночі:

nightly: * - - * - - * - - * - - *
                     |
beta:                *

Припустимо, було знайдено регресію. Добре, що ми мали якийсь час для перевірки бета-релізу перед тим, як регресія прокралася до стабільного реліз! Виправлення застосовується до master, тож тепер щонічна версія виправлена, а потім виправлення переноситься (backport) у бета-гілку і робиться реліз:

nightly: * - - * - - * - - * - - * - - *
                     |
beta:                * - - - - - - - - *

Шість тижнів минуло після створення першої бети, настав час для стабільної версії! Стабільна гілка робиться з гілки beta:

nightly: * - - * - - * - - * - - * - - * - * - *
                     |
beta:                * - - - - - - - - *
                                       |
stable:                                *

Ура! Rust 1.5 зроблено! Проте ми забули одну річ: оскільки минуло шість тижнів, нам також потрібна нова бета наступної версії Rust, 1.6. Тож після того, як стабільна версія відгалужується від бети, наступна версія бети знову відгалужується від щонічної версії:

nightly: * - - * - - * - - * - - * - - * - * - *
                     |                         |
beta:                * - - - - - - - - *       *
                                       |
stable:                                *

Це зветься "залізничною моделлю", тому що кожні шість тижнів реліз "залишає станцію", але все ще потрібно здійснити подорож в бета-каналі, перш ніж він прибуде як стабільна версія.

Релізи Rust випускаються що шість тижнів, як годинник. Якщо ви знаєте дату одного релізу Rust, то можете дізнатися дату наступного: за шість тижнів. Гарний аспект запланованих що шість тижнів релізів полягає в тому, що наступний потяг прибуде незабаром. Якщо певний функціонал пропускає якийсь певний реліз, немає потреби хвилюватися: інший відбудеться за короткий час! Це допомагає зменшити тиск, що хтось спробує протягти, можливо, недошліфований функціонал близько до строку релізу.

Завдяки цьому процесу, ви завжди можете перевірити наступну збірку Rust і впевнитись, що до неї легко оновитися: якщо бета реліз не працює так, як очікувалося, ви можете повідомити про це команді, і його відремонтують до наступного стабільного релізу! Аварії в бета релізі порівняно рідкісні, але rustc є лише програмою, і вади існують.

Нестабільний функціонал

Є ще одна хитрість у цій моделі релізів: нестабільний функціонал. Rust використовує техніку, що зветься "прапорці функціонала", щоб визначити, який функціонал увімкнено в даному релізі. Якщо новий функціонал перебуває в активній розробці, він опиняється в master, а, відтак, у щонічних релізах, але поза прапорцем функціонала. Якщо ви, як користувач, захочете спробувати функціонал, над яким ведеться робота, то можете це зробити, але ви маєте використовувати нічний реліз Rust і позначити свій вихідний файл відповідним прапорцем, щоб погодитися на цей функціонал.

Якщо ви використовуєте бета або стабільний реліз Rust, то не можете використовувати прапорці функціонала. Це ключ, що дозволяє нам отримати практичний досвід нового функціонала до того, як його оголосять стабільним назавжди. Ті, хто бажає бути на передньому краю, можуть підписатися на це, а ті, хто бажає надійного досвіду, може залишитися на стабільному релізі і знати, що їхній код не зламається. Стабільність без застою.

Ця книга містить інформацію лише про стабільний функціонал, оскільки в процесі функціонал все ще змінюється, і, безумовно, він буде різним у той час, коли була написана ця книжка, і коли він буде включеним до стабільних збірок. Ви можете знайти документацію про функціонал, доступний лише в щонічних релізах, онлайн.

Rustup і роль щонічного Rust

Rustup дозволяє легко перемикатися між різними каналами релізів Rust, глобально чи для окремих проєктів. За замовчуванням буде встановлено стабільний Rust. Для встановлення, наприклад, щонічного, запустіть:

$ rustup toolchain install nightly

Ви також можете побачити всі ланцюжки інструментів (toolchain, релізи Rust і пов’язаних компонентів), що ви встановили за допомогою rustup. Ось приклад на комп'ютері одного з авторів з Windows:

> rustup toolchain list
stable-x86_64-pc-windows-msvc (default)
beta-x86_64-pc-windows-msvc
nightly-x86_64-pc-windows-msvc

Як ви можете бачити, стабільний ланцюжок інструментів є замовчуванням. Більшість користувачів Rust використовують переважно стабільний реліз. Ви можете використовувати стабільний реліз більшу частину часу, але використовувати щонічний у конкретному проєкті, якщо вам потрібен функціонал з переднього краю. Для цього, ви можете запустити rustup override в теці цього проєкту, щоб встановити щонічний ланцюжок інструментів для використання rustup, коли ви в цій теці:

$ cd ~/projects/needs-nightly
$ rustup override set nightly

Відтепер кожного разу як ви викликаєте rustc чи cargo всередині ~/projects/needs-nightly, rustup переконається, що ви використовуєте щонічний Rust, а не стабільний Rust за замовчуванням. Це стає в пригоді, коли ви маєте багато проєктів Rust!

Процес і команди RFC

То як же вам дізнатися про цей новий функціонал? Модель розробки Rust слідує процесу "прохання прокоментувати (RFC, Request For Comments). Якщо ви хочете покращення в Rust, то можете написати пропозицію, що зветься RFC.

Будь-хто може написати RFC для покращення Rust, і пропозиції розглядаються і обговорюються командою Rust, що складається з багатьох тематичних підкоманд. Повний список команд знаходиться на вебсайті Rust і включає команди для кожної області проєкт: дизайн мови, реалізація компілятора, Інфраструктура, документація та інші. Відповідна команда читає пропозицію і коментарі, пише деякі власні коментарі, і врешті-решт виникає консенсус - прийняти або відхилити цей функціонал.

Якщо функціонал буде прийнятий, то в репозиторії Rust відкривається задача, і хтось може їх виконати. Особа, що реалізує функціонал цілком може бути не тою особою, що його взагалі запропонувала! Коли реалізація готова, вона додається в гілку master за бар'єром функціонала, про який ми говорили в підрозділі "Нестабільний функціонал" .

За деякий час, коли розробники Rust, які використовують щонічні релізи, зможуть спробувати новий функціонал, члени команди обговорять, як функціонал працює на щонічному релізі, і вирішать, чи варто перенести його в стабільний Rust чи ні. Якщо буде ухвалено рішення просуватися, то бар'єр функціонала знімають, і функціонал тепер вважається стабільним! І він їде залізницею у новий стабільний реліз Rust.