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


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


rustup update stable

Если у вас ещё не установлен rustup, вы можете установить его с соответствующей страницы нашего веб-сайта.


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


Изюминка данного выпуска — конвейерная компиляция.


Конвейерная компиляция


Компилятору нужны не полностью собранные зависимости для сборки пакета, а лишь их "метаданные" (список типов, зависимостей, экспортов и т.д.), генерируемые на ранней стадии компиляции. Начиная с Rust 1.38.0, Cargo будет сразу же начинать сборку зависимых пакетов, как только их метаданные будут доступны.


Время сборки одного пакета не уменьшилось, но наши тесты показали, что скорость компиляции возрастает на 10%-20% в случае оптимизированных сборок (где некоторые зависимости уже скомпилированы). Для других же пакетов сильного прироста скорости компиляции не произошло. Время, необходимое для сборки пакета, зависит от компьютера, поэтому показатели могут отличаться. Конвейерная компиляция включена автоматически с версии 1.38.0.


Проверка некоторых неправильных использований mem::{uninitialized, zeroed}


Как ранее анонсировалось, std::mem::uninitialized не рекомендуется к применению. Вместо неё должен использоваться MaybeUninit<T>.


Функция mem::uninitialized ещё не обозначена устаревшей, но это будет сделано в следующих выпусках. Но несмотря на это, начиная с 1.38.0, rustc совершает проверку для узкого класса неправильных инициализаций с использованием mem::uninitialized или mem::zeroed.


Для некоторых типов, таких как &T и Box<T>, нулевое значение считается неопределённым поведением, так как они представляют собой подобные указателю объекты, которые не должны быть null. Будет ошибкой использовать mem::uninitialized или mem::zeroed для инициализации этих типов, поэтому компилятор будет пытаться предупредить вас, если какая-либо из этих функций используется для инициализации указанных выше объектов, и не важно, будут ли они инициализированы напрямую или в качестве поля большой структуры. Данная проверка рекурсивная, так что следующий код влечёт за собой предупреждение:


struct Wrap<T>(T);
struct Outer(Wrap<Wrap<Wrap<Box<i32>>>>);
struct CannotBeZero {
    outer: Outer,
    foo: i32,
    bar: f32
}

...

let bad_value: CannotBeZero = unsafe { std::mem::uninitialized() };

Внимательные читатели могут заметить, что стандартная библиотека содержит больше типов, которые не должны быть заполнены нулями, особенно NonNull<T> и NonZero<T>. Пока что инициализация этих структур посредством mem::uninitialized или mem::zeroed не проверяется.


Данные проверки не покрывают все случаи ненадлежащего использования mem::uninitialized или mem::zeroed, но позволяют обнаружить гарантированно неверный код, который должен перейти на использование MaybeUninit.


#[deprecated] для макросов


Атрибут #[deprecated], впервые представленный в Rust 1.9.0, позволяет авторам пакетов уведомлять пользователей об устаревающей функциональности, которую планируется удалить в последующих выпусках. Rust 1.38.0 позволяет применять данный атрибут и для макросов.


std::any::type_name


Строковое представление используемого типа может понадобиться при отладке кода. Например, в теле обобщённой функции вы можете захотеть напечатать тип переданного аргумента. Теперь это осуществимо посредством std::any::type_name:


fn gen_value<T: Default>() -> T {
    println!("Initializing an instance of {}", std::any::type_name::<T>());
    Default::default()
}

fn main() {
    let _: i32 = gen_value();
    let _: String = gen_value();
}

Результат:


Initializing an instance of i32
Initializing an instance of alloc::string::String

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


Изменения в стандартной библиотеке



Кроме того, некоторые функции были стабилизированы:



Другие изменения


Синтаксис, пакетный менеджер Cargo и анализатор Clippy также претерпели некоторые изменения.


Участники 1.38.0


Множество людей собрались вместе, чтобы создать Rust 1.38.0. Мы не смогли бы сделать это без всех вас, спасибо!


От переводчиков


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


Данную статью совместными усилиями перевели andreevlex, nlinker, funkill и Gymmasssorla.

Комментарии (3)


  1. MooNDeaR
    27.09.2019 14:42

    Можно поподробнее, что такое "конвейерная компиляция"?


    1. ozkriff
      27.09.2019 14:46

      Компилятору нужны не полностью собранные зависимости для сборки пакета, а лишь их "метаданные" (список типов, зависимостей, экспортов и т.д.), генерируемые на ранней стадии компиляции. Начиная с Rust 1.38.0, Cargo будет сразу же начинать сборку зависимых пакетов, как только их метаданные будут доступны.

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


      With ASCII diagrams, let’s say we have a binary which depends on libB which in turn depends on libA. A compilation today might look like this:
               meta                meta
      [-libA----|--------][-libB----|--------][-binary-----------]
      0s        5s       10s       15s       20s                30s


      With pipelined compilation, however, we can transform this to:
      [-libA----|--------]
                [-libB----|--------]
                                   [-binary-----------]
      0s        5s       10s       15s                25s

      (из IRLO темы)


      1. MooNDeaR
        27.09.2019 14:56

        Ок, теперь понял. Спасибо)