LINUX.ORG.RU

Rust 1.19

 


3

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 ()
Последнее исправление: Virtuos86 (всего исправлений: 3)
Ответ на: комментарий от Virtuos86

Вот там выше поясняют за сноску. Тут всё же ссылка. Да и официальное название у неё такое. Ничего не поделать.

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

Куда же делись ваши эстетические чувства? Очевидно, что тут должно быть минимум constant reference to a.

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

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

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

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

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

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

Вообще ссылка - это просто смещение в памяти.

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

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

Вы вместо того, чтобы воду мутить, лучше бы примеры «хорошего» привели. Претензии выдавать - много ума не надо.

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

Вики говорит, что сноска это примечание, помещаемое где-то отдельно от текста. В контексте ЯП это означает, что сноска не является значением (value), но является примечанием к значению. Примечание к значению типа T указывает, что можно делать с этим значением в данном контексте (блоке кода). Всё сходится. А ну цыц, англодумающие неруси!)

Upd: то есть каждый блок кода является отдельным «текстом», определяющим контекст, в котором существуют сноски.

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

Вообще ссылка - это ровно то, что означает на языке Rust. На языке C++ это другая сущность. На уровне железа ее вообще не существует. И компилятор не смотрит, а превращает код с одного языка (Rust) в код на другом языке (llvm ir).

либо говорит deny и генерирует исключение

Хватит писать чушь.

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

Я Вам привёл проблему которая постоянно появляется при использовании семафоров и мьютексов. В расте это пофиксили. Как Вы выразились

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

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

для чего нужны угловые скобки с 3-х кратной вложенностью?

Вы про ARC<RC<Vec<...>>>?

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

И то что всякие ruby и т.д. не вышли за пределы своей ниши из-за своей системы пакетирования не приняли во внимание.

Серьёзно? То есть, Ruby исключительно «система пакетирования» помешала захватить мир? А ничего, что свой «пакетный менеджер»/система сборки в каждом первом более-менее свежем языке есть?

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

В контексте ЯП это означает, что сноска не является значением (value), но является примечанием к значению. Примечание к значению типа T указывает, что можно делать с этим значением в данном контексте

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

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

А ну цыц, англодумающие неруси!)

Вот когда хотя бы одна русскоязычная страна станет из себя хоть что-нибудь в computer science представлять (в плане инноваций, а не в плане «мы хорошо освоили то, что придумали англодумающие неруси»), вот тогда и «цыц» :D

А пока что — «конст референс ту тэ». Ну или «константная референса на тэ».

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

Хочешь, чтобы я двинул ноги с голодухи? Вот «указатель», кстати, намного более грамотный термин, чем «ссылка».

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

Хватит писать чушь.

Ну ОК, напишите тогда что умное. Слово чушь - неумное. Это просто критиканство. Даже люди в дурдомах постоянно что-то критикуют и ничего не предлагают.

Насчёт ссылки - да, на уровне машинного кода любые куски данных адресуются по смещениям, в том числе и смещениям в стеке. И что? Ссылка - это значение смещения в памяти, по которому записано другое смещение в памяти. Так лучше?

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

Вот когда хотя бы одна русскоязычная страна станет из себя хоть что-нибудь в computer science представлять (в плане инноваций, а не в плане «мы хорошо освоили то, что придумали англодумающие неруси»), вот тогда и «цыц» :D

Выше пример давали про thread/stream. До «потоков» ведь додумались...

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

Речь о том, «указатель» в отличие от «ссылки» не вызывает недоумения.

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

Но указатель и ссылка - это разные вещи.

Чойта? Ссылка это такой высокоуровневый указатель. Просто плюсатые вынуждены были новый термин придумать для своей мути, и все цепепе-утята его подхватили.

bread
()

В общем собрал в одно месте весь тупняк хейтеров и попытался на него ответить.

  1. На Rust ничего не написали за 7 лет.

    Rust 1.0 вышел 15 мая 2015-го. Как не сложно посчитать, ему всего 2 года.

  2. На Rust нет серьезных проектов.

    Какие серьезные проекты предполагается реализовать за пару лет? Photoshop?

  3. Rust никто не использует.
    • На Rust написали уже 10k+ пакетов.
    • Rust включён в репозитории большинства дистрибутивов linux.
  4. Rust не используют крупные компании.

    Используют.

  5. У Rust нет вакансий.

    Вакансий действительно мало. Но в его области применения, там же где и C/C++, вакансий в принципе не много. Сравнивать его с Go, Swift - бессмысленно.

  6. У Rust ужасный синтаксис.

    У Rust сложный синтаксис. Это следствие низкоуровневости и предлагаемых гарантий. Сравнивать его с Python, который является скриптовым ЯП с GC, - бессмысленно.

    Сравнивать нужно с его ближайшим конкурентом - C++. И в данном сравнении Rust лаконичнее.

  7. Rust небезопасный, ведь у него есть unsafe и все будут им использоваться.

    Гарантии Rust распространяются на обычный код. unsafe - это механизм обхода текущих ограничений компилятора.

    Практика показывает, что unsafe почти не используется и/или является опциональным. К примеру как оптимизация во избежание bounds checking.

  8. Современный C++ даёт те же гарантии, что и Rust.

    Частично.

    • Современный C++ по-прежнему не даёт никаких механизмов для упрощения написания многопоточных приложений (аналог Send/Sync из Rust, которые проверяются на этапе компиляции).
    • Большая часть библиотек по-прежнему работает с сырыми указателями (тот же Qt).
    • Умные указатели помогают избежать утечек, use-after-free, double free, но не гарантируют этого.
  9. Rust не отличается от современного C++.

    Rust имеет:

    • pattern matching
    • ADT
    • систему владения (borrowing)
    • указание времени жизни объекта (lifetimes)
    • типажи (traits), да, в C++ есть нечто подобное, но в ужасном виде
    • строгую типизацию, да, в C++11 изобрели list initialization, но это костыль
    • модули
    • единую систему сборки, документации, тестирования
    • репозиторий пакетов
    • нормальные макросы (hygienic macros)
    • возврат нескольких значений (tuple как часть языка)
    • простой статический полиморфизм
    • etc.
  10. Нормальный программист не совершит ошибок, от которых защищает Rust.

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

  11. Rust не защищает от утечек.

    Технически - да, не защищает. Утечка памяти не является нарушением memory safety. Но получить её довольно сложно. Для этого нужны: циклические ссылки, mem::forget и unsafe. При том последние два легко отловить при рецензировании кода.

  12. Rust не защищает от логических ошибок.

    Он это и не постулирует.

  13. В Rust постоянно ломают совместимость.

    Технически - да. Но начиная с 1.0 все изменения были незначительными и не затронули большую часть пользователей. Все пакеты из crates.io (10k+ штук) собираются новой версией компилятора перед релизом и если находятся какие-то проблемы - автору отправляется патч.

  14. Rust недостаточно низкроуровневый, чтобы заменить С.

    Уже есть прототип ОС на Rust - Redox. Если примеры использования Rust на микроконтроллерах.

    Но список поддерживаемых архитектур по-прежнему мал.

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

Отличие with от target-переменной в семантике: семантика «точки» однозначна, это сокращение записи. Семантика target'а абсолютно непрозрачна: надо как-то очень хитро назвать переменную, чтобы понять, что она является неким «псевдонимом» для a.b.c.d Без этого же даже умная IDE никогда не сможет сообщить, что вот эта переменная - не самостоятельный объект, а просто способ сокращения записи.

В языках, в которых присутствуют понятия «указатель» или «ссылка» (т.е. во всех современных, кроме какой-нибудь узкоспециализированной экзотики), переменная часто бывает «псевдонимом» для другой. В Расте ссылки есть. Более того, из-за move семантики и безопасности, гарантированной borrow checker'ом, в Расте ссылки ещё распространённее, их можно и нужно использовать часто не теряя в надёжности кода.

Если Вы знаете, для чего нужен target и на что он ссылается - это не значит, что Вы не будете проклинать себя же через 3 года или вам ну будет икаться, когда этот код унаследует ваш преемник/коллега.

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

with foo.bar.baz
   .waldo=1
   .fred=3.0
   .do_something()
end with
идеальным, и немного избыточным аналогом в расте был бы код типа
{ 
   let  = &mut foo.bar.baz;
   .waldo=1
   .fred=3.0
   .do_something()
}
Но он невозможен, потому что в расте нельзя иметь переменную с пустым именем. Придётся использовать хотя бы одну букву, например a (сокращение от alias).
{ 
   let a = &mut foo.bar.baz;
   a.waldo=1;
   a.fred=3.0;
   a.do_something();
}
С точки зрения понятности полный аналог, что есть «a» видно, оно вот тут, вначале блока. Конец блока тоже отмечен. Один минус, бессмысленное имя «a» («» в случае настоящего with), из-за которого читателю приходится прыгать вверх и смотреть, что же там назначили. Более того, увидев, что имеется в виду «foo.bar.baz» читатель должен вспомнить, почему именно foo.bar.baz, а не foo.bar.qux. Это сильно напрягает кратковременную память. Но подход с переменной предлагает решение: если в рамках этого куска алгоритма у foo.bar.baz есть какая-то внятная роль (например «приёмник» в случае, если тут происходит копирование данных или «аккумулятор» или ещё что), то можно сильно улучшить читабельность, назвав переменную-алиас внятным именем. Блок становится элементом декомпозиции, при взгляде поверх него видно, что foo.bar.baz - это target, т.е. приемник информации, при рассмотрении содержимого блока программист работает в контексте подзадачи, ему не надо смотреть на что ссылается псевдоним, назначение видно из названия.

Кроме того, можно в одном блоке создать 2 псевдонима (source и target, например), что в случае with невозможно.

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

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

Нет не лучше. Вы описываете сейчас реализацию ссылки. Почему вы считаете что она должна определять её семантику?

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

«Rust недостаточно низкроуровневый, чтобы заменить С.» Этого достаточно, чтоб не называть его системным. А то получается, что мол системный, но С заменить не может. Не надо выдумывать новые языки - это мажорство и понты, сколько их придумали за последние пяток лет? Я уж со счета сбился. Истинные, православные языки типа С, С++, божественной жабки живут и здравствуют, все остальное - понты.

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

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

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

Ой, извини, не заметил ржачных комментов выше.

Вообще ссылка - это просто указатель.

RazrFalcon ★★ (31.07.2017 18:16:47)

Но указатель и ссылка - это разные вещи.

RazrFalcon ★★ (31.07.2017 18:50:44)

Вот что бывает, если долго кодить на цепепе. Начинаешь спорить с голосами в голове.

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

когда увижу ядро ОС на русте

redox же. Был даже срач на лоре про это, поищи.

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

Первая строка - это не утверждения, а вбросы местных неадекватов.

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

Ну это так только тип пишется. Как ранее писали - Rc и Arc контролируют неизменяемый объект, поэтому типичное их использование выглядит как Rc<Cell<T>> в однопоточной программе и Arc<Mutex<T>> в многопоточной.

В коде это будет выглядеть так

let arc_data = Arc::new(Mutex::new(Box::new(Data)));

Обворачивая в Box мы данные кладём не на стек, а на кучу. Обворачивая в Mutex появляется возможность синхронизации данных между потоками и обворачивая в Arc мы имеем атомарный подсчёт ссылок. Как только все потоки перестанут использовать, те данные, что есть в Arc, так он их и освободит. Таким образом не будет утечек памяти, состояния гонок и кучи ненужных переменных для мьютекса, счётчика ссылок и указателя. Сильно ли Rust поменял подход который был раньше в других языках программирования? Не особо. НО теперь компилятор в случае ошибки программиста не скомпилирует код и это хорошо.

Реальный пример.

Там ещё апострофы появляются с самых неожиданных местах.

На самом деле нет. Ибо объект один и время жизни ресурса одно. А значит нет не определённости и указать что-то вроде 'a не нужно.

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

Но он невозможен, потому что в расте нельзя иметь переменную с пустым именем. Придётся использовать хотя бы одну букву, например a (сокращение от alias).

Вами приведённый код не корректный, его не пропустит компилятор

{ 
   let a = &mut foo.bar.baz; // <= Тут проблема  
   a.waldo=1;
   a.fred=3.0;
   a.do_something();
}

Корректный такой:

{
    let a = &mut Foo {
                     waldo: 1,
                     fred: 3.0,
                 };
    a.do_something();
}

И кмк, он проще примера с with ;)

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

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

Во-вторых, всё работает. https://play.rust-lang.org/?gist=33ad706e0866c577da6e2d5c0cc5f171&version...

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

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

Практика показывает, что unsafe почти не используется и/или является опциональным.

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

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

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

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

Современный C++ по-прежнему не даёт никаких механизмов для упрощения написания многопоточных приложений (аналог Send/Sync из Rust, которые проверяются на этапе компиляции).

Он даёт тебе модель памяти (а раст даёт?). При наличии мозга программы получаются мягкие и шелковистые.

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

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

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

А про rust memory model не знаю.

В доках написано что

Rust's memory orderings are the same as LLVM's [1]
[1] http://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations

А в доках LLVM написано

This model is inspired by the C++0x memory model.

Так что получается в расте такая же модель как в плюсах.

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

Через сколько лет после создания языка она появилась, не напомните? IIRC только в C++11,а это больше 25 лет, если что. Rust в котором эта проблема актуальна (т.е. когда он перестал быть эрлангом с плюшками) — 3 года, а с релиза 1.0 и того меньше. И проблемой отсутствия формализованной memory model занимаются.

grossws
()
Последнее исправление: grossws (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.