LINUX.ORG.RU

Rust 1.17

 ,


3

9

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

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

$ rustup update stable

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

Что вошло в стабильную версию 1.17.0

Выпуск Rust 1.17.0 в основном вносит небольшие улучшения, преимущественно касающиеся удобства использования. Например, время жизни 'static теперь автоматически подразумевается для констант или статических переменных. При создании константы или статической переменной:

const NAME: &'static str = "Ferris";
static NAME: &'static str = "Ferris";

Rust 1.17 позволит вам больше не писать 'static, так как это единственное время жизни, которое имеет смысл:

const NAME: &str = "Ferris";
static NAME: &str = "Ferris";

В некоторых ситуациях это позволит избавиться от лишних повторений:

// было
const NAMES: &'static [&'static str; 2] = &["Ferris", "Bors"];

// стало
const NAMES: &[&str; 2] = &["Ferris", "Bors"];

Другим подобным косметическим улучшением является «короткая инициализация полей». Подобно ECMAScript 6, который называет это «Сокращение Значения Свойства Объектного Литерала» («Object Literal Property Value Shorthand»), дублирование может быть удалено при объявлении структур, к примеру:

// определение
struct Point {
    x: i32,
    y: i32,
}

let x = 5;
let y = 6;

// было
let p = Point {
    x: x,
    y: y,
};

// стало
let p = Point {
    x,
    y,
};

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

Другое маленькое, но полезное улучшение касается в основном новичков в Rust, которые пытаются использовать +, чтобы соединить две &str вместе. Но это не работает, соединить вы можете лишь String + &str. Поэтому, было добавлено новое сообщение об ошибке, чтобы помочь пользователям, которые совершают подобную ошибку:

// код
"foo" + "bar"

// было
error[E0369]: binary operation `+` cannot be applied to type `&'static str`
 --> <anon>:2:5
  |
2 |     "foo" + "bar"
  |     ^^^^^
  |
note: an implementation of `std::ops::Add` might be missing for `&'static str`
 --> <anon>:2:5
  |
2 |     "foo" + "bar"
  |     ^^^^^

// стало
error[E0369]: binary operation `+` cannot be applied to type `&'static str`
 --> <anon>:2:5
  |
2 |     "foo" + "bar"
  |     ^^^^^
  |
  = note: `+` can't be used to concatenate two `&str` strings
help: to_owned() can be used to create an owned `String` from a string
reference. String concatenation appends the string on the right to the string on
the left and may require reallocation. This requires ownership of the string on
the left.
  |     "foo".to_owned() + "bar"

При использовании сценариев сборки Cargo вы должны указать расположение скрипта в вашем Cargo.toml. Однако, подавляющее большинство людей писали build = «build.rs», тем самым используя файл build.rs, расположенный в корне проекта. Теперь это соглашение поддерживается самим Cargo, и будет использовано по умолчанию, если существует файл build.rs. Мы предупреждали об этом изменении в течение нескольких последних выпусков. Вы также можете использовать build = false для отказа от этого соглашения.

В этом выпуске удалена старая система сборки на основе Makefile. Новая система, анонсированная в Rust 1.15, написана на Rust и в основном использует Cargo для управления сборкой. На данный момент она уже достаточно зрелая, чтобы быть единственной системой сборки.

В рамках этого изменения, пакеты из crates.io теперь можно использовать в системе сборки Rust. Первым был добавлен mdBook, и он теперь используется при сборки нашей разнообразной книжной документации:

Обратите внимание на ссылки на соответствующие репозитории; документы были перемещены из основного дерева. Кроме того, мы добавили четвертую книгу, которая все еще расположена в основном дереве: Книга «Нестабильные возможности Rust». Она описывает нестабильные возможности, содержит ссылки на задачи, связанные с их стабилизацией, и может содержать исходную документацию. Если есть возможность, которую вы хотите увидеть стабилизированной, то пожалуйста, примите участие в ее обсуждении!

Несколько выпусков назад rustup перестал по умолчанию устанавливать документацию. Мы внесли это изменение, чтобы немного разгрузить канал, а также потому, что не все пользователи в действительности хотят хранить локальную копию документации. Однако это создало ловушку: некоторые пользователи не были в курсе, что произошло изменение, и заметили бы это, только если бы у них пропало подключение к Интернету. Кроме того, некоторые пользователи хотели иметь локальную копию документации, независимо от их подключения. Таким образом, мы откатили данное изменение, и документация снова устанавливается по умолчанию.

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

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

Был стабилизирован 21 новый интерфейс:

  • Arc::into_raw и Rc::into_raw позволят вам забрать Arc или Rc и получить сырой указатель.
  • Arc::from_raw и Rc::from_raw позволят вам забрать сырой указатель и получить Arc или Rc.
  • Arc::ptr_eq и Rc::ptr_eq возвращает true если оба Arc или оба Rc указывают на одно и то же значение (не обязательно значения, которые сравниваются, равны).
  • Ordering::then позволит вам сцепить два Ordering вместе, и Ordering::then_with позволит сделать это с помощью функции.
  • BTreeMap::range позволит вам итерировать лишь по части BTreeMap, и BTreeMap::range_mut позволит вам сделать это с возможностью изменения. collections::Bound может дать вам еще больше контроля.
  • process::abort будет полностью завершать процесс анормальным образом.
  • ptr::read_unaligned и ptr::write_unaligned аналогичны ptr::read и ptr::write, но без требований к выравниванию.
  • Result::expect_err зеркально подобен Result::expect, то есть работает с вариантом Err, а не с вариантом Ok.
  • Cell::swap аналогичен std::mem::swap, но позволяет вам делать это с &Cell вместо &mut T.
  • Cell::replace аналогичен std::mem::replace, но позволяет вам делать это с &Cell вместо &mut T.
  • Cell::into_inner позволит вам взять Cell, и извлечь его значение.
  • Cell::take позволит вам забрать значение Cell наружу, заменив его на Default::default.

Что касается других изменений, для многих методов Cell<T> требовалось ограничение T: Copy, но теперь это требование значительно ослаблено.

Box<T> теперь реализует более дюжины новых преобразований с помощью From.

SocketAddr и IpAddr также теперь имеют несколько новых преобразований. Раньше вы должны были писать код вроде этого:

"127.0.0.1:3000".parse().unwrap()

Сейчас же вы можете писать
SocketAddr::from(([127, 0, 0, 1], 3000))
// или
([127, 0, 0, 1], 3000).into())

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

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

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

Помимо ранее упомянутых изменений, касающихся build.rs, у Cargo есть еще несколько новых улучшений. cargo check --all и cargo run --package — два отсутствовавших до этого момента флага, которые теперь поддерживаются.

Теперь вы можете игнорировать проверки отзыва SSL. Конечно, по умолчанию проверка все еще производится.

Новое поле в Cargo.toml, required-features, позволяет указать конкретные возможности, которые должны быть установлены для цели, которую нужно собрать. Вот пример: предположим, что мы пишем контейнер, который взаимодействует с базами данных, и хотим, чтобы он поддерживал несколько баз данных. Мы могли бы это сделать в нашем Cargo.toml:

[features]
# ...
postgres = []
sqlite = []
tools = []

Возможность tools позволяет нам включить дополнительные инструменты, а возможности postgres и sqlite указывают, какие базы данных мы хотим поддерживать.

Раньше cargo build пыталась собрать все цели, которые вам нужны. Но что, если у нас есть файл src/bin/postgres-tool.rs, который является нужным только при условии, что возможности postgres и tools были включены? Раньше нам приходилось писать что-то вроде этого:

#[cfg(not(all(feature = "postgres", feature = "tools")))]
fn main() {
    println!("This tool requires the `postgres` and `tools` features to be enabled.");
}

#[cfg(all(feature = "postgres", feature = "tools"))]
fn main() {
    // код
}

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

С помощью нового ключа required-features мы можем добавить следующее:

[[bin]]
# ...
required-features = ["postgres", "tools"]

Теперь cargo build будет собирать наш postgres-tool, только если у нас включены две эти возможности, и поэтому мы можем написать нормальный fn main без всяких нагромождений вроде cfg.

Разработчики версии 1.17.0

Много людей внесли свой вклад в создание Rust 1.17. Мы не смогли бы сделать это без всех вас. Спасибо!

Авторы перевода и публикации @kgv, @vitvakatu, @ozkriff.

>>> Подробнее смотрите примечания к выпуску

★★★★★

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

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

привязка к llvm

Это же наоборот отвязка. Бекенд будет либо перемешан с кодом компилятора (тогда он привязан, прибит гвоздями, теряется гибкость), либо будет отдельным проектом. Такой отдельный проект есть - llvm. Вот когда он перемешан с основным кодом, тогда его нельзя использовать где-то еще. Ну скопипасть код llvm в rust, легче станет? Что поменяется?

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

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

я еще раз процитирую:

Если сделаешь что-то неправильно, то получишь ошибку компиляции

серьёзно, ownership/borrowing system заруливает все косяки? а почему тогда происходит такое:

Вчера в очередной раз посмотрел на эффективность этого Servo. Вот результат за приблизительно минуту тестирования: https://postimg.org/image/b0thfx14v/ Грешным делом думал, что увижу панику, но увидел дедлок. А так да, наплодить 337 потоков и грузить ими сайт с полной загрузкой всех ядер процессора в десять раз дольше, чем это делает хром (а после этого при прокрутке - вообще зависнуть намертво) у серво получается замечательно. Кстати, правильно рендерить оно до сих пор не умеет даже примитивный LOR (так что не рассказывайте мне про HTML5/CSS3). И вот у меня вопрос: а что же, собственно, авторы хотели продемонстрировать этим серво? Надёжность? Фейл. Безопасную работу с потоками? Снова фейл. Скорость разработки? Фейл, фейл, фейл.

почему оно скомпилировалось, если сделали неправильно?

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

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

У гугловцев аналогичный опыт ещё больше.

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

Во-вторых, это вообще не важно, т.к. нельзя оставлять ссылки на объекты, для которых уже был вызван деструктор.

Про это уже писали выше. А так - спасибо.

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

погоди. наверно мы по разному понимаем слово «неправильно».

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

у курильщиков, неправильно это когда программа упала и денежку рабу-фрилансеру не заплатили. от этого у раба подгорает жопонька.

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

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

но это не единственный способ сделать ошибку. более того, раст привлекает бракоделов, у которых бомбит от С++ потому что в С++ их говнокод падает. например в треде про 337 потоков растаманы не понимают, что не так с этими 337ю потоками. «нуачо?». отсутствует фундаментально понимание, что в этой ситуации неправильно.

кстати, а ты там тоже отметился. нука щас пересмотрим, что ты писал там.

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

Слышал да, врешь зачем?

https://github.com/contiki-os/contiki/blob/master/cpu/x86/bootstrap_quarkX1000.S

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

Не ври. Без ассемблерных вставок невозможна ни одна операционная система - просто потому что ни один более менее высокоуровневый язык не в курсе ни про регистры cr0-cr4 и инструкции для работы с ними и их аналоги в других архитектурах вроде сp15 у арма и cop0 у мипса.Не знают они и про in out, без которых ты пинус, а не многозадачную ось напишешь.

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

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

Понимание ровно одно. И оно чётко описано в доке.

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

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

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

ownership/borrowing system спасает от

  • buffer overflow
  • stack overflow
  • use after free
  • double free
  • data races
  • segmentation faults

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

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

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

Ну подожди. Ты выдвигаешь определённые требования и говоришь, что и С далёк от идеала. Так смысл ровняться на недостижимый идеал?

Раст однозначно «более системный», чем большинство мейнстримных языков и вполне способен «конкурировать» с С: вопрос в инфраструктуре и желании. Наверное, можно и лучше, но никаких «особых извращений» не требуется.

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

Это очень серьезная проблема. Потому что после double free следующий вызов malloc может вернуть плохой указатель и будешь неделю дебажить почему оно все падает в рандомных местах.

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

Циклический Rc, mem::forget. Других способов, насколько я знаю, нет.

Но если с Rc ещё можно налажать, то forget только вручную нужно вызывать, что сильно снижает уровень проблем.

PS: forget нужен по большей части для FFI, чтобы можно было отдать указатель и забыть о нём.

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

Так это, как я понимаю, как раз способ обмануть ownership, т.е. вручную вмешаться и сказать, что программист берет ответственность на себя. Т.е. это преднамеренная утечка памяти в отличии от непреднамеренных утечек в C/C++/Ada, когда программист просто забывает освобождать ранее выделенную память.

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

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

Это очень серьезная проблема. Потому что после double free следующий вызов malloc может вернуть плохой указатель и будешь неделю дебажить почему оно все падает в рандомных местах.

А с чего malloc должен вернуть плохой указатель?

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

должно

кому должно и почему?

после new должны быть delete :-)

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

А с чего malloc должен вернуть плохой указатель?

обьсню на пальцах

a = malloc(...);
free(a);
b = malloc(...);
free(a);
c = malloc(...);

Все три вызова malloc вернут один и тот же указатель и получишь что b и с указывают на одну и ту же память.

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

Этож просто анализ регионов, который ловит висячие указатели, чего вы от него ждете?

let x = Box::new(SomeShit::new());

while true {}

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

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

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

Аноним, узнай пожалуйста что такое утечка. Здесь x — это просто ресурс, который живет всё время жизни программы. Как только ивентлуп завершится, ресурс будет освобожден перед завершением программы.

Утечка — это когда программа теряет возможность освободить память раньше чем память освобождена (указатель на структуру уходит из скопа без free)

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

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

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

По твоей логике если ты в джаве хранишь ссылку на объект, но не используешь ее — это тоже утечка!
BREAKING NEWS! УТЕЧКИ В JVM!

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

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

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

Так же как и тут.

SomeShit x = new SomeShit();

while(true) {}

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

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

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

Лол, но это же не утечка. Можно потроха назвать зефиром и говорить что в курице внутри зефир.

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

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

В примере с джавой, кстати, ты реально ничего не сделаешь до выхода ссылки из скопа, но это все равно не утечка потому что не ОС подчистит, а JVM в итоге.

В примере с растом ты можешь сделать x.drop() и освободить ресурс в любое время работы в своем ивент-лупе

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

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

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

если он не используется в работе программы

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

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

Терминология не так однозначна, например google: logical memory leak

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

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