LINUX.ORG.RU

Rust 1.13

 


4

10

Представлен релиз Rust 1.13 — системного языка программирования, нацеленного на безопасную работу с памятью, скорость и параллельное выполнение кода. В этот релиз вошли 1448 патчей.

Этот сезон оказался очень плодотворным для Rust. Проведены конференции RustConf, RustFest и Rust Belt Rust. Обсуждено будущее языка, разработан план на 2017 год и созданы новые инструменты.

Новое в 1.13

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

Cargo в этом релизе содержит важные обновления безопасности, связанные с зависимостями от curl и OpenSSL, для которых также недавно были опубликованы обновления безопасности. Подробную информацию можно найти в соответствующих источниках для curl 7.51.0 и OpenSSL 1.0.2j.

Оператор ?

Добавлен новый оператор ?, делающий обработку ошибок приятнее за счёт уменьшения визуального шума. В качестве иллюстрации представим следующий код, который считывает некоторые данные из файла:

fn read_username_from_file() -> Result<String, io::Error> {
    let f = File::open("username.txt");

    let mut f = match f {
        Ok(file) => file,
        Err(e) => return Err(e),
    };

    let mut s = String::new();

    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),
    }
}

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

С оператором ?, вышестоящий код выглядит следующим образом:

fn read_username_from_file() -> Result<String, io::Error> {
    let mut f = File::open("username.txt")?;
    let mut s = String::new();

    f.read_to_string(&mut s)?;

    Ok(s)
}

Оператор ? заменяет весь код обработки ошибок, написанный при помощи оператора match ранее. Иными словами, ? применяется к значению Result, и если оно равно Ok, разворачивает его и отдаёт вложенное значение; если это Err, то происходит возврат из функции, в которой вы находитесь.

Более опытные пользователи могут заметить, что этот оператор делает то же самое, что и макрос try!, который доступен начиная с Rust 1.0. И будут правы, в самом деле, это то же самое. До 1.13 read_username_from_file можно было бы написать следующим образом:

fn read_username_from_file() -> Result<String, io::Error> {
    let mut f = try!(File::open("username.txt"));
    let mut s = String::new();

    try!(f.read_to_string(&mut s));

    Ok(s)
}

Так зачем надо было расширять язык, если до этого уже был такой макрос? Есть несколько причин. Во-первых, try! доказал своё огромное значение и часто используется в идеоматичном Rust. Он используется так часто, что было принято решение о создании собственного «подслащенного» синтаксиса для него. Такой вид эволюции — одно из преимуществ мощной системы макросов: расширения к синтаксису языка можно добавлять через прототипирование без внесения изменений в сам язык и особо полезные макросы могут указать на недостающие возможности языка. Эволюция try! в ? — яркий пример этого.

Другая причина — восприятие нескольких последовательных вызовов try!:

try!(try!(try!(foo()).bar()).baz())
против
foo()?.bar()?.baz()?

В первом случае, где каждый уровень обработки ошибки вызывает try!, код сложнее для восприятия и может отвлекать внимание от основного кода, как в данном случае.

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

Более подробно об операторе ? можно прочитать в RFC 243.

Улучшение производительности

В последнее время очень много внимания заострено на производительности компилятора. Mark Simulacrum и Nick Cameron произвели улучшения http://perf.rust-lang.org/, инструмента для отслеживания производительности компилятора, на котором периодически запускается набор rustc-benchmarks на выделенном оборудовании. Инструмент записывает результаты каждого прохода компилятора и позволяет находить и отслеживать код, приведший к регрессии. Например, при помощи этого инструмента можно посмотреть график производительности за весь цикл разработки релиза 1.13, где можно увидеть заметное сокращение времени работы компилятора, отдельно представленное на соответствующей странице со статистикой.

Большое улучшение на графике от 1 сентября связано с оптимизацией от Niko по кешированию нормализованных проекций во время преобразования. То есть во время генерации промежуточного представления LLVM компилятор больше не пересчитывает каждый раз конкретные экземпляры связанных типов, когда они необходимы, а использует ранее вычисленные значения. Несмотря на то, что данная оптимизация не влияет на всю кодовую базу, для некоторого кода с определенным шаблоном, например, futures-rs, ускорение сборки в режиме отладки достигает 40%.

Другая оптимизация от Michael Woerister уменьшает время компиляции библиотек, экспортирующих множество встраиваемых функций. Когда функция помечена как «#[inline]», в дополнение к преобразованию этой функции в текущей библиотеке компилятор сохраняет её представление MIR и преобразует функцию в представление LLVM в каждой библиотеке, которая вызывает её. Оптимизация, сделанная Michael Woerister, позволяет компилятору избегать предварительных преобразований кода встраиваемых функций в библиотеках, в которых они определены, до их непосредственного прямого вызова. Таким образом, компилятор избавляется от необходимости выполнения лишних шагов по преобразованию функции в промежуточное представление LLVM, оптимизации LLVM и преобразования функции в машинный код.

В некоторых случаях это приводит к впечатляющим результатам. Например, время сборки библиотеки ndarray уменьшилось на 50%, а библиотека winapi 0.3 (ещё не опубликована) полностью избавилась от шага генерации машинного кода.

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

Другие заметные изменения

Макросы теперь можно использовать на позиции типов (RFC 873), а атрибуты могут быть применены к операторам (RFC 16):

// Use a macro to name a type
macro_rules! Tuple {
    { $A:ty,$B:ty } => { ($A, $B) }
}

let x: Tuple!(i32, i32) = (1, 2);

// Apply a lint attribute to a single statement
#[allow(uppercase_variable)]
let BAD_STYLE = List::new();

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

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

Стабилизация языка

Стабилизация библиотек

Возможности Cargo

Более детальный список изменений доступен по ссылке: https://github.com/rust-lang/rust/blob/stable/RELEASES.md#version-1130-2016-1...

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

★★★★★

Проверено: maxcom ()
Последнее исправление: cetjs2 (всего исправлений: 5)
Ответ на: комментарий от anonymous

Rust - это Си, в который прикрутили старые плюшки из ML и не очень старые плюшки из Cyclone.

Если это

std::sync::Weak<Mutex<()>>

Си, то я - Дональд Трамп.

А кто тебе сказал, что это Си - голоса в голове?

Раст изначально готовили как замену плюсам в браузерном движке

Да, школьник, я помню твою любимую теорию заговора.

Так что в виде наличия современного С++ нужность раста сомнительна

Когда в Си++ появятся лайфтаймы и возможность использовать только подмножество языка - он сможет отчасти делать то, что умеет Rust уже сегодня.

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

Rust - это Си, в который прикрутили

Если это Си, то я - Дональд Трамп.

А кто тебе сказал, что это Си - голоса в голове?

Мне это сказал голос в твоей голове, который заставил тебя отрицать, что Раст, — это С++, из которого выкинули лишнее.

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

выкинули лишнее

Правда штоле? (недобро взирая на винегрет фич, приправленный всеми мыслимыми закорючками). C++ (олдскульный) теперь уже мне кажется минималистичным, лол.

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

Зачем? Си с классами хватит всем. А на расте можно так не приходя в сознание писать? Судя по трешу и содомии в unsafe примерах, как то не верится.

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

Зачем?

Чтобы он больше не казался минималистичным :D

Rust на порядок проще, хотя код внешне тоже выглядит не особо :/

А на расте можно так не приходя в сознание писать?

Не, так можно только на энтерпрайз-языках

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

отсюда и увлечение всякими там :: и <>

Как боком синтаксис к идеологии языка?

Что касается Си, то у него уже есть замена, С++ называется

Никогда не был и не будет.

Так что в виде наличия современного С++ нужность раста сомнительна

И что же делает «современный С++» для безопасности? Ах да - ничего.

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

Наверное, ты удивишься, но - они знают о монадах и не в восторге от них.

Это лишь дешевая попытка замаскировать нежелание пилить HKT.

mix_mix ★★★★★
()

Вроде интересный язык, но жизнь коротка и выучить можно будет или его или C++, а на крестах столько ништячков написано. Что скажите, господа?

anonymous
()
Ответ на: комментарий от awesomebuntu

Опять эти хипсторы, везде лезут со своим растом.

Опять эти тролли везде лезут со своими вбросами.

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

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

anonymous
()
Ответ на: комментарий от tailgunner

Память совсем полностью закончилась,
и ронять программу из-за этого как-то слишком резко.

ваши предложения, каковы могут быть альтернативные действия, в общем случае, в такой ситуации?

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

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

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

Блин, ну кучу раз обсуждалось же.
Как минимум, безопасно скинуть промежуточный результат на диск, чтобы бухгалтер Маша не носитась по офису с глазами навыкат потому что у нее ворд с полугодовым отчетом в несохраненном документе упал

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

Как минимум, безопасно скинуть промежуточный результат на диск

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

//вообще, строго говоря, если память совсем-совсем закончилась, у вас, обычно, не получится скинуть промежуточный результат на диск: не хватит памяти а) на промежуточный буфер б) на процесс обработки промежуточного результата, чтобы его привести в вид пригодный для записи на диск

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

как продолжать работу, если память совсем закончилась

Скинуть кэши, если они есть. Это зависит от конкретной программы.

если память совсем-совсем закончилась, у вас, обычно, не получится скинуть промежуточный результат на диск

Тоже 100 раз обсуждалось: для этого при старте преаллоцируется достаточный для записи буффер.

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

Как минимум, безопасно скинуть промежуточный результат на диск

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

//вообще, строго говоря, если память совсем-совсем закончилась, у вас, обычно, не получится скинуть промежуточный результат на диск: не хватит памяти а) на промежуточный буфер б) на процесс обработки промежуточного результата, чтобы его привести в вид пригодный для записи на диск

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

каковы могут быть альтернативные действия, в общем случае, в такой ситуации?

В общем случае всё тлен и мы все умрем, так что poweroff. В частном - логируем ошибку и переходим к обработке следующего запроса.

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

дешевая попытка замаскировать нежелание пилить HKT.

Вот ведь гады. Знают, как сделать, но не хотят.

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

В частном - логируем ошибку

возможно

и переходим к обработке следующего запроса

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

anonymous
()
Ответ на: комментарий от tailgunner

Наркоман, ты понимаешь, что всем пофиг на то, что рантайм реализован на unsafe-языке?

мне не пофиг

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

при этом польза от использования safe-подмножества для прикладного кода (дергая unsafe библиотеку/runtime/whatever) конечно есть, правда достаточно ли она, чтобы уйти допустим с с++ на раст — это открытый вопрос

вообще после того, как растаманы отказались решать вопрос об указателях в графе и двухсвязном списке, мой мнение о них очень сильно поубавилось

при этом, конечно, сам процесс разработки этого языка несет кучу полезной информации

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

я к тому, что это может оказаться хорошим тестом для системы типов языка: «можно ли на языке сделать ооп (с vtable и желательно множественным наследованием), не уходя в unsafe»

второй, более простой тест, который все современные языки проходят: «можно ли на языке написать интерпретатор лиспа, обязательно используя стек языка как стек лиспа» — правда, если потребовать continuations в лиспе, то вопрос становится совсем не однозначным

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

обработка следующего запроса опять завершится с ошибкой по нехватке памяти

Обоснуй.

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

Обоснуй.

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

обработка следующего запроса опять завершится с ошибкой по нехватке памяти

1) Для обработки нового запроса (в реальном мире) вам в 99% случаев понадобится выделение новой, которую мы выделить не можем

Обоснуй.

2) Положим, всего в системе NГб памяти, из которых задействовано ровно NГб: в исходном предложении говорилось, что память закончилась «совсем-совсем». Полагаем, что единственный шаг, который вы назвали (логирование) не связано с освобождением памяти. Таким образом, проблема всё ещё не решена. И тут см. пункт 1.

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

единственный шаг, который вы назвали (логирование) не связано с освобождением памяти

До логирования произошла раскрутка стека с освобождением ресурсов.

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

освобождением ресурсов

Каковы гарантии, что этой памяти достаточно для выполнения следующего запроса? И каковы гарантии, что выполнение следующего запроса будет вообще иметь смысл, если предыдущий не был корректно обработан? Более того, с выполнением каждого последующего запроса, обычно, увеличивается число затраченных ресурсов, а значит, с каждым запросом, вероятность того, что все последующие не смогут выполниться, растёт катастрофически быстро.

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

освобождением ресурсов

Каковы гарантии, что этой памяти достаточно для выполнения следующего запроса?

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

И если этих гарантий нет (а их, естественно, нет), то что?

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

Ты только что доказал, что любая система рано или поздно рухнет от исчерпания ресурсов %)

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

Ты только что доказал, что любая система рано или поздно рухнет от исчерпания ресурсов %)

У нас здесь что, появилось решение задачи остановки?! ;-)))

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

И если этих гарантий нет (а их, естественно, нет), то что?

На практике, обычно, на этом — всё, программа завершает работу, либо (что хуже) виснет намертво, причём, нередко, вместе со всей ОС.

Ты только что доказал, что любая система рано или поздно рухнет от исчерпания ресурсов %)

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

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

Сбросить тот самый кэш, который к этому привел (работать в пиковом режиме, медленно, но работать)

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

И если этих гарантий нет (а их, естественно, нет), то что?

На практике, обычно, на этом — всё, программа завершает работу

На какой практике, где обычно? Возьмем, например, ОС - твоя ОС обычно паникует при нехватке памяти?

пока условия, которые привели к её исчерпанию, не будут устранены, продолжать выполнение программы бессмысленно

Слезь с трибуны. Впрочем... можешь не слезать.

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

У нас здесь что, появилось решение задачи остановки?! ;-)))

Да. Программа всегда останавливается.

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

Ты сам себе и ответил. Раст просуществует ровно столько, сколько будут его финансировать. Причина проста, судя по синтаксису, они делали язык не для всех, а для себя. Отсюда и хайп про хипстеров.

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

Язык с сиподобным синтаксисом
Вангуют провал именно из-за него

Продолжайте, господа

mersinvald ★★★★★
()

Rust не знаю, но в одном из прошлых тредов кто-то сокрушался, что приходится писать много copy/paste кода, т.к. нельзя forward-нуть методы из одной имплементации трейта в другую (или типа того. Не владею терминологией)

Что-нибудь изменилось?

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

Ладно, Михаил, посмотрю его поближе, может он мне не понравится.

anonymous
()
Ответ на: комментарий от tailgunner

возможность использовать только подмножество языка

а кто на плюсах запрещает? и зачем это нужно?

лайфтаймы

как минимум, частично, есть: static и thread_local

anonymous
()
Ответ на: комментарий от tailgunner

На какой практике, где обычно?

Странно, что вам это неизвестно. Вы точно профессиональный разработчик?

Возьмем, например, ОС - твоя ОС обычно паникует при нехватке памяти?

при полной нехватке — виснет намертво, как уже говорил — это хуже просто падения

Слезь с трибуны. Впрочем... можешь не слезать.

если вам нечего ответить, пожалуйста, просто промолчите, а не фантазируйте

anonymous
()
Ответ на: комментарий от makoven

Кто мешает реализовать типаж для всего, что реализует нужный (impl<S: Another> Trait for S)?

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

А что мне мешает ловить паник на 1 уровень выше и использовать другую логику?

То, что далеко не всегда UnwindSafe реализован. То есть даже если захочется построить на этом error handling, то не получится

loyd
()
Ответ на: комментарий от makoven

Можно пример на псевдокоде? Наследование трейтов и так есть.

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

На какой практике, где обычно?

Странно, что вам это неизвестно.

Ясно понятно.

Возьмем, например, ОС - твоя ОС обычно паникует при нехватке памяти?

при полной нехватке — виснет намертво

Хреново быть маководом, чо. Нормальные ОС возврщают ошибку ENOMEM.

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

при полной нехватке — виснет намертво, как уже говорил — это хуже просто падения

То есть ОС и при OOM должна падать? «Вы точно профессиональный разработчик?»

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

Причина проста, судя по синтаксису, они делали язык не для всех

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

Отсюда и хайп про хипстеров.

А где хайп то? Нету никакого хайпа, хоть мозила и пытается его изобразить. Реально два с половиной землекопа на редите очень громко обсуждают раст. Тоже самое на лоре: пара персонажей форсят раст, анонимусы набрасывают, вот и все. Хайп - это стартапы, митапы, вакансии, вал пет-прожектов. Это нет и не будет.

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

возможность использовать только подмножество языка

а кто на плюсах запрещает?

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

лайфтаймы

как минимум, частично, есть: static и thread_local

Смешно.

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

два с половиной землекопа на редите очень громко обсуждают раст

/r/cpp metrics Total Subscribers 42,182

/r/rust metrics Total Subscribers 20,184

Два с половиной, да.

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

Дык, всю мозилу корп подписали, в т.ч. уборщиц, плюс ботов пачка.

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