Команда Rust рада представить выпуск Rust 1.18.0. Rust — это системный язык программирования, нацеленный на безопасность, скорость и параллельное выполнение кода.
Если у вас установлена предыдущая версия Rust, то для обновления достаточно выполнить:
$ rustup update stable
Если у вас ещё не установлен Rust, вы можете установить rustup
c соответствующей страницы нашего веб-сайта и ознакомиться с подробным примечанием к выпуску 1.18.0 на GitHub.
Что вошло в стабильную версию 1.18.0
Как и всегда, Rust 1.18.0 собрал в себе множество улучшений и новых возможностей.
Одно из крупнейших и самых ожидаемых изменений: члены команды Carol Nichols и Steve Klabnik пишут новую редакцию "Язык программирования Rust", официальной книги о Rust. Она пишется открыто на GitHub, и уже более ста человек внесли в нее свой вклад. Этот выпуск включает первый черновой вариант второго издания в нашей онлайн документации. 19 из 20 глав уже написаны, черновой вариант 20 главы будет добавлен в выпуске Rust 1.19. Когда книга будет завершена, версия для печати будет доступна через No Starch Press, если вы предпочитаете бумажную копию. Мы все еще работаем совместно с редакторами No Startch, чтобы улучшить текст, но мы бы хотели представить книгу широкой аудитории уже сейчас.
Новое издание написано полностью с нуля, используя знания, полученные нами за последние два года обучения людей Rust. Вы найдете совершенно новые объяснения множества ключевых концепций Rust, новые проекты для обучения, и много других интересных и полезных вещей. Пожалуйста, взгляните и сообщите нам, что думаете!
Что касается самого языка, старые функции получили новые возможности: ключевое слово pub
было немного расширено. Опытные программисты Rust знают, что в Rust все элементы приватны по умолчанию, и вы должны использовать ключевое слово pub
, чтобы сделать их публичными. В Rust 1.18.0 pub
получило новую форму:
pub(crate) bar;
Выражение внутри ()
является 'ограничением', уточняющим область видимости. Использование ключевого слова crate
в примере выше означает, что bar
будет публичным для всего контейнера (crate), но не вне него. Это упрощает создание API, которые "публичны для вашего контейнера", но не доступны вашим пользователям. Это было возможно с существующей системой модулей, но очень часто выглядело неудобно.
Вы также можете указать путь, например:
pub(in a::b::c) foo;
Это означает "foo
публично внутри иерархии a::b::c
, но нигде больше". Эта особенность была определена в RFC 1422 и описана в документации.
Для пользователей Windows, Rust 1.18.0 имеет новый атрибут, #![windows_subsystem]
. Это работает так:
#![windows_subsystem = "console"]
#![windows_subsystem = "windows"]
Эти выражения контролируют флаг /SUBSYSTEM
компоновщика. В настоящий момент, доступны только console
и windows
.
Когда это может быть полезным? В простейшем случае, если вы разрабатываете графическое приложение, и не указали windows
, окно консоли будет появляться при старте вашего приложения. С этим флагом, этого не произойдет.
Наконец, кортежи, перечисления и структуры (без #[repr]
) всегда имели неопределенное размещение в памяти. Мы включили автоматическое переупорядочивание, что может привести к меньшим размерам структур.
Представьте следующую структуру:
struct Suboptimal(u8, u16, u8);
В предыдущих версиях Rust на платформе x86_64, эта структура будет занимать в памяти шесть байт. Но смотря на код, вы ожидаете только 4. Дополнительные два байта появляются из-за выравнивания: так как наибольший тип в структуре u16
, она должна быть выравнена по два байта. Но в этом случае u16
расположено в памяти со смещением в один байт. Чтобы разместить его со смещением в два байта, нужно добавить еще один байт выравнивания после первого u8
. Добавив еще один байт после второго u8
, получаем:
1 + 1 (выравнивание) + 2 + 1 + 1 (выравнивание) = 6 байт
.
Но что, если наша структура выглядит так?
struct Optimal(u8, u8, u16);
Эта структура выровнена оптимально; u16
лежит с выравниванием в два байта, как и вся структура в целом. Никакого выравнивания не требуется. Это дает нам 1 + 1 + 2 = 4 байт
.
Проектируя Rust, мы оставили детали размещения в памяти неопределенными именно по этой причине. Не придерживаясь определенной политики, мы можем вносить оптимизации, например, как в этом случае, когда компилятор может оптимизировать Suboptimal
в Optimal
автоматически. И если вы проверите размеры Suboptimal
и Optimal
в Rust 1.18.0, вы увидите, что они обе имеют размер 4 байта.
Мы планировали это изменение в течение длительного времени; предыдущие версии Rust включали эту оптимизацию в ночных (nightly) сборках, но некоторые люди писали небезопасный код, который требовал точных данных о размещении в памяти. Мы откатили это изменение и исправили все подобные случаи, о которых знали. Но если вы найдете какой-нибудь код, который работает неправильно, сообщите нам, чтобы мы смогли его исправить!
Мы планировали перенести rustdoc
на Markdown-совместимый парсер CommonMark в течение долгого времени. Однако, простой переход может привести к проблемам, так как спецификация CommonMark отличается от нашего текущего парсера, Hoedown. Как часть нашего плана перехода, новый флаг был добавлен в rustdoc
, --enable-commonmark
. Этот флаг включает использование нового парсера вместо старого. Пожалуйста попробуйте его! Насколько мы знаем, оба парсера производят одинаковые результаты, но мы хотим знать, если вы найдете сценарий, при котором их результаты отличаются!
Наконец, компиляция самого rustc
теперь на 15%-20% быстрее. Сообщения коммитов в этом PR содержат некоторые детали; существовало множество неэффективных мест, но теперь все они исправлены.
Смотрите подробные заметки о выпуске для подробностей.
Стабилизация стандартной библиотеки
Семь новых API были стабилизированы в этом выпуске:
Child::try_wait
, неблокирующая версияChild::wait
.HashMap::retain
иHashSet::retain
добавляютretain
из APIVec<T>
для этих двух хранилищ.PeekMut::pop
позволяет вам вытащить верхний элемент изBinaryHeap<T>
после того как вы уже прочитали его без необходимости упорядочивать кучу второй раз.TcpStream::peek
,UdpSocket::peek
,UdpSocket::peek_from
позволяют вам просматривать поток или сокет.
Смотрите подробные заметки о выпуске для подробностей.
Функции Cargo
В Cargo появилась поддержка для Pijul VCS, написанной на Rust.
cargo new my-awesome-project --vcs=pijul
включает ее!
В дополнение к флагу --all
, Cargo теперь имеет несколько новых флагов, например --bins
, --examples
, --tests
и --benches
, которые позволяют вам собирать все программы заданного типа.
Наконец, Cargo теперь поддерживает Haiku и Android!
Смотрите подробные заметки о выпуске для подробностей.
Вклад в 1.18.0
Множество людей участвовало в создании Rust 1.18. Мы не смогли бы этого добиться без помощи каждого из вас. Спасибо!
От переводчика
Благодарю Gordon-F и ozkriff за помощь в переводе.
Комментарии (30)
Jenyay
13.06.2017 15:22> Этот выпуск включает первый черновой вариант второго издания в нашей онлайн документации. 19 из 20 глав уже написаны, черновой вариант 20 главы будет добавлен в выпуске Rust 1.19.
А есть pdf-версия этой версии?
Falstaff
13.06.2017 16:46+1Я собираюсь как-нибудь потыкать Rust, но меня снедают разные сомнения. Вот я хотел спросить об одном — может, кто-нибудь сможет его развеять. Как продвигаются дела с non-lexical borrow? Я просто слышу звон, и у меня есть впечатление, что когда это наконец появится, то стиль кода сильно изменится. Меня это здорово сдерживает — поскольку тыкать собирался не по какой-то необходимости а так, попробовать тёплая ли водичка, то хочется уже сразу писать идиоматично. Вместо этого есть ощущение, что сейчас придётся пробовать poor man's Rust, а уж потом, когда появится non-lexical borrow, вот тогда заживём и наконец я пойму, что такое идиоматичный код. По делу беспокоюсь, или мерещится?
DarkEld3r
13.06.2017 17:49+2Насколько я понимаю, принципиально ничего не изменится. Да и специально задумываться об этом, вроде, не приходится. То есть, иногда компилятор бьёт по рукам за код, который вполне мог бы быть корректным — приходится исправлять.
red75prim
13.06.2017 18:52+1Самое неприятное, что мне встречалось — ситуация, когда нужно написать функцию, возвращающую ссылку на объект в контейнере, если он там есть, или добавляющую новый элемент и возвращающую ссылку на него.
Этот код не компилируется, так как время жизни возвращаемой ссылки включает весь код функции, в том числе и
self.insert(...)
. То есть компилятор считает, чтоself
менять нельзя даже послеreturn v;
, поскольку его часть всё ещё позаимствована возвращаемой ссылкойv
.
fn get<T>(&mut self, key: &T) -> &u32 { if let Some(v) = self.find(key) { return v; } self.insert(key, 0) }
Сейчас советуют использовать два вызова
find
, что, конечно, менее эффективно:
fn get<T>(&mut self, key: &T) -> &u32 { if self.find(key).is_none() { return self.insert(key, 0); } self.find(key).unwrap() }
torkve
14.06.2017 09:33Посмотрите, как это делается в стандартной библиотеке:
https://doc.rust-lang.org/src/core/option.rs.html#667
https://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html#method.or_insert
torkve
14.06.2017 09:37+1И касательно времени жизни, вам должно помочь оборачивание if-блока в фигурные скобки:
fn get<T>(&mut self, key: &T) -> &u32 { { if let Some(v) = self.find(key) { return v; } } self.insert(key, 0) }
Не так красиво, но время жизни закончится там, где надо.
Ockonal
13.06.2017 23:56+1Очень надеюсь, что у Мозиллы все будет хорошо, либо же кто-то из гигантов заметит язык и начнет использовать и вкладывать в него.
Через месяц буквально сложности с borrow checker'ом уходят вообще на второй план и даже не задумываешься. Жутко не хватает готовых библиотек, кусков кода. В документации иногда вообще непонятно, что делать с той или иной библиотекой.
После С++ это как глоток свежего воздуха в этой нише.
Envek
14.06.2017 11:37А для проектов типа Diesel или Rocket всё ещё нужна Nightly-сборка? Те расширения языка, которые они используют (кодогенерация во все поля) собираются стандартизировать?
vitvakatu
14.06.2017 12:35+2Diesel
компилируется с Rust 1.17.Rocket
все еще требует nightly. Потихоньку все это стабилизируется (процедурные макросы, например, были стабилизированы то ли в прошлой, то ли в позапрошлой версии)ozkriff
14.06.2017 12:39+2процедурные макросы, например, были стабилизированы то ли в прошлой, то ли в позапрошлой версии
В 1.15 там же только "custom derive" был стабилизирован. Насколько я помню, полная стабилизация процедурных макросов это еще дело очень далекого будущего.
nehaev
Хотел как-то посмотреть, как выглядят production-ready проекты на Rust. Похоже, многие проекты, которые можно найти на github, делались для изучения языка и впоследствие забрасывались. Можете порекомендовать что-нибудь production-ready и кем-нибудь реально использующееся на Rust?
ozkriff
Видел что часто https://github.com/BurntSushi/ripgrep советуют в ответ на подобное, как пример небольшого, довольно идиоматичного и быстрого кода.
Есть статейка с обзором кода проекта: http://blog.mbrt.it/2016-12-01-ripgrep-code-review/
nehaev
Спасибо за пример проекта, и отдельно — за статью с обзором!
halpro
Кто использует Rust в production
В Mozilla Firefox уже часть кода на Rust.
ozkriff
И правда, с чего я решил что вопрос про исходные коды этих проектов? :(
kostus1974
хм! нет, это немного не то, учитывая, что раст возник в мозиллы от потребностей мозиллы. что есть стороннего, независимого?
то есть суть вопроса — взлетит или нет? го, шарп, цпп, или всё-таки раст? может всё-таки котлин во все поля?
Dark_Daiver
имхо, вы сейчас перечислили языки с достаточно сильно разными областями применения, если вам хватает kotlin, то скорее всего вам не нужен rust/cpp
kostus1974
завидую такой уверенности в оценках чужих потребностей.
мне хватает шарпа, ц\цпп и спецязыков на работе и ещё жабы немного. интересен котлин в степени уже бОльшей, чем некоторое время назад был интересен го. а гоу был интересен тем, что на нём достаточно просто создавать лёгкие сервисы с переносимым кодом. в котлин можно уже всё, включая андроид во все поля. можно ли котлин в сервисы с переносимым кодом так же, как в го — пока не понял.
так что пока смотрю на раст ровно так же, как на го, но знаю при этом, что у го история успеха толще.
halpro
Вопрос не в популярности сейчас. Пишут, что Dropbox запустил новое хранилище на Rust. OneSignal запустил push нотификацию со 100 000 tps на Rust. Samsung вкладывает в разработчиков компилятора Rust.
Rust попал в нишу. По мне так Rust надежнее C++ (искать баги проще уже при компиляции) и нет дурацкого GC который есть в Go, Java, C#, Kotlin, D…
ZurgInq
У меня чувство дежавю. Два года назад Dropbox переписывал хранилища на Go, а vk запускали на нём push нотификацию. Go тогда попал в нишу.
Revertis
Дело как раз в том, что код хранилища DropBox, написанный на Go, ужасно тормозил. Они его переписали на Rust, и теперь он летает. Они писали об этом в блоге.
ZurgInq
Дело в том, что код Dropbox был написан на python и ужасно тормозил. Они его переписали на Go и стало всё летать. Они писали об этом https://blogs.dropbox.com/tech/2014/07/open-sourcing-our-go-libraries/
Revertis
Вот тут лучше описано. Я тоже был не совсем прав — Го жрал слишком много памяти, поэтому переписали на Rust:
https://www.wired.com/2016/03/epic-story-dropboxs-exodus-amazon-cloud-empire/
Falstaff
Справедливости ради, они только пару компонентов переписали, остальная кодовая база у них всё ещё на Го и вроде, говорят, не собираются слезать. Но да, по их словам, памяти сэкономили много.