[Open source, Rust, Компиляторы, Программирование, Системное программирование] Rust 1.45.0: стабилизация функциональных процедурных макросов, исправление дефектов преобразования (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Команда Rust рада сообщить о выпуске новой версии, 1.45.0. Rust — это язык программирования, позволяющий каждому создавать надёжное и эффективное программное обеспечение.
Если вы установили предыдущую версию Rust средствами rustup, то для обновления до версии 1.45.0 вам достаточно выполнить следующую команду:
rustup update stable
Если у вас ещё не установлен rustup, вы можете установить его с соответствующей страницы нашего веб-сайта, а также посмотреть на GitHub.
Что вошло в стабильную версию 1.45.0
Данный выпуск содержит два больших изменения: исправление давних дефектов при преобразовании между целыми числами и числами с плавающей точкой и стабилизация фич, необходимых для того, чтобы как минимум один веб-фреймворк смог работать на стабильном Rust.
Исправление дефектов в преобразованиях
Изначально Issue 10184 была открыта в октябре 2013 года, за полтора года до выпуска Rust 1.0. Так как rustc использует LLVM в качестве 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".
Но здесь есть проблема, описанная в документации:
Инструкция ‘fptoui’ преобразовывает операнд с плавающей точкой в ближайшее (округляя до нуля) беззнаковое целое значение. Если значение не помещается в ty2, то результирующее значение будет испорченным.
Оригинал
SPL
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 кода тут нет) — то есть ошибка, когда компилятор делает неправильные вещи. Мы отмечаем их в нашем трекере как I-unsound, и относимся к ним очень серьёзно.
Однако эта ошибка заняла много времени для исправления. Причина в том, что было очень неясно, каким должен быть правильный путь.
В итоге было принято решение сделать так:
- 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() };
Но, как всегда, использовать этот метод рекомендуется лишь в крайних случаях. Как и при доступе к массиву, компилятор часто может соптимизировать проверки, делая эквивалентными безопасные и небезопасные версии, где это возможно доказать.
Стабилизация функциональных процедурных макросов в выражениях, шаблонах и стейтментах
В Rust 1.30.0 мы стабилизировали «функциональные процедурные макросы в позиции элемента». Например, крейт gnome-class:
Gnome-класс — это процедурный макрос для Rust. Внутри макроса мы определяем Rust-о подобный мини-язык, имеющий расширения, позволяющие вам определять подклассы GObject, их свойства, сигналы, реализации интерфейса и остальные функции GObject. Цель состоит в том, чтобы не требовать небезопасного кода с вашей стороны.
Это выглядит так:
gobject_gen! {
class MyClass: GObject {
foo: Cell<i32>,
bar: RefCell<String>,
}
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!(); // в стейтменте
}
Возможность использовать макросы в большем количестве мест интересна, но есть ещё одна причина, по которой многие разработчики давно ждали эту функцию: Rocket. Популярный веб-фреймворк Rocket, первоначально выпущенный в декабре 2016 года, часто называют одной из лучших вещей, которую может предложить экосистема Rust. Вот пример "Привет, мир" из его предстоящего релиза:
#[macro_use] extern crate rocket;
#[get("/<name>/<age>")]
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 требует наличия свойства proc_macro_hygiene для компиляции. Тем не менее, как вы можете догадаться из названия свойства, сегодня оно попадёт стабильный выпуск! Данная проблема для отслеживания истории ночных функций в Rocket. Теперь они все проверены и готовы к использованию!
Следующая версия Rocket всё ещё находится в разработке, но когда она выйдет, многие будут очень довольны :)
Изменения в стандартной библиотеке
В Rust 1.45.0 были стабилизированы следующие функции:
- Arc::as_ptr,
- BTreeMap::remove_entry,
- Rc::as_ptr,
- rc::Weak::as_ptr,
- rc::Weak::from_raw,
- rc::Weak::into_raw,
- sync::Weak::as_ptr,
- sync::Weak::from_raw,
- sync::Weak::into_raw,
- str::strip_prefix,
- str::strip_suffix,
- char::UNICODE_VERSION,
- Span::resolved_at,
- Span::located_at,
- Span::mixed_site,
- unix::process::CommandExt::arg0.
Также теперь можно использовать char с диапазонами для итерации по символам:
for ch in 'a'..='z' {
print!("{}", ch);
}
println!();
// Выведет "abcdefghijklmnopqrstuvwxyz"
Полный список изменений вы можете увидеть в детальных примечаниях к выпуску.
Другие изменения
Синтаксис, пакетный менеджер Cargo и анализатор Clippy также претерпели некоторые изменения.
Участники 1.45.0
Множество людей собрались вместе, чтобы создать Rust 1.45.0. Мы не смогли бы сделать это без всех вас, спасибо!
От переводчиков
С любыми вопросами по языку Rust вам смогут помочь в русскоязычном Телеграм-чате или же в аналогичном чате для новичковых вопросов. Если у вас есть вопросы по переводам или хотите помогать с ними, то обращайтесь в чат переводчиков.
Данную статью совместными усилиями перевели nlinker, funkill, Hirrolot и blandger.
===========
Источник:
habr.com
===========
===========
Автор оригинала: The Rust Core Team
===========Похожие новости:
- [C#, F#, Программирование] Асинхронность в C# и F#. Подводные камни асинхронности в C #
- [JavaScript, PHP, Ненормальное программирование, Программирование, Разработка веб-сайтов] Inertia.js – современный монолит
- [Open source, Python, Информационная безопасность, Сетевые технологии] Реализация ARP-спуфинга на Python
- [*nix, Open source, Анализ и проектирование систем, Программирование, Разработка систем связи] Цикл статей «Изучаем VoIP-движок Mediastreamer2» одним pdf-файлом
- [JavaScript, Open source, Программирование] Объектно-ориентированная альтернатива jquery
- [Программирование] Довольно непонятное решения в schema.org с LocalBusiness
- [Python, Программирование] Как я заработал 30$ на ставках на спорт
- [GitHub, Open source, Хранилища данных] GitHub разместил свой архив в арктическом хранилище Arctic World Archive
- [GitHub, Open source] GitHub создал архив ПО с открытым исходным кодом в арктическом хранилище
- [Kubernetes, Программирование] Как устроен процесс создания docker-контейнера (от docker run до runc) (перевод)
Теги для поиска: #_open_source, #_rust, #_kompiljatory (Компиляторы), #_programmirovanie (Программирование), #_sistemnoe_programmirovanie (Системное программирование), #_clippy, #_cargo, #_rustc, #_rustdoc, #_rustfmt, #_rustfix, #_release, #_stable, #_jazyki_programmirovanija (языки программирования), #_stabilnaja_versija (стабильная версия), #_vypusk_versij (выпуск версий), #_sistemnoe_programmirovanie (системное программирование), #_novosti_tehnologij (новости технологий), #_perevod (перевод), #_open_source, #_rust, #_kompiljatory (
Компиляторы
), #_programmirovanie (
Программирование
), #_sistemnoe_programmirovanie (
Системное программирование
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:14
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Команда Rust рада сообщить о выпуске новой версии, 1.45.0. Rust — это язык программирования, позволяющий каждому создавать надёжное и эффективное программное обеспечение. Если вы установили предыдущую версию Rust средствами rustup, то для обновления до версии 1.45.0 вам достаточно выполнить следующую команду: rustup update stable
Если у вас ещё не установлен rustup, вы можете установить его с соответствующей страницы нашего веб-сайта, а также посмотреть на GitHub. Что вошло в стабильную версию 1.45.0 Данный выпуск содержит два больших изменения: исправление давних дефектов при преобразовании между целыми числами и числами с плавающей точкой и стабилизация фич, необходимых для того, чтобы как минимум один веб-фреймворк смог работать на стабильном Rust. Исправление дефектов в преобразованиях Изначально Issue 10184 была открыта в октябре 2013 года, за полтора года до выпуска Rust 1.0. Так как rustc использует LLVM в качестве 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". Но здесь есть проблема, описанная в документации: Инструкция ‘fptoui’ преобразовывает операнд с плавающей точкой в ближайшее (округляя до нуля) беззнаковое целое значение. Если значение не помещается в ty2, то результирующее значение будет испорченным.
ОригиналSPLThe ‘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 кода тут нет) — то есть ошибка, когда компилятор делает неправильные вещи. Мы отмечаем их в нашем трекере как I-unsound, и относимся к ним очень серьёзно. Однако эта ошибка заняла много времени для исправления. Причина в том, что было очень неясно, каким должен быть правильный путь. В итоге было принято решение сделать так:
Это очень похоже на доступ к массиву, например:
Итак, что такое насыщающее приведение? Давайте посмотрим на слегка изменённый пример: 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() }; Но, как всегда, использовать этот метод рекомендуется лишь в крайних случаях. Как и при доступе к массиву, компилятор часто может соптимизировать проверки, делая эквивалентными безопасные и небезопасные версии, где это возможно доказать. Стабилизация функциональных процедурных макросов в выражениях, шаблонах и стейтментах В Rust 1.30.0 мы стабилизировали «функциональные процедурные макросы в позиции элемента». Например, крейт gnome-class: Gnome-класс — это процедурный макрос для Rust. Внутри макроса мы определяем Rust-о подобный мини-язык, имеющий расширения, позволяющие вам определять подклассы GObject, их свойства, сигналы, реализации интерфейса и остальные функции GObject. Цель состоит в том, чтобы не требовать небезопасного кода с вашей стороны.
gobject_gen! {
class MyClass: GObject { foo: Cell<i32>, bar: RefCell<String>, } 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!(); // в стейтменте } Возможность использовать макросы в большем количестве мест интересна, но есть ещё одна причина, по которой многие разработчики давно ждали эту функцию: Rocket. Популярный веб-фреймворк Rocket, первоначально выпущенный в декабре 2016 года, часто называют одной из лучших вещей, которую может предложить экосистема Rust. Вот пример "Привет, мир" из его предстоящего релиза: #[macro_use] extern crate rocket;
#[get("/<name>/<age>")] 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 требует наличия свойства proc_macro_hygiene для компиляции. Тем не менее, как вы можете догадаться из названия свойства, сегодня оно попадёт стабильный выпуск! Данная проблема для отслеживания истории ночных функций в Rocket. Теперь они все проверены и готовы к использованию! Следующая версия Rocket всё ещё находится в разработке, но когда она выйдет, многие будут очень довольны :) Изменения в стандартной библиотеке В Rust 1.45.0 были стабилизированы следующие функции:
Также теперь можно использовать char с диапазонами для итерации по символам: for ch in 'a'..='z' {
print!("{}", ch); } println!(); // Выведет "abcdefghijklmnopqrstuvwxyz" Полный список изменений вы можете увидеть в детальных примечаниях к выпуску. Другие изменения Синтаксис, пакетный менеджер Cargo и анализатор Clippy также претерпели некоторые изменения. Участники 1.45.0 Множество людей собрались вместе, чтобы создать Rust 1.45.0. Мы не смогли бы сделать это без всех вас, спасибо! От переводчиков С любыми вопросами по языку Rust вам смогут помочь в русскоязычном Телеграм-чате или же в аналогичном чате для новичковых вопросов. Если у вас есть вопросы по переводам или хотите помогать с ними, то обращайтесь в чат переводчиков. Данную статью совместными усилиями перевели nlinker, funkill, Hirrolot и blandger. =========== Источник: habr.com =========== =========== Автор оригинала: The Rust Core Team ===========Похожие новости:
Компиляторы ), #_programmirovanie ( Программирование ), #_sistemnoe_programmirovanie ( Системное программирование ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:14
Часовой пояс: UTC + 5