LINUX.ORG.RU

Rust 1.19

 


4

8

Команда Rust рада объявить о последней версии Rust, 1.19.0. Rust это системный язык программирования, сфокусированный на безопасности, скорости и конкурентном выполнении.

Если у вас установлена предыдущая версия Rust, то получите Rust 1.19, выполнив команду:

$ rustup update stable

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

Что нового в 1.19.0 stable

Rust 1.19.0 получил некоторые долгожданные возможности, но для начала примечание для наших пользователей Windows. На Windows Rust полагается на link.exe для линковки, который вы можете получить из “Microsoft Visual C++ Build Tools.” С последним выпуском Visual Studio 2017, структура каталогов для этих инструментов изменилась. Таким образом, чтобы использовать Rust, вы должны придерживаться инструментов 2015 или использовать обходной путь (такой как запуск vcvars.bat). В 1.19.0 rustc теперь знает, как найти инструменты 2017, и они работают без использования обходных путей.

А теперь к новым возможностям! Rust 1.19.0 это первый выпуск, который поддерживает объединения (unions):

union MyUnion {
    f1: u32,
    f2: f32,
}

Объединения это вид перечислений (enums), но в отличие от последних они «непомечены» («untagged»). Перечисления имеют «пометку», которая хранит информацию, какой вариант является правильным в рантайме; объединения игнорируют эту пометку.

Так как мы можем интерпретировать данные, хранящиеся в объединении, используя неправильный вариант, и Rust не может проверить это для нас, это означает, что чтение или запись поля объединения является unsafe:

let u = MyUnion { f1: 1 };

unsafe { u.f1 = 5 };

let value = unsafe { u.f1 };

Сопоставление с образцом также работает:

fn f(u: MyUnion) {
    unsafe {
        match u {
            MyUnion { f1: 10 } => { println!("ten"); }
            MyUnion { f2 } => { println!("{}", f2); }
        }
    }
}

Когда полезны объединения? Одним из основных случаев использования является интероперабельность с Си. C API могут использовать объединения, и во многих областях часто это делают, и с появлением объединений в Rust написание оберток для API подобных библиотек становится значительно проще. Дополнительно, из этого же RFC:

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

Эту возможность уже давно ждали, и еще больше улучшений на подходе. Сейчас объединения могут только содержать Copy типы и не могут реализовывать Drop. Мы ожидаем снятия этих ограничений в будущем.

Также циклы loop теперь имеют возможность возвращать значение при выходе с break:

// old code
let x;

loop {
    x = 7;
    break;
}

// new code
let x = loop { break 7; };

Rust традиционно позиционируется как «язык, ориентированный на выражения», в котором большинство вещей являются выражениями, вычисляющимися в значения, а не директивами. Раньше loop странно выделялся, так как был директивой.

Что насчет других форм циклов? Здесь еще не всё ясно. Посмотрите этот RFC для ознакомления с некоторыми дискуссиями вокруг открытых вопросов.

Замыкания, которые не захватывают окружение, теперь могут быть приведены к указателю на функцию:

let f: fn(i32) -> i32 = |x| x + 1;


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

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

Наибольшей новой библиотечной возможностью являются макросы eprint! и eprintln!. Они работают так же, как и print! и println!, но пишут в стандартный поток ошибок, а не в стандартный поток вывода.

Другие нововведения:

.

И некоторые недавно стабилизированные API:

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

Cargo

Cargo в основном получил небольшие, но значимые улучшения в данном выпуске. Так, Cargo больше не проверяет локальный рабочий каталог для индекса crates.io. Это должно обеспечить меньший размер файла для реестра и улучшить время клонирования, особенно на машинах Windows.

Другие улучшения:

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

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

★★★★★

Проверено: Shaman007 ()
Ответ на: комментарий от grossws

если она появится в формально описанном виде и в расте, то будет хорошо

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

если inspired означает «совпадает до буквы», то ок

Нет, не совпадает. Например в расте нету memory_order_consume (который все равно не работает в плюсах).

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

Осталось понять, какая программисту польза от этого.

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

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

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

Осталось понять, какая программисту польза от этого.

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

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

польза проста

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

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

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

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

Появится, конечно. Народ понимает её необходимость и работает над этим. Библиотеки-то не всегда целиком на safe rust, где всё хорошо.

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

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

Я просто сразу не понял что Вы имели ввиду. Можно юзать семантику обновления с затенением текущей переменной, но выглядеть это будет... кхм... Странно =)

let mut foo = Foo{bar : Bar{baz : Baz{waldo : 1, fred : 3.0}, .. foo.bar}};

Из минусов, чтобы println был на том же месте как и в Вашем примере, надо реализовать Copy типаж для Baz...

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

Rust без unsafe - это Haskell для бедных. Haskell же живет без unsafe. Он нужен для асемблерных вставок и битхаков.

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

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

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

Да при чём здесь вообще ускорение написания кода? То к чему ты придрался, это скорее о гибкости. Вон в плюсах есть, например, «просто» shared_ptr - внутри атомарный счётчик ссылок. Вот только иногда подсчёт ссылок нужен, а многопоточность - нет. И что тогда? На этот случай в бустовой реализации имеется дефайн, вот только он глобальный. Если надо и так и этак, то облом, а в расте такой проблемы не будет.

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

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

Я такого не писал. Давайте конкретно: что вам не удалось написать без

страшных костылей и прыжков с бубном вокруг компилятора

?

В отличии от Хаскеля в расте рантайма так же мало как в си (приблизительно) и есть возможность работать с ссылками не нарушая memory safety. Потому он системный язык.

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

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

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

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

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

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

Как это работает: функция которая создает канал возвращает два значения (половинки) rx и tx.

rx имеет тип Send + !Sync

tx имеет тип Send + !Sync + Clone

Ограничение !Sync говорит о том что нельзя пользоваться таким обьектом из нескольких потоков сразу, а Send только разрешает перемещать обьект из одного потока в другой.

Но tx еще дополнительно реализует Clone. Следовательно разрешается создать много копий tx и поотправлять (Send) их по разным потокам.

Копию rx сделать невозможно, так что владеть им будет всегда только один поток.

В итоге получили систему в которой на этапе компиляции гарантируется что пользователь не сможет неправильно воспользоваться этим каналом.

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

но пока вбрасывать не буду, подожду следующей новости.

Почему?

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

Достаточно в этот процесс вставить какую-нибудь глобальную переменную (типа кэша) и писать-читать туда без синхронизации.

Будет «К контейнеру претензии есть?», а работать будет с undefined behaviour.

Если в расте нельзя без Arc<Park<Spark#<Rc<Mc&'>>, Mut>> ptr читать глобальные переменные, то жизнь всё равно вынудит рано или поздно это делать.

А если учесть distributed programming, то средства раста вообще бессильны от изменения shared state другими процессами. Жизнь - боль. На всех языках программирования.

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

Если в producer/consumer заставить использовать только неизменяемые объекты и не использовать внешнее окружение, то можно сказать, что такая имплементация producer/consumer потокобезопасна.

Но в реальности есть ситуации, когда используется shared state или системные ресурсы, и тогда никакой sync/send не может гарантировать, например отсутствие параллельной записи в один и тот же файл на гибкий диск.

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

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

В глобальную переменную можно положить только Sync типы, например атомики.

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

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

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

В глобальную переменную можно положить только Sync типы, например атомики.

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

====

Достаточно написать на rust (или на плюсах) потокобезопасный логгер - и станет очевидно, что серебряной пули нет.

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

А можно и не положить

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

Хотя тут на лоре уже были такие примеры, это да.

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

stdin и stdout в расте лежат под мьютексом, так что даже простейший println не будет рвать строку посередине.

pftBest ★★★ ()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)