Alvaros
.
- Регистрация
- 14.05.16
- Сообщения
- 21.452
- Реакции
- 101
- Репутация
- 204
Команда Rust рада сообщить о выпуске новой версии, 1.45.0. Rust — это язык программирования, позволяющий каждому создавать надёжное и эффективное программное обеспечение.
Если вы установили предыдущую версию Rust средствами rustup, то для обновления до версии 1.45.0 вам достаточно выполнить следующую команду:
rustup update stable
Если у вас ещё не установлен rustup, вы можете
Что вошло в стабильную версию 1.45.0
Данный выпуск содержит два больших изменения: исправление давних дефектов при преобразовании между целыми числами и числами с плавающей точкой и стабилизация фич, необходимых для того, чтобы как минимум один веб-фреймворк смог работать на стабильном Rust.
Исправление дефектов в преобразованиях
Изначально
pub fn cast(x: f32) -> u8 {
x as u8
}
компилятор Rust в версиях 1.44.0 и раньше генерировал следующее LLVM-IR:
define i8 @_ZN10playground4cast17h1bdf307357423fcfE(float %x) unnamed_addr #0 {
start:
%0 = fptoui float %x to i8
ret i8 %0
}
fptoui реализует преобразование и является сокращением от "floating point to unsigned integer".
Но здесь есть проблема,
Следующая часть, если только вы регулярно не копаетесь в недрах компиляторов, может быть не совсем понятна. Она полна жаргона, но есть более простое объяснение: если вы приводите большое число с плавающей запятой к маленькому целому числу, вы получаете неопределённое поведение.
Это означает что, например, поведение следующего кода не определено:
fn cast(x: f32) -> u8 {
x as u8
}
fn main() {
let f = 300.0;
let x = cast(f);
println!("x: {}", x);
}
На моём компьютере с Rust 1.44.0 этот код печатает "x: 0", но т.к. его поведение не определено, напечатать он может всё что угодно. Это мы называем ошибкой «корректности» (ведь unsafe кода тут нет) — то есть ошибка, когда компилятор делает неправильные вещи. Мы отмечаем их в нашем трекере как
Однако эта ошибка заняла много времени для исправления. Причина в том, что было очень неясно, каким должен быть правильный путь.
В итоге было принято решение сделать так:
Это очень похоже на доступ к массиву, например:
Итак, что такое насыщающее приведение? Давайте посмотрим на слегка изменённый пример:
fn cast(x: f32) -> u8 {
x as u8
}
fn main() {
let too_big = 300.0;
let too_small = -100.0;
let nan = f32::NAN;
println!("too_big_casted = {}", cast(too_big));
println!("too_small_casted = {}", cast(too_small));
println!("not_a_number_casted = {}", cast(nan));
}
Выведет:
too_big_casted = 255
too_small_casted = 0
not_a_number_casted = 0
То есть слишком большие числа превращаются в максимально возможное значение. Слишком малые числа дают наименьшее возможное значение (равное нулю). NaN выдаёт ноль.
А это новый API для небезопасного приведения:
let x: f32 = 1.0;
let y: u8 = unsafe { x.to_int_unchecked() };
Но, как всегда, использовать этот метод рекомендуется лишь в крайних случаях. Как и при доступе к массиву, компилятор часто может соптимизировать проверки, делая эквивалентными безопасные и небезопасные версии, где это возможно доказать.
Стабилизация функциональных процедурных макросов в выражениях, шаблонах и стейтментах
В
Это выглядит так:
gobject_gen! {
class MyClass: GObject {
foo: Cell,
bar: RefCell,
}
impl MyClass {
virtual fn my_virtual_method(&self, x: i32) {
... do something with x ...
}
}
}
В "позиции элемента" — это некий жаргон, но в основном это означает, что вы можете вызывать только gobject_gen! в определённых местах в вашего кода.
Rust 1.45.0 добавляет возможность вызывать процедурные макросы в трёх новых местах:
// представим, что мы имеем процедурный макрос "mac"
mac!(); // позиция элемента, то, что было стабилизировано ранее
// но здесь представлены 3 новых:
fn main() {
let expr = mac!(); // в выражении
match expr {
mac!() => {} // в шаблоне
}
mac!(); // в стейтменте
}
Возможность использовать макросы в большем количестве мест интересна, но есть ещё одна причина, по которой многие разработчики давно ждали эту функцию:
#[macro_use] extern crate rocket;
#[get("//")]
fn hello(name: String, age: u8) -> String {
format!("Hello, {} year old named {}!", age, name)
}
#[launch]
fn rocket() -> rocket::Rocket {
rocket::ignite().mount("/hello", routes![hello])
}
До этого дня Rocket зависела от функциональности из ночной версии компилятора для предоставления своей гибкости и эргономики. По факту, как можно видеть на
Следующая версия Rocket всё ещё находится в разработке, но когда она выйдет, многие будут очень довольны
Изменения в стандартной библиотеке
В Rust 1.45.0 были стабилизированы следующие функции:
Также теперь можно
for ch in 'a'..='z' {
print!("{}", ch);
}
println!();
// Выведет "abcdefghijklmnopqrstuvwxyz"
Полный список изменений вы можете увидеть в
Другие изменения
Участники 1.45.0
Множество людей собрались вместе, чтобы создать Rust 1.45.0. Мы не смогли бы сделать это без всех вас,
От переводчиков
С любыми вопросами по языку Rust вам смогут помочь в
Данную статью совместными усилиями перевели
Если вы установили предыдущую версию Rust средствами rustup, то для обновления до версии 1.45.0 вам достаточно выполнить следующую команду:
rustup update stable
Если у вас ещё не установлен rustup, вы можете
You must be registered for see links
с соответствующей страницы нашего веб-сайта, а также посмотреть
You must be registered for see links
.Что вошло в стабильную версию 1.45.0
Данный выпуск содержит два больших изменения: исправление давних дефектов при преобразовании между целыми числами и числами с плавающей точкой и стабилизация фич, необходимых для того, чтобы как минимум один веб-фреймворк смог работать на стабильном Rust.
Исправление дефектов в преобразованиях
Изначально
You must be registered for see links
была открыта в октябре 2013 года, за полтора года до выпуска Rust 1.0. Так как rustc использует
You must be registered for see links
в качестве backend-компилятора, когда вы пишете подобный код:pub fn cast(x: f32) -> u8 {
x as u8
}
компилятор Rust в версиях 1.44.0 и раньше генерировал следующее LLVM-IR:
define i8 @_ZN10playground4cast17h1bdf307357423fcfE(float %x) unnamed_addr #0 {
start:
%0 = fptoui float %x to i8
ret i8 %0
}
fptoui реализует преобразование и является сокращением от "floating point to unsigned integer".
Но здесь есть проблема,
You must be registered for see links
:Инструкция ‘fptoui’ преобразовывает операнд с плавающей точкой в ближайшее (округляя до нуля) беззнаковое целое значение. Если значение не помещается в ty2, то результирующее значение будет испорченным.
Оригинал
The ‘fptoui’ instruction converts its floating-point operand into the nearest (rounding towards zero) unsigned integer value. If the value cannot fit in ty2, the result is a poison value.
Оригинал
The ‘fptoui’ instruction converts its floating-point operand into the nearest (rounding towards zero) unsigned integer value. If the value cannot fit in ty2, the result is a poison value.
Следующая часть, если только вы регулярно не копаетесь в недрах компиляторов, может быть не совсем понятна. Она полна жаргона, но есть более простое объяснение: если вы приводите большое число с плавающей запятой к маленькому целому числу, вы получаете неопределённое поведение.
Это означает что, например, поведение следующего кода не определено:
fn cast(x: f32) -> u8 {
x as u8
}
fn main() {
let f = 300.0;
let x = cast(f);
println!("x: {}", x);
}
На моём компьютере с Rust 1.44.0 этот код печатает "x: 0", но т.к. его поведение не определено, напечатать он может всё что угодно. Это мы называем ошибкой «корректности» (ведь unsafe кода тут нет) — то есть ошибка, когда компилятор делает неправильные вещи. Мы отмечаем их в нашем трекере как
You must be registered for see links
, и относимся к ним очень серьёзно.Однако эта ошибка заняла много времени для исправления. Причина в том, что было очень неясно, каким должен быть правильный путь.
В итоге было принято решение сделать так:
- as будет выполнять "насыщающее приведение" (saturating cast),
- будет добавлено новое unsafe приведение, если вы хотите пропустить проверки.
Это очень похоже на доступ к массиву, например:
- array проверит, чтобы убедиться, что array содержит по крайней мере i + 1 элемент,
[*]можно использовать unsafe { array.get_unchecked(i) }, чтобы пропустить проверку.
Итак, что такое насыщающее приведение? Давайте посмотрим на слегка изменённый пример:
fn cast(x: f32) -> u8 {
x as u8
}
fn main() {
let too_big = 300.0;
let too_small = -100.0;
let nan = f32::NAN;
println!("too_big_casted = {}", cast(too_big));
println!("too_small_casted = {}", cast(too_small));
println!("not_a_number_casted = {}", cast(nan));
}
Выведет:
too_big_casted = 255
too_small_casted = 0
not_a_number_casted = 0
То есть слишком большие числа превращаются в максимально возможное значение. Слишком малые числа дают наименьшее возможное значение (равное нулю). NaN выдаёт ноль.
А это новый API для небезопасного приведения:
let x: f32 = 1.0;
let y: u8 = unsafe { x.to_int_unchecked() };
Но, как всегда, использовать этот метод рекомендуется лишь в крайних случаях. Как и при доступе к массиву, компилятор часто может соптимизировать проверки, делая эквивалентными безопасные и небезопасные версии, где это возможно доказать.
Стабилизация функциональных процедурных макросов в выражениях, шаблонах и стейтментах
В
You must be registered for see links
мы стабилизировали «функциональные процедурные макросы в позиции элемента». Например,
You must be registered for see links
:Gnome-класс — это процедурный макрос для Rust. Внутри макроса мы определяем Rust-о подобный мини-язык, имеющий расширения, позволяющие вам определять подклассы GObject, их свойства, сигналы, реализации интерфейса и остальные функции GObject. Цель состоит в том, чтобы не требовать небезопасного кода с вашей стороны.
Это выглядит так:
gobject_gen! {
class MyClass: GObject {
foo: Cell,
bar: RefCell,
}
impl MyClass {
virtual fn my_virtual_method(&self, x: i32) {
... do something with x ...
}
}
}
В "позиции элемента" — это некий жаргон, но в основном это означает, что вы можете вызывать только gobject_gen! в определённых местах в вашего кода.
Rust 1.45.0 добавляет возможность вызывать процедурные макросы в трёх новых местах:
// представим, что мы имеем процедурный макрос "mac"
mac!(); // позиция элемента, то, что было стабилизировано ранее
// но здесь представлены 3 новых:
fn main() {
let expr = mac!(); // в выражении
match expr {
mac!() => {} // в шаблоне
}
mac!(); // в стейтменте
}
Возможность использовать макросы в большем количестве мест интересна, но есть ещё одна причина, по которой многие разработчики давно ждали эту функцию:
You must be registered for see links
. Популярный веб-фреймворк Rocket, первоначально выпущенный в декабре 2016 года, часто называют одной из лучших вещей, которую может предложить экосистема Rust. Вот пример "Привет, мир" из его предстоящего релиза:#[macro_use] extern crate rocket;
#[get("//")]
fn hello(name: String, age: u8) -> String {
format!("Hello, {} year old named {}!", age, name)
}
#[launch]
fn rocket() -> rocket::Rocket {
rocket::ignite().mount("/hello", routes![hello])
}
До этого дня Rocket зависела от функциональности из ночной версии компилятора для предоставления своей гибкости и эргономики. По факту, как можно видеть на
You must be registered for see links
, тот же пример что выше в текущей версии Rocket требует наличия свойства proc_macro_hygiene для компиляции. Тем не менее, как вы можете догадаться из названия свойства, сегодня оно попадёт стабильный выпуск!
You must be registered for see links
для отслеживания истории ночных функций в Rocket. Теперь они все проверены и готовы к использованию!Следующая версия Rocket всё ещё находится в разработке, но когда она выйдет, многие будут очень довольны
Изменения в стандартной библиотеке
В Rust 1.45.0 были стабилизированы следующие функции:
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links,
-
You must be registered for see links.
Также теперь можно
You must be registered for see links
для итерации по символам:for ch in 'a'..='z' {
print!("{}", ch);
}
println!();
// Выведет "abcdefghijklmnopqrstuvwxyz"
Полный список изменений вы можете увидеть в
You must be registered for see links
.Другие изменения
You must be registered for see links
,
You must be registered for see links
и
You must be registered for see links
также претерпели некоторые изменения.Участники 1.45.0
Множество людей собрались вместе, чтобы создать Rust 1.45.0. Мы не смогли бы сделать это без всех вас,
You must be registered for see links
!От переводчиков
С любыми вопросами по языку Rust вам смогут помочь в
You must be registered for see links
или же в аналогичном
You must be registered for see links
. Если у вас есть вопросы по переводам или хотите помогать с ними, то обращайтесь в
You must be registered for see links
.Данную статью совместными усилиями перевели
You must be registered for see links
,
You must be registered for see links
,
You must be registered for see links
и
You must be registered for see links
.



