То, что начиналось как маленький побочный проект на ноутбуке одного разработчика — сегодня стало одним из самых успешных языков программирования с открытым исходным кодом, которым пользуются Microsoft, Amazon, Google, Tesla, Discord и многие другие.


Если кто не знает эту историю — велком.


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


Семнадцать лет назад программист из Mozilla Грейдон Хоар вернулся с работы и обнаружил, что лифт в его доме вышел из строя. Он был вынужден подниматься на двадцать первый этаж, проклиная всё на свете. А потом узнал, что лифт не работал из-за сбоя программного обеспечения. Тогда он решил попробовать сделать язык программирования, который сводил бы такие ошибки к нулю. Чтобы даже начинающий разработчик мог бы написать код, который не зависал.




Хоар выплеснул все свои разочарования в код и за несколько месяцев создал основу для простого и гибкого языка, рассчитанного на минимизацию ошибок памяти и предотвращение таких проблем, как поломка его лифта. Он назвал его Rust («ржавчина») — в честь ржавчинных грибов, славящихся своей выносливостью и способностью выживать в любых условиях.


Дело в том, что старые языки программирования, такие как C и C++ (которым больше сорока лет), имеют характерные недостатки. С одной стороны, они обеспечивают гибкость в плане разработки кода и дают в руки пользователя ряд инструментов, позволяющих создавать самые разные программы для чего угодно, от автомобилей и дефибрилляторов — до Windows и Android. Но с другой стороны — они требуют от разработчиков тщательного управления транзакциями памяти. Отсутствие учета состояния этих транзакций легко может привести к сбою или нестабильностям в работе приложения.


Чтобы облегчить бремя постоянного управления памятью, такие языки как Java представили концепцию «сборщиков мусора». Эти сборщики предназначены для периодической очистки системной памяти, сводя к минимуму риск ошибок памяти. Однако это происходит за счет более высокого общего использования памяти и большего потребления ресурсов системы — для постоянного поддержания работоспособности сборщиков.


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


Ошибки типа переполнения буфера и выхода за пределы массива в языке стали невозможны в принципе. А ведь как раз подобные (человеческие) ошибки в языках с ручным управлением памятью типа С и С++ и приводили к самым опасным уязвимостям вроде удаленного выполнения кода.




Mozilla взяла Rust на вооружение и начала спонсировать проект в 2009 году — в рамках разработки экспериментального быстрого браузерного движка под названием Servo. Этот проект был официально анонсирован компанией в 2010-м. С тех пор язык Rust стал широко поддерживаемым проектом с открытым исходным кодом, используемым для всего, от ПО для лифтов — до масштабных приложений, решающих задачи масштаба Microsoft и Amazon.


К 2013 году сторонники языка усовершенствовали систему управления памятью Rust до такой степени, что она больше вообще не требовала функции сборщика мусора. Язык очень активно развивался и получал поддержку от разработчиков по всему миру, что привело к выпуску первого официального стабильного релиза Rust в мае 2015 года.



Народная любовь


В январе 2014 года главный редактор компьютерного журнала Dr. Dobb's Journal Эндрю Бинсток прокомментировал шансы Rust стать полновесным конкурентом C++. По словам Бинстока, хотя Rust «многие считают удивительно элегантным языком», его внедрение замедлилось, потому что он чересчур сильно менялся между версиями.


Но популярность Rust после его официального релиза в 2015 году росла фантастическими темпами. Несмотря на свою молодость, Rust быстро вошел в число самых популярных языков программирования. Например, в индексе сообщества программистов TIOBE в июле 2019 года он занимал 33-е место, а уже к июлю 2020 года поднялся на 18-е. Точно так же, согласно опросу разработчиков Stack Overflow, Rust является «самым любимым» языком опрошенных с 2016 года. Его любят 86% разработчиков, на втором месте — TypeScript с одобрением 67%, на третьем — Python с 66,7%.



В опросе Stack Overflow показывается процент тех, кто разрабатывает с помощью языка или технологии и выражает заинтересованность в продолжении разработки с их помощью


В результате многие программисты теперь видят в Rust серьезную альтернативу C и C++ даже в сферах, где эти языки доминировали. Дэйв Херман, соучредитель Mozilla Research, расписал некоторые из преимуществ языка в своем посте:


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


Что сейчас


В бизнес-мире на одной любви не прожить. А поскольку у Mozilla сейчас не самые лучшие времена, в том числе из-за давления со стороны Chrome и Edge, то и развитие нового языка оказалось под угрозой.


В августе 2020 года Mozilla уволила 250 из 1000 своих сотрудников в рамках корпоративной реструктуризации, вызванной пандемией. Команда разработчиков Servo, браузерного движка, написанного на Rust, была тогда полностью расформирована. Это вызвало обеспокоенность по поводу будущего Rust, поскольку члены команды вносили активный вклад в разработку и поддержку языка.


На следующей неделе основная команда Rust признала серьезные последствия увольнений и объявила о планах по созданию фонда поддержки Rust. Первой целью фонда было стать владельцем всех товарных знаков и доменных имен, относящихся к языку, и взять на себя финансовую ответственность за их стоимость.




8 февраля 2021 года пять компаний-основателей (AWS, Huawei, Google, Microsoft и Mozilla) объявили о создании Rust Foundation. В сообщении в блоге, опубликованном в апреле того же года, Google заявила о поддержке Rust в рамках Android Open Source Project в качестве альтернативы C и C++. Низкоуровневый код для Android теперь в самой Google пишется на Rust.


К 2022 году размер сообщества Rust увеличился втрое и превысил три миллиона пользователей. Его включили в рекомендованный Агентством национальной безопасности США список безопасных для памяти языков. Rust поставили в один ряд с другими хорошо зарекомендовавшими себя языками, такими как Java, C# и Ruby.


Сейчас использование Rust продолжает расти, особенно в автомобильной и аэрокосмической промышленности, где критически важно, чтобы ничего не сломалось. Язык также любят многие крупные ИТ-компании, включая Microsoft, Amazon и Dropbox. За счет этого использование Rust продолжает расти, уменьшая общую зависимость разработчиков от C и C++, которые считаются менее безопасными, особенно в руках неопытных программистов.


От программирования лифтов — к запуску космических ракет и электрокаров. Неплохо для «ржавчины».


По мотивам.




P.S. Хотите работать над крутыми проектами? Лучшие вакансии — в телеграм-боте getmatch. Тысячи предложений от топовых компаний. Указываете нужную вилку зарплаты, и бот выдает вам лучшие предложения, и помогает пройти интервью. Всё бесплатно.


Комментарии (48)


  1. Zhbert
    00.00.0000 00:00
    +62

    На фотке Торвальдс же?


    1. plFlok
      00.00.0000 00:00
      +14

      что особенно иронично если учесть, как Торвальдс сопротивлялся внедрению rust в код ядра линукса.


      1. slonoten
        00.00.0000 00:00
        +4

        А фотография попала из этой статьи https://www.techspot.com/news/96037-rust-programming-language-join-linux-kernel.html


      1. Rrs
        00.00.0000 00:00
        +32

        Вроде он сопротивлялся только появлению C++, для rust он выкатил список требований, которые они и удовлетворили.


        1. u007
          00.00.0000 00:00
          +1

          А есть подробности? Интересно почитать, но не гуглится этот список



      1. Halt
        00.00.0000 00:00
        +3

        Настолько сопротивлялся что вкатили поддержку в апстрим 6.1, в 6.3 будут готовы вливать драйверы.


    1. aamonster
      00.00.0000 00:00
      +12

      Это иллюстрация к "сводить ошибки к нулю" :-D


  1. lain8dono
    00.00.0000 00:00
    +7

    Кстати servo недавно ожил.


    1. domix32
      00.00.0000 00:00
      +3

      Не сказать, что он умирал. Оксидация FF имеет довольно неплохой план и servo его пророк.


      1. lain8dono
        00.00.0000 00:00
        +8

        https://servo.org/blog/

        Новости идут до 2020-11-17 и потом два обновления 2023-01-16 и 2023-02-03. Два года перерыва.


      1. Halt
        00.00.0000 00:00

        После очередного административного апокалипсиса в Мозилле, дело почти заглохло. Stylo впилили, парсер медиафайлов влили, WebRender влили уже года полтора назад, но все так не выберется.

        Целиком Servo никто в FF тащить не будет.


  1. ElVibrio
    00.00.0000 00:00
    +29

    Интересно наблюдать, как мифологизация становится значимой частью Computer Science.

    ...когда был Торвальдс маленький, с кудрявой головой

    Он тоже бегал в валенках по горке ледяной!


    1. ProstoTyoma
      00.00.0000 00:00
      +5

      становится

      "Just For Fun" была издана в 2001 году )


  1. a14e
    00.00.0000 00:00
    +6

    Возможно я не в курсе про какую-то концепцию. Но я не помню, чтобы в C/C++ было понятие транзакций памяти. Ссылка на статью в Вики про транзакционную память -- это совершенно другое понятие, которое к ручному менеджменту памяти имеет весьма опосредованное отношение


  1. SergeyTatevosyan
    00.00.0000 00:00
    +4

    Можно подумать что все ошибки при написании кода сводятся к ошибкам при работе с памятью. Это просто фишка языка, которая есть почти у любого другого языка.


    1. DirectoriX
      00.00.0000 00:00
      +5

      которая есть почти у любого другого языка
      Эти «почти все» другие языки в основном обеспечивают безопасную работу с памятью через сборку мусора, что накладывает свои ограничения и создаёт свои проблемы. А в Rust — безопасная память через принудительное RAII.
      RAII в некоторой степени помогает работать и другим фишкам языка, например fearless concurrency (при захвате мьютекса создаётся MutexGuard, который автоматически разрушается при выходе из области видимости, и вместе с этим разблокирует мьютекс).


      1. SergeyTatevosyan
        00.00.0000 00:00
        +4

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


      1. mikhanoid
        00.00.0000 00:00
        +3

        Будто подход Rust не накладывает своих ограничений и не создаёт проблем. Впорос только в том, какие ограничения удобнее, и какие проблемы менее болезнены.


        1. DirectoriX
          00.00.0000 00:00
          +2

          Дайте угадаю, вы опять хотите поведать о том, что в Rust без unsafe нельзя сделать базовые структуры данных, поэтому этот язык не пригоден для серьёзной разработки?


          1. staticmain
            00.00.0000 00:00
            +1

            Простите, но если сам язык создавался для того чтобы в нем не было небезопасных мест то факт того, что в нем нельзя создать двусвязный список без unsafe - это ужасно. И политика "говорящих голов", что двусвязные списки не нужны, потому что есть массивы - это показатель уровня разработчиков.


            1. DirectoriX
              00.00.0000 00:00
              +7

              Так всё дело в том, что «правильный» двусвязный список не ложится в концепцию владения, потому что у каждого узла получается два равноправных обладателя.
              Но двусвязные списки всё же есть, причём в стандартной библиотеке. Да, под капотом у них unsafe, но публичный интерфейс полностью доступен из safe-подмножества. Можно долго спорить, считается это «честной» реализацией или нет, но тогда давайте не забывать, что где-то в глубине стека вызовов всё равно нет-нет, да и происходит обращение к ядру ОС, которое unsafe просто потому что FFI.


              1. staticmain
                00.00.0000 00:00

                С этим никто не спорит, но ведь тогда нельзя говорить, что это безопасно, если под капотом все равно unsafe linux/windows ядро. На любом шаге может быть факап, начиная с ядра и заканчивая условным libxml2


                1. DirectoriX
                  00.00.0000 00:00
                  +3

                  Именно так, полная безопасность недостижима, ведь даже если ПО будет без багов, то всё равно может произойти аппаратный сбой.
                  Но это не означает, что к безопасности и стабильности не надо стремиться. Те же языки со сборкой мусора (с которых +- начался этот тред) именно поэтому и появились: работать с памятью сложно.


                1. unC0Rr
                  00.00.0000 00:00
                  +8

                  Если под капотом небезопасно, то это не значит, что язык не может выражать только безопасные (без багов памяти) конструкции. К примеру, мы ведь не думаем, как избегать сегфолтов, пиша запросы в SQL? SQL же не считается небезопасным языком только потому что под капотом движок, написанный на C++, и ОС на чёрт знает чём. И то, что на нижнем уровне небезопасные языки, не является причиной того, чтобы и в языке запросов были конструкции для низкоуровневой работы с памятью без проверки корректности.


    1. domix32
      00.00.0000 00:00
      +3

      Да чтоб я так безошибочно многопоток на Си писал...


    1. morijndael
      00.00.0000 00:00
      +6

      Андроид, Хром и Мозилла сходятся на цифре 70. 70% уязвимостей так или иначе вызвано ошибками в работе с памятью.

      Во вторых, borrow-checker часто ловит в том числе логические ошибки

      В третьих, не borrow-checker-ом единым! У раста очень много других фишек, помогающих писать надёжный код. Option/Result вместо исключений, требование полноты для match, и многое другое — вынуждает программиста думать о всех путях выполнения кода. В том числе, когда что-то идёт не по плану. Возможные ошибки видны как на ладони, и просвечивают через сигнатуры. И они все должны быть обработаны, чтобы программа прошла тайпчек

      И, по моему субъективному опыту, писать крупную долгоиграющую систему намного приятнее, когда гарантировано знаешь, где она может посыпаться, а где не может


  1. easimonenko
    00.00.0000 00:00
    +4

    О чём эта статья?


    1. OneMike
      00.00.0000 00:00
      +2

      Велком - что-то про колбасу, наверное, но видел в тексте только про грибы...


  1. MiraclePtr
    00.00.0000 00:00
    +6

    Тогда он решил попробовать сделать язык программирования, который сводил бы такие ошибки к нулю.

    А потом окажется, что программа ПЛК, управляющая лифтом, скорее всего написана на вообще каком-нибудь языке лестничной релейной логики, то вполне возможно что Rust проблему не решит :)

    Чтобы даже начинающий разработчик мог бы написать код, который не зависал.

    Учитывая порог вхождения, начинающий разработчик просто не напишет никакого кода. Нет кода - нет багов и зависаний, badum-tsss :)


    1. LinearLeopard
      00.00.0000 00:00
      +4

      https://llvm.org/devmtg/2014-10/Slides/Baker-CustomHardwareStateMachines.pdf

      Вроде, есть способы генерировать код для FPGA на llvm, в который и компилируется rust.

      Правда, FPGA и PLC разные устройства (кстати, насколько? не в теме), так что придётся немного и железо поменять в лифте, а раз уже меняется, то можно и arm воткнуть. Разумеется с k8s и метриками.


      1. MiraclePtr
        00.00.0000 00:00
        +1

        кстати, насколько? не в теме

        Совершенно разные.
        ПЛК - это по сути дела или микроконтроллер или SoC, обвешанный модулями ввода-вывода (входные/выходные дискретные/релейные, аналоговые, частотные, RS232, RS485, и т.д.). На нем работает какая-нибудь RTOS или Linux, исполняющая либо скомпилированный бинарный, либо байт-код управляющей программы.


        1. LinearLeopard
          00.00.0000 00:00

          Спасибо, а зачем на RTOS или Linux свой язык лестничной релейной логики. Кажется, можно написать на более привычном C? Я думал, там что-то на уровне отдельных транзисторов, а не SoC. Это не так?


          1. MiraclePtr
            00.00.0000 00:00
            +1

            Там не только Ladder, там целое семейство языков, которые обычно используются в ПЛК.

            LD удобен для переноса в ПЛК систем автоматики, которые были построены на релейной логике. FBD - для переноса систем автоматики, которые были построены на цифровых дискретных микросхемах (там те же самые логические блоки, счётчики, компараторы, таймеры, триггеры, и т.д.). IL - что-то типа ассемблера байт-кода, ST - что-то типа сильно урезанного Паскаля.

            Причины того, что именно эти языки выбрали в качестве индустриального стандарта прозаичны, основная идея этих языков в том, чтобы 1) можно было легко переносить старые существующие системы автоматики на новые рельсы; 2) программу мог писать и модифицировать не программист, а электронщик, КИПовец или вообще электрик, для которых подобные графические схемв гораздо понятнее и привычнее, чем Си; 3) было минимум возможностей отстрелить себе ногу всяким неочевидным поведением (типа undefined behavior в Си). Я думаю, что возможно ещё была мысль о переносимости программ между ПЛК разных производителей, но по факту это практически невыполнимо, ибо языки-то общие, но каждый вендор что-то к ним досыпает от себя (хотя есть рантаймы, которые работают на разных ПЛК разных вендоров, например CoDeSyS, IsaGRAF). А ещё некоторые вендоры, кому не хватило денег на вышеупомянутые рантаймы и кому было лень/ниасилили написать свой рантайм, используют такую штуку как Beremiz, которая по сути дела является транслятором с МЭКовских языков в Си-код.

            Так что да, самом деле, под некоторые ПЛК вполне можно писать сразу на C и C++. И некоторые даже пишут. Вот только многие заказчики такие проекты не любят и принимать такое не соглашаются. Так уж сложилось.


    1. morijndael
      00.00.0000 00:00

      Нет кода - нет багов и зависаний

      Всё верно. Поэтому многие разработчики переходят на no-code


  1. SIMPLicity
    00.00.0000 00:00
    +2

    Похоже на речь евангелистов типа "Любите говно!"...


  1. Chamie
    00.00.0000 00:00
    +5

    С трудом уже сдерживаю желание вычислять по айпи и бить по голове тезаурусом говнопереводчиков, использующих слово «кодировать» („encode“) для перевода слова, означающего «писать код»/«программировать».


    1. avril_rocks
      00.00.0000 00:00

      В общем и целом – это одно и то же. Писать на естественном языке по мне – тоже кодирование


      1. Chamie
        00.00.0000 00:00
        +1

        Кодировать — это переводить входные данные в закодированные данные. Писать код и программировать — это совершенно другой процесс. Писать на естественном языке — это кодировать, да. Кодировать устную речь при помощи системы письменности. А вот придумывать, что написать — это, как и программирование, совершенно другая задача.


        1. avril_rocks
          00.00.0000 00:00
          -1

          В статье и употребляется "кодирование" в контексте "жестких правил", что исключает "придумывать, что написать".
          Но по мне и придумывание так же можно называть кодированием, ведь в этом конечный результат


          1. Chamie
            00.00.0000 00:00
            +1

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


  1. Solicitor
    00.00.0000 00:00

    А потом узнал, что лифт не работал из-за сбоя программного обеспечения. Тогда он решил попробовать сделать язык программирования, который сводил бы такие ошибки к нулю. Чтобы даже начинающий разработчик мог бы написать код, который не зависал.

    Какая элегантная подмена понятий.
    Начинающий разработчик пишет программу для здания в 10 этажей (псевдокод):
    Пока(этаж<20) повторять
    пауза(1 сек);
    и она зависает.


  1. anka007
    00.00.0000 00:00

    О, а мне байку рассказывали, что для лифтов делают управление на плис, так как они доказательно верифицируются.


  1. wataru
    00.00.0000 00:00
    +2

    Ошибки типа переполнения буфера и выхода за пределы массива в языке стали невозможны в принципе.

    Всмысле не возможны? Там встроенные проверки и программа падает при попытке записать что-то за границы массива? Как std::vector::at в C++?


    Ну так это та же ошибка, только поведение при ней — аварийное завершение программы, а не возможная уязвимость.


    1. DirectoriX
      00.00.0000 00:00
      +2

      Есть get/get_mut, которые возвращают Option. То есть если индекс внутри массива — будет Some(&T) который можно использовать, а если за границами — всего лишь None. Есть даже конструкция if let Some(value) = vec.get(index) {...} как раз для подобных случаев.
      Можно обращаться и с помощью квадратных скобок — тогда да, запаникует.


      1. wataru
        00.00.0000 00:00

        Что будет, если этот Option программист попробует вывести или прибавить к счетчику?


        А с записью как?
        Ну вот, допустим, вам надо данные крипто-ключа записать в массив. Массив оказался коротким. Вижу 2 варианта: программа запаникует или надо проверять результат, вдруг ошибка вернулся. В любом случае, программа будет работать некорректно. Ну некуда ей этот ключ записывать, а что-то делать с обрезком бессмыслено.


        От зависнувшего лифта не помогает. Предотвращает возможность эксплоита — да.


        1. DirectoriX
          00.00.0000 00:00
          +3

          Option нужно распаковать перед использованием, именно поэтому он спасает от ошибок выхода за границу, не вводя панику.
          А ещё массивы и ко. знают, какова их ёмкость, так что можно явно проверить перед записью.
          Вот вам небольшой пример как это может быть использовано (можете раскомментировать строки 3 и/или 4 если хотите посмотреть поведение для чуть других типов).


  1. zaiats_2k
    00.00.0000 00:00
    +4

    Тема лифта не раскрыта совершенно. Как он узнал что сбой был именно из-за ПО, что за баг там был...