LINUX.ORG.RU

Rust 1.27

 


3

10

Команда разработчиков языка Rust рада представить новую версию Rust 1.27.0. Rust — системный язык программирования, ориентированный на безопасность, скорость и параллельность.

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

  • SIMD — наиболее значимое и ожидаемое нововведение: стабильная версия Rust обзавелась базовой поддержкой SIMD.
    Для примера использования рассмотрим следующий сниппет:
    pub fn foo(a: &[u8], b: &[u8], c: &mut [u8]) {
        for ((a, b), c) in a.iter().zip(b).zip(c) {
            *c = *a + *b;
        }
    }
    
    Здесь мы берем два слайса, складываем числа в них и помещаем результат в третий слайс. Самый простой способ, описанный выше — это проход в цикле по каждому слайсу, сложение и сохранение результата. Впрочем, это можно сделать быстрее и в LLVM может автовекторизовать такой код, подставив SIMD инструкции автоматически.

    Стабильный Rust уже давно использует возможности автовекторизации LLVM, но, к сожалению, компилятор может использовать подобные оптимизации не всегда. В Rust 1.27.0 добавлен модуль std::arch, включающий базовую поддержку использования инструкций SIMD напрямую из кода на Rust. Кроме того, добавлены соответствующие директивы условной компиляции:

    #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"),
          target_feature = "avx2"))]
    fn foo() {
        #[cfg(target_arch = "x86")]
        use std::arch::x86::_mm256_add_epi64;
        #[cfg(target_arch = "x86_64")]
        use std::arch::x86_64::_mm256_add_epi64;
    
        unsafe {
            _mm256_add_epi64(...);
        }
    }
    
    В примере выше флаги cfg позволяют выбрать правильную версию функции в зависимости от целевой архитектуры во время компиляции. Также мы можем это сделать в рантайме:
    fn foo() {
        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
        {
            if is_x86_feature_detected!("avx2") {
                return unsafe { foo_avx2() };
            }
        }
    
        foo_fallback();
    }
    

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

    Без SIMD

    let lots_of_3s = (&[-123.456f32; 128][..]).iter()
        .map(|v| {
            9.0 * v.abs().sqrt().sqrt().recip().ceil().sqrt() - 4.0 - 2.0
        })
        .collect::<Vec<f32>>();
    

    С SIMD (faster)

    let lots_of_3s = (&[-123.456f32; 128][..]).simd_iter()
        .simd_map(f32s(0.0), |v| {
            f32s(9.0) * v.abs().sqrt().rsqrt().ceil().sqrt() - f32s(4.0) - f32s(2.0)
        })
        .scalar_collect();
    

  • dyn Trait

    Изначальный синтаксис трейт-объектов в Rust — одна из тех вещей, о введении которых мы жалеем: для некоторого трейта Foo, его трейт-объект будет выглядеть так: Box<Foo>

    И если Foo является структурой, синтаксис аллокации структуры в «куче» будет выглядеть точно так же.

    Когда язык разрабатывался, казалось что сходство здесь уместно, но опыт показал, что это только путает людей.

    То же самое справедливо для случая impl SomeTrait for SomeOtherTrait, что является корректным синтаксисом, но интуитивно понимается как реализация трейта SomeTrait для всех типов, реализующих SomeOtherTrait, но на самом деле это записывается как impl<T> SomeTrait for T where T: SomeOtherTrait, в то время как первый вариант является реализацией трейта для трейт-объекта.

    Кроме того, появление impl Trait в противовес Trait ввело некую неконсистентность при обучении языку.

    Исходя из этого, в Rust 1.27 мы стабилизируем новый синтаксис dyn Trait.
    Теперь трейт-объейты выглядят так:

    // old => new
    Box<Foo> => Box<dyn Foo>
    &Foo => &dyn Foo
    &mut Foo => &mut dyn Foo
    

    То же самое применимо к другим типам указателей:
    Arc<Foo> теперь объявляется как Arc<dyn Foo>.

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

  • #[must_use] для функций
    Наконец, атрибут #[must_use] получил новые возможности: теперь он применим к функциям.

    Раньше он использовался только на типах, таких как Result<T, E>, где возвращаемое значение должно быть использовано, но теперь возможно такое применение:

    #[must_use]
    fn double(x: i32) -> i32 {
        2 * x
    }
    
    fn main() {
        double(4); // warning: unused return value of `double` which must be used
    
        let _ = double(4); // (no warning)
    }
    

    Также этот атрибут был добавлен к некоторым функциям в стандартной библиотеке, таким как Clone::clone, Iterator::collect и ToOwned::to_owned, теперь компилятор предупредит в случае, если их результат останется неиспользованным, что поможет заметить и предотвратить случайный вызов затратных операций.

Стабилизация стандартной библиотеки

Новые возможности Cargo

В текущем релизе в Cargo включены два маленьких нововведения:

Во-первых, Cargo теперь принимает флаг --target-dir.

Во-вторых, Cargo теперь будет пытаться автоматически найти тесты, примеры и исполняемые файлы (прим. бинарные подпроекты в библиотечных крейтах) в проекте, но явная конфигурация всё же будет требоваться в некоторых случаях.

Для помощи в конфигурации мы добавили несколько ключевых слов в Cargo.toml.

Обновить Rust можно с помощью команды:

curl https://sh.rustup.rs -sSf | sh # если у вас еще не установлен rustup
rustup update stable

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

★★★★★

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

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

Человек, который наезжал на Rust, потому что НИПАНЯТНА, защищает bash, по сравнению с которым Rust и Perl вместе взятые ясны и прозрачны? Серьёзно? В принципе, я не удивлён. Это типично, когда нечто новое кажется непонятным, а то, к чему привык, пускай оно десять раз жуткое неочевидное кривое говно — чистым и хорошим.

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

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

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

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

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

Очень толсто.

PS: В расте std::path убогий до не могу.

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

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

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

Ну перл же не зря вышел на сцену ровно в тот момент когда баш начал сосать. Они как братья-акробатья — баш и перл-однострочник внутри него

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

Ну стандартная вещь — какой-нибудь скрипт для бекапа, что ты делаешь? В баше ты поперемещал файлики, запустил tar, всё ок. В питоне ты импортишь shutil, импортишь tarfile / subprocess, пишешь ненужную херню всякую...

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

Си++ с std::filesystem - вполне себе замена башу.

Тогда и Java подойдёт.

Java медленно запускается. Сделают AOT в нормальные бинари - и Java подойдет, да.

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

Я не пишу скрипты бекапа, тем более на баше. Мне rsync хватает.

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

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

А завтра захотел бэкапить несколько папок в разные архивы, причем раскладывая эти архивы по дням недели. А инфу о неудавшихся бекапах складывать в лог вместе с выводом stderr. И отправлять результат на почту если ошибки были

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

Да ладно, тот же питон для веба и прочего серверного вполне сгодится, если нагрузка небольшая, Go, если большая. А если по середине + специфичный вкус, то сгодится и нода.

Для десктопных приложений ну или чего-то пониже те же плюсы ещё никуда не делись, также есть прямой конкурент — D. Некоторые ленивые/упоротые и на PyQt гуй пишут, а ещё есть электрон.

А для ядер операционок как был так и будет C. Разве что случится чудо, джекпот допишет Редокс, а все остальные юниксы вымрут. Но как-то я сомневаюсь.

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

Вы о чём? Rust находится в нише C/C++. Больше тут никого и нет.

прямой конкурент — D

Он мёртв. И у него нет GUI.

те же плюсы ещё никуда не делись

Между C++ и Rust выбор очевиден.

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

А если по середине + специфичный вкус, то сгодится и нода

питоновский sanic быстрее ноды, даром что внутре у него тот же самый libuv что и у ноды

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

Имелось ввиду, что дата в имени файла присутствует.

С таким туманным требованием - man sort. А вообще, проектирование структур данных решает. Даже в шелл-скриптах.

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

Пошли маневры. Ну у тебя все равно маловато шансов не обосраться. Давай уж задачку на балансировку деревьев каких-нить хитровывернутых.

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

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

На баше?

Крон, файнд, где проблема-то?

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

Имелось ввиду, что дата в имени файла присутствует.

С таким туманным требованием - man sort

sort умеет сортировать по произвольному формату данных?

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

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

Крон, файнд, где проблема-то?

Читер! Давай на баше без внешних команд, иначе нещитово!!!11

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

Он мёртв. И у него нет GUI.

Вот прямо сейчас у меня слева от окна браузера открыт очень живой и офигенный Tilix.

Между C++ и Rust выбор очевиден.

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

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

Щас бы представлять преимуществом неявный control-flow с early return против детерминированного, однозначного и явного exception-based return

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

Да, очень красиво и читаемо с ними выходит.

long long htoi(char *s)
{
    int offset = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 2 : 0;
    long long result = 0;
    for (char *temp = s + offset; *temp; temp++)
    {
        signed char digit = ((*temp >= '0') && (*temp <= '9')) ? 
            (*temp - '0') : 
            (((*temp >= 'A') && (*temp <= 'F')) ? 
                (*temp - 'A' + 10) : 
                (((*temp >= 'a') && (*temp <= 'f')) ? 
                    (*temp - 'a' + 10) : 
                    -1));
        if (digit==-1)
        {
            return -1;
        }
        result = (result << 4) + digit;
    }
    return result;
}
mersinvald ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

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

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

Это я на вскидку прикинул наименее мобильную область после операционок, могу ошибаться.

По сравнению с операционками, геймдев очень мобилен - Си++, Java, C#, Lua, Racket. Там _гораздо_ больше экспериментов, чем в ОС.

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

С чего такие выводы? Я даже функции на нём писал когда-то. Помнится был скрипт на строк 400.

Ну и тут извечный вопрос что считать башем: сам язык или unix утилиты + bash.

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

Вот прямо сейчас у меня слева от окна браузера открыт очень живой и офигенный Tilix.

Биндинги к GTK+ - это не GUI на D.

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

А ещё игровая индустрия вообще никогда не подвинется ни на какой раст.

Смотря какая. Для идюшатины не проблема.

А ААА - это совсем другая песня. И С++ у них очень своеобразный.

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

в расте можно писать в строку

WitcherGeralt: КОКОКО, ЯЗЫК ТАКОЕ ПОЗВОЛЯЕТ ЗНАЧИТ НЕНУЖНО

тернарка во все случаях кроме выражения нулевой вложенности нечитаема

WitcherGeralt: Ну а кто и зачем так делает?

Всё, что нужно знать о двойных стандартах.

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

А ещё игровая индустрия вообще никогда не подвинется ни на какой раст.

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

Расту тут и вправду ничего не светит

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

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

С чего такие выводы?

Вот с^Wиз таких высказываний:

RazrFalcon> Ну и тут извечный вопрос что считать башем: сам язык или unix утилиты + bash.

Просто в рамочку и на стену: шелл - это баш, Unix-утилиты - нечто отдельное. Вендовое прошлое (и настоящее)?

Я даже функции на нём писал когда-то

Что такое «функции» -

myfunc() { чототам; }
? Ну да, это показатель.

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

С такой логикой и C++ ничего не светит, лол.

Ниша — движки же. Падения игр из-за кривых крестовых кишков всё еще не редкость.

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

Ты либо поторопился, либо хреново читал. Я сказал, что тернарка мне нравится чисто эстетически. Ну и тут ещё разложил свою позицию подробней на примере баша.

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

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

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

Ужас... Ты понимаешь, что издавая звуки пернатых, кривляясь ты дискредитируешь сообщество языка Rust?
Как бы тяжело не было не нужно опускаться до сленга двача.

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

а ещё ключи от квартиры где деньги лежат.

slice и join есть. Как реализовать отправляю тебя к RTFM.

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

что поделать

Не спускаться.

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