Pull to refresh

Выпуск Rust 1.32

Reading time 5 min
Views 7.8K
Original author: The Rust Release Team

Команда разработчиков Rust рада сообщить о выпуске новой версии Rust, 1.32.0. Rust — это язык программирования, который дает возможность каждому создавать надежное и эффективное программное обеспечение.


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


$ rustup update stable

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


Небольшое замечание: за последнее время вышло несколько новых выпусков rustup! Чтобы обновить сам rustup, выполните rustup self update.

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


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


Макрос dbg


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


let x = 5;

println!("{:?}", x);

// или даже так
println!("{:#?}", x);

Это не самое большое препятствие, замедляющее разработку, но это требует чересчур много усилий для простого отладочного вывода значения x. Кроме того, тут не учитывается контекст. Если у вас есть несколько таких println!-ов, то становится сложно определить, что к чему относится в выводе, пока вы сами не добавите информацию о контексте к каждому вызову, что требует еще больше работы.


Для этих целей в Rust 1.32.0 мы добавили новый макрос dbg!:


fn main() {
    let x = 5;

    dbg!(x);
}

После запуска этой программы, вы увидите:


[src/main.rs:4] x = 5

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


Кроме того, println! печатает в стандартный поток вывода, поэтому лучше использовать eprintln! для печати в стандартный поток ошибок. Макрос dbg! выводит в stderr, и это правильно.


Это работает даже в сложных случаях. Рассмотрим пример реализации факториала:


fn factorial(n: u32) -> u32 {
    if n <= 1 {
        n
    } else {
        n * factorial(n - 1)
    }
}

Для того, чтобы его отладить, мы можем использовать eprintln!:


fn factorial(n: u32) -> u32 {
    eprintln!("n: {}", n);

    if n <= 1 {
        eprintln!("n <= 1");

        n
    } else {
        let n = n * factorial(n - 1);

        eprintln!("n: {}", n);

        n
    }
}

Мы хотим выводить n на каждой итерации и видеть контекст каждой из веток. Для factorial(4) будет выведено:


n: 4
n: 3
n: 2
n: 1
n <= 1
n: 2
n: 6
n: 24

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


Рассмотрим тот же пример с использованием dbg!:


fn factorial(n: u32) -> u32 {
    if dbg!(n <= 1) {
        dbg!(1)
    } else {
        dbg!(n * factorial(n - 1))
    }
}

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


[src/main.rs:3] n <= 1 = false
[src/main.rs:3] n <= 1 = false
[src/main.rs:3] n <= 1 = false
[src/main.rs:3] n <= 1 = true
[src/main.rs:4] 1 = 1
[src/main.rs:5] n * factorial(n - 1) = 2
[src/main.rs:5] n * factorial(n - 1) = 6
[src/main.rs:5] n * factorial(n - 1) = 24
[src/main.rs:11] factorial(4) = 24

Так как макрос dbg! возвращает само отлаживаемое значение, в отличии от eprintln!, который возвращает (), то нам не нужно делать никаких изменений в структуре нашего кода. Дополнительно мы получаем гораздо более полезный вывод.


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


По умолчанию убран jemalloc


Давным-давно у Rust был большой рантайм, подобный Erlang'овому. Для него был выбран jemalloc вместо системного аллокатора, потому что он часто был производительнее. Постепенно мы все больше и больше избавлялись от рантайма и в конце-концов он почти весь был удален, но jemalloc остался. У нас не было способа выбирать пользовательский аллокатор, и поэтому мы не могли окончательно убрать jemalloc, чтобы не навредить тем, кто нуждался в нем.


Кроме того, утверждение, что jemalloc был всегда аллокатором по умолчанию, относилось преимущественно к UNIX-миру, так как он был по умолчанию только на некоторых платформах. В частности цель MSVC на Windows уже давно использует системный аллокатор.


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


По этим причинам, как только Rust 1.28 предоставил способ выбирать глобальный аллокатор, мы начали планировать переход на системный аллокатор по умолчанию и предоставление jemalloc в качестве внешней библиотеки. В Rust 1.32 мы наконец завершили эту работу, и теперь по умолчанию ваша программа будет использовать системный аллокатор.


Если вы хотите продолжать использовать jemalloc, используйте библиотеку jemallocator. Для этого в Cargo.toml укажите:


jemallocator = "0.1.8"

И в корневом файле вашего проекта:


#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

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


Заключительные улучшения системы модулей


В последних двух выпусках мы говорили о нескольких улучшениях системы модулей. В 1.32.0 и редакцию 2018 мы добавили последнее изменение. Оно называется "единообразные пути" ("uniform paths") и разрешает работать с путями импорта также, как с остальными путями, что до этого работало некорректно. Например:


enum Color { Red, Green, Blue }

use Color::*;

Этот код ранее не компилировался, поскольку пути в use должны были начинаться с super, self или crate. Теперь, благодаря поддержке компилятором единообразных путей, этот код будет работать и сделает то, что вы ожидаете: импорт вариантов определенного выше перечисления Color.


Этим изменением завершается наша ревизия системы модулей. Мы надеемся, что вы получите удовольствие от работы с упрощенной системой!


Улучшения макросов


В Rust 1.32.0 выпущено несколько улучшений макросов. Во-первых, был добавлен новый спецификатор фрагмента literal:


macro_rules! m {
    ($lt:literal) => {};
}

fn main() {
    m!("some string literal");
}

Фрагмент literal сопоставляется литералам любого типа: строковым, числовым и символьным.


В редакции 2018 в макросе macro_rules можно использовать также и ?:


macro_rules! bar {
    ($(a)?) => {}
}

Фрагменту с ? будет сопоставлено ноль или одно вхождение, подобно тому, как фрагменту с * уже сопоставляется "ноль или более" вхождений, а с + — "одно или более" вхождений.


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


Макрос dbg!, о котором мы уже рассказали выше, стал важным добавлением к стандартной библиотеке. Помимо этого, 19 функций были сделаны константными и все числовые примитивные типы получили функции преобразования в байтовый массив и обратно с указанным порядком байтов. Всего шесть функций с именами to_<endian>_bytes и from_<endian>_bytes, где <endian> это:


  • ne — нативный порядок (native endianness)
  • le — порядок от младшего к старшему (little endian)
  • be — порядок от старшего к младшему (big endian)

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


Улучшения в Cargo


Cargo получил псевдоним cargo c для команды cargo check, и теперь разрешает использовать имена пользователей в URL репозиториев.


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


Разработчики 1.32.0


Множество людей совместно создавало Rust 1.32.0. Мы не смогли бы завершить работу без участия каждого из вас. Спасибо!


От переводчика: выражаю отдельную благодарность участникам сообщества Rustycrate и лично @dashadee и ozkriff за помощь с переводом и вычиткой.

Tags:
Hubs:
+59
Comments 21
Comments Comments 21

Articles