LINUX.ORG.RU

Выпуск языка программирования Rust 1.47

 ,


2

8

Опубликован релиз 1.47 языка системного программирования Rust, основанного проектом Mozilla. Язык сфокусирован на безопасной работе с памятью, обеспечивает автоматическое управление памятью и предоставляет средства для достижения высокого параллелизма выполнения заданий, при этом обходясь без использования сборщика мусора и runtime (runtime сводится к базовой инициализации и сопровождению стандартной библиотеки).

Автоматическое управление памятью в Rust избавляет разработчика от ошибок при манипулировании указателями и защищает от проблем, возникающих из-за низкоуровневой работы с памятью, таких как обращение к области памяти после её освобождения, разыменование нулевых указателей, выход за границы буфера и т.п. Для распространения библиотек, обеспечения сборки и управления зависимостями проектом развивается пакетный менеджер Cargo. Для размещения библиотек поддерживается репозиторий crates.io.

Основные новшества:

  • Реализована поддержка типажей для массивов произвольного размера. Ранее, из-за невозможности определить generic-функции для всех целых значений, стандартная библиотека предоставляла встроенную поддержку типажей только для массивов, размер которых не превышал 32 элемента (типажи для каждого размера были определены статически). Благодаря созданию функциональности константных дженериков («const generics») появилась возможность определения generic-функций для любых размеров массива, но они пока не включены в состав стабильных возможностей языка, хотя реализованы в компиляторе и теперь задействованы в стандартной библиотеке для типажей массивов любого размера. Например, следующая конструкция в Rust 1.47 приведёт к выводу содержимого массива, хотя раньше привела бы к ошибке:
    fn main() {
        let xs = [0; 34];
        println!("{:?}", xs);
    }
  • Обеспечен вывод более коротких трассировок (backtrace), выводимых при внештатных ситуациях. Из трассировки исключены элементы, не представляющие интереса в большинстве ситуаций, но захламляющие вывод и отвлекающие внимание от первичных причин проблемы. Для возвращения полной трассировки можно использовать переменную окружения «RUST_BACKTRACE=full». Например, для кода
    fn main() {
        panic!();
    }

раньше выводилась трассировка в 23 этапа, а теперь она будет сведена к 3 этапам, позволяющим сразу уловить суть:

thread 'main' panicked at 'explicit panic', src/main.rs:2:5
    stack backtrace:
       0: std::panicking::begin_panic
                 at /rustc/d...d75a/library/std/src/panicking.rs:497
       1: playground::main
                 at ./src/main.rs:2
       2: core::ops::function::FnOnce::call_once
                 at /rustc/d...d75a/library/core/src/ops/function.rs:227
  • Компилятор rustc обновлён до сборки с использованием LLVM 11 (Rust использует LLVM в качестве бэкенда для генерации кода). При этом сохранена возможность сборки со старыми LLVM, вплоть до версии 8, но по умолчанию (в rust-lang/llvm-project) теперь используется LLVM 11. Релиз LLVM 11 ожидается в ближайшие дни.
  • На платформе Windows в компиляторе rustc обеспечена поддержка включения проверок целостности потока выполнения (Control Flow Guard), активируемых при помощи флага «-C control-flow-guard». На других платформах данный флаг пока игнорируется.
  • В разряд стабильных переведена новая порция API, в том числе стабилизированы Ident::new_raw, Range::is_empty, RangeInclusive::is_empty, Result::as_deref, Result::as_deref_mut, Vec::leak, pointer::offset_from, f32::TAU и f64::TAU.
  • Признак «const», определяющий возможность использования в любом контексте вместо констант, применён в методах:
    • new для всех целых, отличных от нуля;
    • checked_add, checked_sub, checked_mul,checked_neg, checked_shl, checked_shr, saturating_add, saturating_sub и saturating_mul для всех целых;
    • is_ascii_alphabetic, is_ascii_uppercase, is_ascii_lowercase, is_ascii_alphanumeric, is_ascii_digit, is_ascii_hexdigit, is_ascii_punctuation, is_ascii_graphic, is_ascii_whitespace и is_ascii_control для типов char и u8.
  • Для FreeBSD задействован инструментарий из FreeBSD 11.4 (FreeBSD 10 не поддерживает LLVM 11).

Взято с opennet.ru

>>> Подробности

★★

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

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

А что constexpr ? Как он помогает бороться с порчей памяти? Я всегда думал, что оно для оптимизации производительности.

constexpr - это для надёжности всегда было.

Вот как пример ошибка компиляции вместо разыменования nullptr:

error: dereferencing a null pointer

https://gcc.godbolt.org/z/369rn3

constexpr находит много всего. Он также и leak находит:

allocated storage has not been deallocated

https://gcc.godbolt.org/z/1fqcax

и use-after-free

error: modification of 'heap deleted' is not a constant expression

https://gcc.godbolt.org/z/EhzsM5

и выход за пределы массива:

array subscript value '3' is outside the bounds of array 'arr' of type 'int [3]'

https://gcc.godbolt.org/z/G9Y7YT

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

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

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

все таки мне кажется что в этой картинке любой яп можно подставить, хоть Питон.

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

Или простимулирует писать тесты.

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

Например, выход за пределы массива С++:

std::array<int, 1> arr;
arr.at(2);

Результат: exception, точно такой же как в Джава или ещё где. Так почему, для джавы наличие такой проблемы - это ок, никак не мешает, а для С++ - о боже мой, выход за пределы массива, мы все умрём?

Или вот освобождение памяти. В С++ память обычно управляется RAII. Если ситуация сложная и RAII не подходит, то в других языках в той же ситуации приходится использовать финализаторы.

Но управление памятью вручную через финализаторы - это норма и хорошо, а через delete - это почему-то плохо. Хотя грабли в реальной жизни будут примерно одними и теми же.

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

«Я не могу в ОС, компиляторы, ассемблер, рантайм, но я за все хорошее против всего плохого» - современные программисты такие программисты.

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

Все перечисленные инструменты есть и для других языков. В rust ещё miri есть.

Да, есть, и это хорошо.

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

Результат: exception, точно такой же как в Джава или ещё где.

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

Ну и вообще, at() не бесплатный. А в C++ не любят лишних затрат.

Но управление памятью вручную через финализаторы - это норма и хорошо, а через delete - это почему-то плохо.

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

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

man memory safety

В джаве вы не испортите память, как ни старайтесь.

В С++ память обычно управляется RAII.

Сколько правил использования RAII и умных указателей вы знаете? С десяток, два десятка? Уверены что никогда не ошибётесь? Уверены что ваш коллега не напишет ерунду?

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

А разве не для запуска кода на этапе компиляции?

http://eel.is/c++draft/expr.const

An expression E is a core constant expression unless the evaluation of E, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following: 

* .. (какое-то условие чего нельзя в constexpr)
* an operation that would have undefined behavior
* .. (какое-то другое условие чего нельзя в constexpr)

то есть компилятор должен защищать нас от UB в constexpr.

Для меня именно это является самой важной фичей constexpr

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

Это замечательно, только в constexpr доступна от силы половина фич C++.

Ну а если почитать https://en.cppreference.com/w/cpp/language/constexpr , то первой же строкой увидим то, что я написал:

The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time.

То что в C++ есть миллион и одни способ соорудить костыль из говна и палок и я так знаю.

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

Это замечательно, только в constexpr доступна от силы половина фич C++.

Да, доступно не всё. Но даже из того что доступно можно сделать многое.

Jason Turner на одном из докладов показывал простой эмулятор ARM процессора полностью constexpr.

Но да, нужно писать constexpr-friendly код, а не обычный С++ код…

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

В том, то и дело, в вышеприведённом коде память тоже не испортить, как ни стараться, memory safety по отношению к выходу за границы коллекции вполне выполняется.

Сколько правил использования RAII и умных указателей вы знаете? С десяток, два десятка? Уверены что никогда не ошибётесь? Уверены что ваш коллега не напишет ерунду?

Сколько правил дорожного движения вы знаете? С десяток, два десятка? Уверены что никогда не ошибётесь? Уверены, что движущийся по соседней полосе не сделает ерунду?

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

в вышеприведённом коде память тоже не испортить

В данном куске кода - нет. В языке - да.

Хотя… если этот код модифицируется из разных потоков…

Уверены, что движущийся по соседней полосе не сделает ерунду?

Я в метро ежу (ездил).

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

Перечитал твои комменты. Своим упоминанием PyPy ты как-бы показываешь некое непонимание как это все работает. А у меня зуб на подобные признаки современных программист - не знать и не видеть ничего дальше своих религиозных возрений.

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

В языке - да.

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

но к С++-то тогда какие претензии? любой другой язык тоже в аналогичной ситуации, рухнет, при вызове чужеродного кода на С или асме, который голыми указателями оперирует и за границы массива выходит

Хотя… если этот код модифицируется из разных потоков…

Если код (точнее данные) из разных потоков модифицируется, в джаве тоже «ой» будет, если что.

Я в метро ежу (ездил).

И что? Я тоже. Только вот до метро телепортироваться пока не научился, правила дорожного движения, как пешеходу, мне приходится соблюдать. И ещё когда на такси/автобусе езжу: с той лишь разницей, что ответственность при этом перекладывается на таксиста/водителя автобуса. Так что, повторяю вопросы.

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

Ну и вообще, at() не бесплатный. А в C++ не любят лишних затрат.

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

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

constexpr - это для надёжности всегда было.

этот тезис в каких-то комитетских пропозалах лейтмотивом идет? Потому что справочник С++ что-то не упоминает о таком назначении констекспр:

The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time.

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

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

  • ты не знаешь это в компайл тайм???
  • да
  • ты дурак или задача твоя говно! Все надо знать в компайл-тайм, и тогда волосы будут мягкими и шелковистыми
seiken ★★★★★
()
Ответ на: комментарий от seiken

Откуда у вчерашнего студента при наличии базового уровня C++ возьмётся основной опыт на rust? Тем более, что более матёрого программиста на rust ему всё равно придётся найти, чтобы присматривать за студентами.

Это безотносительно выбора языка.

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

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

Даже на небезопасном ЯП можно разрабатывать системы ответственного применения, если недостатки этого ЯП компенсируются: формализацией предметной области и созданием кастомных инструментов поверх доступных библиотек и систем; разумным применением лучших практик, и просто добросовестным, ответственным подходом к делу, а не так, чтобы «проверять API/ABI на совместимость?! а пофиг! авось и так ракета полетит; за нас тут манагер (ну или там, полковник) решил, так что будем кровь из носа план выполнять.»

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

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

От тестирования всё равно никуда не уйти. От логических ошибок в реализации встроенные инструменты не защитят. Иначе бы в баг-треккерах проектов были только [feature request] без «эта штука делается явно не то, что должна на самом деле».

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

От логических ошибок в реализации встроенные инструменты не защитят.

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

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

Что по существу можно ответить на твой высосанный из ничего бред? Ты нафантзировал что-то, а я почему-то должен на это отвечать. Ладно бы ты ещё конкретные претензии предъявил, приправленные цитатами, но ведь нет.

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

Я скидывал ссылку на стандарт: Выпуск языка программирования Rust 1.47 (комментарий)

И разработчики компиляторов знают об этом. У меня есть несколько открытых багов в багзилле gcc и MSVC о том что их компиляторы пропускают UB в constexpr и о том, что constexpr должен быть свободен от UB.

Но если использовать все 3 компилятора, то насколько я знаю хотя бы один из 3 выдаст ошибку компиляции, если в коде есть UB…

Пример того как MSVC пропускает UB в constexpr: https://gcc.godbolt.org/z/a754sb

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

(какое-то условие чего нельзя в constexpr)

Там же не просто пара «каких-то условий», а нехилый список, включая ограничения на виртуальные функции. И самое главное, вызов не constexpr-функций превращает вызываемое выражение в тыкву… в не constexpr. Т.e. это мир, замкнутый сам на себе, не только без связи с мнешним миром по не-constexpr интерфейсам, но даже не позволяющий использовать STL классы типа vector в своем constexpr контексте.

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

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

виртуальные функции

виртуальные функции могут быть constexpr

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1064r0.html

https://gcc.godbolt.org/z/88Yh8d

https://gcc.godbolt.org/z/T63eTe

но даже не позволяющий использовать STL классы типа vector в своем constexpr контексте.

внимательно почитай табличку что есть в С++20, vector это constexpr класс..

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1004r2.pdf

Табличка: https://en.cppreference.com/w/cpp/compiler_support

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

В других языках будет подробный stack trace.

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

Ну и вообще, at() не бесплатный. А в C++ не любят лишних затрат.

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

Через финализаторы не памятью управляют, а другими ресурсами

бывает, что памятью тоже - так-то умные указатели в С++ разрулят доступ к памяти точно также, как и сборщик мусора в том же CPython - shared_ptr, например, работает идентично

но в сложных ситуациях, соглашусь, ни сборщик мусора, ни умные указатели не справятся

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

Более того, умные указатели С++ не только позволяют автоматически управлять памятью/другими ресурсами с той же лёгкостью, что и в gc, но ещё и автоматически избегать утечек памяти в некоторых ситуациях, где в языке с gc случится утечка памяти.

Пример. Дано: Есть объекты A, B, С. A указывает на С, Б на С. При удалении либо А, либо Б должен удаляться С.

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

В С++ не проблема написать умный указатель на такую ситуацию.

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

который будет полезен только во время отладки

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

Что касается времени компиляции, то как угадать насколько пользователь изменит вектор? Для константного массива есть теоретическая возможность, хотя на практике не проверял. Но я сталкивался с тем, что компилятор C# не даёт явно поделить на ноль, например.

Кстати, как на C++ перехватить деление на ноль и переполнение целых?

но никто не жужжит по поводу лишних затрат

Да. Но там для обращения по индексу просто пишут в квадратных скобках, без всякого at(). В C++ приоритеты другие, поэтому по умолчанию опасный вариант.

как и сборщик мусора в том же CPython - shared_ptr, например, работает идентично

Возможно, я не очень разбираюсь в shared_ptr. Можете привести пример кода, в котором shared_ptr указывает на какой-нибудь элемент из vector?

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

Да. Но там для обращения по индексу просто пишут в квадратных скобках, без всякого at(). В C++ приоритеты другие

о боже мой, ну сделайте класс-наследник от array и пропишите что хотите

Кстати, как на C++ перехватить деление на ноль и переполнение целых?

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

Можете привести пример кода, в котором shared_ptr указывает на какой-нибудь элемент из vector

std::vector<shared_ptr<MyClass> > vec;
vec.push_back(shared_ptr<MyClass>(new MyClass()));

что вы хотите в примере увидеть, не очень ясно

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

ну сделайте класс-наследник от array и пропишите что хотите

Вы рекомендуете наследоваться от чужого класса? Не лучшая практика, но ок. Можно вообще стандартную библиотеку переписать. Но не лучше ли просто перейти на какой-нибудь D тогда? Какой смысл использовать C++, если мы собрались снизить скорость до уровня других языков с помощью своих велосипедов?

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

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

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

что вы хотите в примере увидеть, не очень ясно

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

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

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

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

emplace_back(std::make_shared<MyClass>())

Ага, я чуял что что-то такое должно быть.

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

самый «дубовый» вариант предложил, который даже в самом древнем стандарте будет работать + он более читабелен (КМК) человеку, незнакомому с плюсами

а так, да, emplace_back лучше

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

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

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

всегда есть неявное наследование от какого-нибудь общего класса Object

если мы собрались снизить скорость до уровня других языков с помощью своих велосипедов?

драматизируете

Какой смысл использовать C++

почему к java нет претензий в той же ситуации

Вместо деления использовать специальную функцию с контролем деления на ноль? А для знаковых и на минус единицу? В то время как в других языках просто значок деления будут использовать?

вот вы сами же и ответили, зачем использовать С++, а не java: в ней нет (вроде, до сих пор) перегрузки операторов

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

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

буду благодарен, если вы продемонстрируете, как без таковой обёртки (даже если она прошита в ЯП) можно обойтись в указанном случае

я хотел увидеть как будет выглядеть то же самое, что и в питоне

вот, увидели

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

вы вообще о чём? можете на примере объяснить

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

В C++ есть наибольшее количество инструментов для проверки кода…

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

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

Ведь вы будете писать на брейнфаке - под него ровно 0 инструментов для проверки. Максимум - на bash, по той же причине.

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

Fortran, C или ассемблер. Вот мой выбор. Язык, где «+» функция а не сумма - ложный, и хрен кто меня переубедит.

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