LINUX.ORG.RU

Rust 1.18

 


1

10

Команда Rust анонсирует релиз 1.18.

Обновление предыдущей версии легко:

$ rustup update stable

Сам rustup можно установить здесь.

Основные изменения

Одно из главных изменений - новая версия «The Rust Programming Language», официального учебника по Rust. Он пишется открыто на Github, и имеет более ста авторов. В этом релизе включен черновик второй версии книги, имеющий 19 из 20 глав; двадцатая глава будет готова к релизу 1.19. Купить бумажную версию можно через No Starch Press. Новая версия книги полностью переписана и учитывает последние два года нашего опыта обучения Rust. Вы найдете новые объяснения основных принципов Rust, новые проекты и прочее.

В самом языке улучшено ключевое слово pub. По умолчанию, в Rust объекты приватны; можно использовать pub чтобы сделать их публичными. В Rust 1.18, pub имеет новый вариант:

pub(crate) bar;

Слово в скобках - ограничение, контролирующее степень публичности объекта. Если указанно pub(crate), то bar будет публичным для всего крейта (пакета), но не вне него. Это позволяет декларировать интерфейсы, «внутренне публичные» для пакета, но не доступные для внешних пользователей.

Также можно указать путь, например:

pub(in a::b::c) foo;

Это значит «доступно в иерархии a::b::c, но не в прочих местах».

Для пользователей Windows Rust 1.18 имеет новый атрибут, #![windows_subsystem]. Он работает так:

#![windows_subsystem(console)]
#![windows_subsystem(windows)]

Он контролирует флаг /SUBSYSTEM в компоновщике. На текущий момент доступны только console и windows. Если вы разрабатываете графическое приложение, и не указываете windows, в момент пуска программы всплывет окно консоли. С атрибутом windows этого не произойдет.

Далее, в Rust кортежи, варианты перечисляемых типов и структуры (без атрибута #[repr]) всегда имели неопределенное расположение в памяти. Мы включили автоматическое упорядочивание, которое может привести к уменьшению потребления памяти путем уменьшения необходимого выравнивания. Например:

struct Suboptimal(u8, u16, u8);

В прежних версиях Rust на платформе x86_64 эта структура имела бы размер в шесть байтов. Но согласно исходному коду, ей достаточно должно быть четырех. Остальные два байта - результат выравнивания. Поскольку мы имеем u16, он требует двух байтов. Но в данном случае, он был смещен на один байт из-за предыдущего u8. Для последнего же u8 требуется еще один байт выравнивая. В итоге, мы имеем 1 + 1 (пусто) + 2 + 1 + 1 (пусто) = 6 байтов.

Но что если структура выглядит так?

struct Optimal(u8, u8, u16);

Эта структура оптимально выравнена; u16 находится на рубеже двух байтов, как и остальная структура. Выравнивание не требуется. Это дает нам 1 + 1 + 2 = 4 байта.

При дизайне Rust мы оставили физическое расположение данных в памяти неопределенным как-раз по этой причине; любой safe-код (не следующий по «сырым» указателям) не будет затронут подобной оптимизацией. Благодаря этому, мы можем научить компилятор оптимизировать Suboptimal в Optimal автоматически. В Rust 1.18 обе структуры занимают в памяти размер в четыре байта.

Мы долго планировали это изменение; оно было и ранее в нестабильной версии Rust, но некоторые программисты писали unsafe-код, который предполагал определенное расположение данных в памяти. Если вам необходима гарантия, что физическое расположение в памяти в точности совпадает с расположением вариантов в исходном коде (например, при обращению к оболочкам Cи-кода), пометьте вашу структуру с атрибутом #[repr(C)].

Напоследок, улучшено время компиляции; например, компиляция самого rustc теперь на 15%-20% быстрее.

Стабилизированы следующие библиотеки:

  • Child::try_wait, неблокирующая форма Child::wait.
  • HashMap::retain и HashSet::retain - версия существующего retain от Vec<T> теперь и у этих двух структур.
  • PeekMut::pop позволяет взять ранее прочитанный верхний элемент от BinaryHeap<T> без необходимости повторно упорядочивать кучу.
  • TcpStream::peek, UdpSocket::peek, UdpSocket::peek_from позволяют прочесть крайний элемент у потока или сокета.

Новый функционал Cargo

Cargo добавил поддержку системы управления версиями Pijul, который написан на Rust:

cargo new my-awesome-project --vcs=pijul

У Cargo несколько новых флагов, дополняющих --all: --bins, --examples, --tests и --benches позволяют собрать все программы указанных типов.

И наконец, Cargo теперь поддерживает Haiku и Android.

Подробнее об изменениях написано здесь.

>>> Подробности



Проверено: Shaman007 ()
Последнее исправление: cetjs2 (всего исправлений: 7)

Ответ на: комментарий от eao197

Выше была ссылка на Brotli в Dropbox-е, там хуже на 28%.

Я пропустил =(

AntonyRF ★★★★
()
Ответ на: комментарий от eao197

Я не вижу там никакого вопроса кроме перемывания вашей вкусовщины и закостенелых привычек старого C++ника. Отвечать не на что.

mersinvald ★★★★★
()
Ответ на: комментарий от mersinvald

Ну тогда еще раз, для совсем тупых: мне, лично мне, синтаксис раста не нравиться и я объяснил почему. Что растоманы пытаются мне доказать? Что вам синтаксис раста нравиться или что у раста хороший и удобный синтаксис?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Что нас синтаксис раста устраивает и что он не вызывает никаких проблем при разработке и чтении кода после изучения языка.

mersinvald ★★★★★
()
Ответ на: комментарий от gene1

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

eao197 ★★★★★
()
Ответ на: комментарий от mersinvald

Давайте считать спецсимволы. Семь у C#, три у Rust.
eao197, еще есть что сказать про плотность спецсимволов и «непривычные» лямбды?

mersinvald ★★★★★
()
Ответ на: комментарий от RazrFalcon

Уже три страницы не волнует. А вас лично мое мнение настолько не волнует, что вы не перестаете со мной общаться.

eao197 ★★★★★
()
Ответ на: комментарий от mersinvald

Отвечаю на вопросы, если вы еще не заметили.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Выше была ссылка на Brotli в Dropbox-е, там хуже на 28%.

Интересно сколько из этих процентов попадают в категорию «gcc vs llvm»

pftBest ★★★★
()
Ответ на: комментарий от mersinvald

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

eao197 ★★★★★
()
Ответ на: комментарий от pftBest

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

eao197 ★★★★★
()
Ответ на: комментарий от eao197

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

gene1
() автор топика
Ответ на: комментарий от eao197

Вы в рекламных проспектах хотите видеть research paper на 50 страниц?
Хотите узнать больше — открываете документацию, там всё описано.

В Safe Rust гарантии все есть, и в прикладном кода unsafe очень редко используется. Обеспечить руками соблюдение гарантий в unsafe-прослойке и покрыть всё это тестами — задача разработчика библиотеки.

mersinvald ★★★★★
()
Ответ на: комментарий от gene1

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

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Но не уточняют на чем эти гарантии базируются.

Гарантии описаны в оф.доках и область их действия тоже. Я уже раз 5 пишу.

AntonyRF ★★★★
()
Ответ на: комментарий от umren

надежда тут только на гениальных студентов-фанатиков, не иначе

Так на них вся индустрия и держится... Где бы мы были сейчас без гениальных студентов фанатиков?

foror ★★★★★
()
Последнее исправление: foror (всего исправлений: 1)
Ответ на: комментарий от eao197

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

Можно ссылку? Лень искать.

AntonyRF ★★★★
()
Ответ на: комментарий от eao197

Я то прочитал, но там нету подробностей. По их подсчетам первые два пункта занимают 10. А куда остальные 18 не известно.

pftBest ★★★★
()

Вы тут спорите такие.

А тем временем у меня пример рисования цветных точек в этом файле https://github.com/baist0/x11-rs/blob/master/x11/examples/xshm.rs

Без вот этой строчки(206 line):

let mut xgcvls: xlib::XGCValues = mem::uninitialized();
пример работать не будет. Приложение крашится.

X Error of failed request:  BadShmSeg (invalid shared segment parameter)
  Major opcode of failed request:  130 (MIT-SHM)
  Minor opcode of failed request:  3 (X_ShmPutImage)
  Segment id in failed request:  0x3a00002
  Serial number of failed request:  21
  Current serial number in output stream:  22

Даже если переменная xgcvls нигде не используется. А может использоваться в этом вызове вместо null_mut():

let grph_cntx = xlib::XCreateGC(self.display, self.demo_window.window, 0, null_mut());

Я ставил разные эксперменты. Но вот именно надо делать так. Тестил на 1.18 версии, на домашнем ПК и рабочем ноуте результат одинаковый.

cargo run --features "xlib dpms" --example xshm

Для сборки нужно еще https://github.com/baist0/posix.rs (new_vers ветка) стянуть в папку с проектами.

А вы говорите про стабильность, про новые версии!

baist ★★
()
Ответ на: комментарий от eao197

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

А вот этого там в тексте нет, приведите цитату

Я только вижу что изначально было 28 но можно убрать проверки и сделать 18

pftBest ★★★★
()
Последнее исправление: pftBest (всего исправлений: 2)
Ответ на: комментарий от AntonyRF

Гарантии описаны в оф.доках и область их действия тоже. Я уже раз 5 пишу.

Еще раз: как только разработчик вынужден уходить в unsafe, гарантии начинают держаться только на обещаниях этого разработчика. Но адепты Rust-а об этом не говорят, когда произносят вот такие спичи:

Может и будет в разы быстрее в многопоточном режиме для практически написанных программ. В Расте, например, берешь библиотеку Rayon, заменяешь .iter() на .par_iter(), и пишешь цикл как обычно. Библиотека сама разбивает цикл на части, оптимизируя под количество доступных ядер и размера задачи. А компилятор гарантирует при этом отсутсвие гонок данных, UB, и прочих «прелестей» мультипоточного программирования.

Можно ссылку? Лень искать.

https://blogs.dropbox.com/tech/2016/06/lossless-compression-with-brotli/

eao197 ★★★★★
()
Ответ на: комментарий от Slackware_user

Tkinter наше все :D

Еще поддержка SDL и OpenGL тоже, даже вроде GTK и QT прихерачили

HasKup9012
()
Ответ на: комментарий от eao197

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

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

Но тут два практических момента:

- Для нарушения режима работы с памятью баг должен быть в вызываемом unsafe-блоке, а не в вызывающим ее коде. То есть, если библиотеку писали нормально, то даже при неправильном ее вызове багов не будет. Разработка библиотек требующих unsafe - крайне низкоуровнее занятие, как правило необходимое при реализации новых типов (или вызова внешних функций из Си). В «обычном» коде это не нужно.

- Отношение количества unsafe кода к остальному крайне мало. Unsafe-блоки как правило имеют лишь несколько строк, тесно связанных. Баг намного легче изолировать, отладить, и покрыть юнит-тестами, если известно, что он среди десятков строк, а не тысяч или больше.

Все равно скажете, «не 100% безопасно»? Пусть. 99% все равно чуть получше, чем 0%.

gene1
() автор топика
Ответ на: комментарий от eao197

Еще раз: как только разработчик вынужден уходить в unsafe, гарантии начинают держаться только на обещаниях этого разработчика.

Это во второй главе rustonomicon описано, что если в unsafe накосячить, то может падать в безопасном коде. НО! Проблема то будет локализована в unsafe

https://blogs.dropbox.com/tech/2016/06/lossless-compression-with-brotli/

Спасибо большое

AntonyRF ★★★★
()
Ответ на: комментарий от pftBest

Я только вижу что изначально было 28 но можно убрать проверки и сделать 18

Да, видимо именно это у меня и отложилось о том, что они смогли улучшить первоначальный результат. Т.е. с уходом в unsafe отставание Rust-а от C для Brotli составило 18% против изначальных 28%.

Соврал как очевидец. Прошу прощения.

eao197 ★★★★★
()
Ответ на: комментарий от gene1

Все равно скажете, «не 100% безопасно»? Пусть. 99% все равно чуть получше, чем 0%.

Похоже, вы выдумали за меня какое-то утверждение и старательно его опровергаете.

Покажите, где я говорил о «не 100% безопасности»?

Речь шла о том, что временами (временами, Карл!) гарантии безопасности базируются на «Мамой клянусь» от разработчика. Вы все еще будете утверждать, что это не так?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

При беглом просмотре кода хорошо было бы более четко видеть границы функций. fn этому не сильно помогает.

Хм... честно говоря, не совсем понимаю проблему. Если код выглядит как-то так, то тут ключевое слово любой длины не поможет:

function...
...........
...........
...........
function...
...........
В нормальном коде всё-таки будут пустые строки между функциями и закрывающие скобки. В идеале - ещё и комментарии:
/// Performs some calculation...
fn foo() {
    ...........
    ...........
}

/// Performs some other calculation...
fn bar() {
    ...........
    ...........
}

DarkEld3r ★★★★★
()
Ответ на: комментарий от Leron

А с mut'ом что не так?

mutable гораздо очевиднее и лучше в глаза бросается.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Да, видимо именно это у меня и отложилось о том, что они смогли улучшить первоначальный результат. Т.е. с уходом в unsafe отставание Rust-а от C для Brotli составило 18% против изначальных 28%.

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

AntonyRF ★★★★
()
Ответ на: комментарий от eao197

Речь шла о том, что временами (временами, Карл!) гарантии безопасности базируются на «Мамой клянусь» от разработчика. Вы все еще будете утверждать, что это не так?

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

gene1
() автор топика
Ответ на: комментарий от Legioner

Суффикс _t вообще в новом языке смысла не имеет, да и в С я не совсем понимаю, зачем нужен.

Суффикс _t определён в стандарте POSIX затем, что в C пространство имён - глобальное. Типы, определённые в POSIX заканчиваются на _t чтобы они не пересекались со встроенными типами C и типами, определёнными конечным разработчиком.

atrus ★★★★★
()
Ответ на: комментарий от gene1

А компилятор гарантирует при этом отсутсвие гонок данных, UB, и прочих «прелестей» мультипоточного программирования.

стопроцентной безопасности не существует нигде и никогда.

Я просто оставлю это тут.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Я просто оставлю это тут.

Понять и простить =)

AntonyRF ★★★★
()
Ответ на: комментарий от eao197

есть «правило наименьшего удивления» (least surprise principle), которое разработчиками Rust-а было нарушено при выборе имен вида i32/u32.

Тут ещё такой момент: растовые имена типов могут в виде суффиксов использоваться:

let a: i32 = 0;
let b = 0i32;
Эти записи эквивалентны. Длинные имена типов тут уже смотрелись бы коряво. А так удобно, что иметь две разные формы.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

let b = 0i32;

Если уж стремиться к очевидности, то лучше уж let b = Int32(0);. Тем же самым grep-ом затем Int32 искать проще будет.

eao197 ★★★★★
()
Ответ на: комментарий от DarkEld3r

Ещё литералы удобны

let a: i32 = 1000000;
let b = 1_000_000i32;

AntonyRF ★★★★
()
Ответ на: комментарий от eao197

И функции короткие, и комментарии. Все как надо.

Ну... это всё-таки не библиотека. (:

И границы функций, как по мне, более-менее отчётливо просматриваются. Да, не идеально, тем более, что пустые строки и внутри функции быть могут, но опять же, не уверен, что более длинное ключевое слово тут помогло бы.

DarkEld3r ★★★★★
()
Ответ на: комментарий от eao197

Что мешает сделать так?

fn Int32(val: i32) -> i32 { val }
...
let b = Int32(0);

AntonyRF ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.