Я и искал try_compile. А сейчас вы скинули совсем другие макросы. И вы в скриншоте вырезали строку "Please do not use this.", что как-бы намекает..
Есть куча документации прямо говорящей, что процедурные макросы компилируются в отдельные библиотеки, запускаются в отдельных процессах, в коде компилятора сами разбирайтесь зачем им сервера и клиенты макросов
Видимо вы не различаете декларативные и процедурные макросы. Последние по определению работают в отдельном процессе. Но вы писали про try_compile, который декларативный.
📦 postcompile: A macro for compiling Rust code at runtime. Useful for snapshot testing.
Вообще первый раз вижу, чтобы макрос делал fork, и нельзя ли было без него обойтись. В остальных 99% макросов никаких форков нет, и все в одном процессе.
А вы заявляете как будто любой макрос в Rust запускает что-то в отдельных процессах, что очевидная ложь. Вобщем продолжайте набрасывать дальше..
Аргументация в самой статье, о чем я и написал. Но в комментариях до моего первого поста суть статьи почти не обсуждали.
Менять же можно разными способами: добавляя новые ключи компиляции, внести в один из профилей безопасности и т.д. А старый функционал постепенно объявлять deprecated.
А теперь посмотрите, на мой первый пост. Минусующие (и вы тоже) даже не поняли, что я знаю как работает std::move по стандарту, и критикую именно стандарт. А заминусовали за то, что я как-бы не знаю стандарт.
Вместо того, чтобы паясничать, могли бы просто признать что были не правы про пропаганду. А вы не правы, как ни считай: ни по кол-ву крейтов, ни по кол-ву строк кода.
Ваше образование почему-то не позволило вам прочитать внимательно текст по вашей же ссылке:
Например, чтобы узнать методом Монте-Карло, какое в среднем будет расстояние между двумя случайными точками в круге, нужно взять координаты большого числа случайных пар точек в границах заданной окружности, для каждой пары вычислить расстояние, а потом для них посчитать среднее арифметическое.
4 штуки никак нельзя назвать большим числом. А вот 127,000 шт по моей ссылке уже большое число.
Кроме того, если в 4 крейтах будет 1/100000000000000000000000 строчек unsafe, по вашей статистике будет 100% случаев unsafe.
Встает вопрос, какие ещё допущения вам позволяет ваше математическое образование =)
P.S.
Вообще метод описан, если Вам мала выборка из 4х, берите большую. Будет выше точность.
С увеличением размера выборки до бесконечности (до фактического кол-ва крейтов) метод Монте-Карло превращается.. превращается в полноценную статистику, которую я уже приводил.
Интересно вы по выборке из 4 приложений отменили общую статистику по всем крейтам (127,000 шт). Большая разница (25% vs 81%) должна была вам тонко намекнуть, что 4 шт для статистики ничтожны.
Вот статистика по строчкам кода из 4 приложений еще куда ни шло, т.к. обеспечена статистически значимым числом: суммарно 109000 строк кода.
Итого 0,04% обоснованного (или 0,05% всего) unsafe кода - это я и называю "в прикладном коде unsafe практически не встречается". Делайте выводы математически правильно!
1) parity-db 20/24600 = 0.081% Внутри вызовы mmap и libс. Обоснованно. Еще 3 transmute, на первый взгляд можно и без них. 2) tabiew 11/7252 = 0,15% Всё в тестах, и абсолютно не нужно. Можно использовать static_cell или атомарные переменные. 3) xi-editor 30/29356 = 0.11% sse, avx, libc - какие-то оптимизации. Еще 2 не нужных str::from_utf8_unchecked.
4) poem 0/47700 = 0% Если выкинуть ненужные (на мой взгляд) unsafe, выйдет (17+28)/(24600+7252+29356+47700) = 0.04% В 2 из 4 проектах можно обойтись без unsafe точно.
P.S. mmap очевидно нужен, c libc, sse и avx я не разбирался, тут уже нужно много времени потратить.
As of May 2024, there are about 145,000 crates; of which, approximately 127,000 contain significant code. Of those 127,000 crates, 24,362 make use of the unsafe keyword, which is 19.11% of all crates. And 34.35% make a direct function call into another crate that uses the unsafe keyword. 6 Nearly 20% of all crates have at least one instance of the unsafe keyword, a non-trivial number.
Most of these Unsafe Rust uses are calls into existing third-party non-Rust language code or libraries, such as C or C++. In fact, the crate with the most uses of the unsafe keyword is the Windows crate 7, which allows Rust developers to call into various Windows APIs.
Примерно 81% крейтов не содержат ни одной строчки unsafe. А среди остальных большинство - это FFI.
Теперь ваша очередь доказывать про пропаганду. Надеюсь получить аргументированный ответ.
Посмотрел. Похоже, что его транслировали из C в Rust (например этим), и потом добились того чтобы компилировался.
Я делаю такой вывод из того, что внутри написана реализация memset, memchr и юникода (лол). Так что ваш пример - это антипример.
P.S. Вот пример +- большого проекта (https://github.com/picodata/picodata), изначально написанного на Rust. На 112kloc Rust кода 238 строк unsafe (0.2%). Из них около 80% это плагин к tarantool, т.к. обращения к ffi.
Но restrict по умолчанию только в safe Rust. А в unsafe мы оказываемся ближе к С (но не на его уровне), и можно писать код на указателях, главное при переходе снова к ссылкам соблюдать ограничение restrict.
На практике за этим надо следить разработчикам библиотек, которые что-то оптимизируют через unsafe и указатели, а в прикладном коде unsafe практически не встречается.
А вы точно прочитали статью? В конце раздела На сцене появляется C++11 ровно один указатель, и можно было бы заменить на std::string без изменения сути примера.
А суть в том, что на повторный std::move компилятор не выдает ошибку (и даже варнинг), и нужно много приседать, чтобы компилятор что-то заметил. Ито это не гарантируется.
"давайте рассыпем по коду сырых указателей да наворотим дикой дичи в стиле pure C".
Целью проекта Rust Coreutils является создание кроссплатформенной альтернативной реализации Coreutils, способной работать в том числе на платформах Windows, Redox и Fuchsia.
На сколько я понимаю, GNU Coreutils не кроссплатформенный.
Возможно вы не знаете, но стандартная библиотека Rust тоже покрыта десятками тысяч тестов.
Если я подлючу случаный крейт с unsafe-фрагментом кода, где гарантия, что он был написан столь же ответственно, и что его ежедневные фиксы не сломают мое приложение?
А если я подключу случайную библиотеку в Java, где гарантия, что она не вызовет внутри гонку данных? Или правильно вызовет С библиотеку, не приводя к UB.
Я думаю что требования для небезопасного кода одинаковые для всех языков: покрывать тестами, проверять санитайзерами, проводить фаззинг и т.д. Если библиотеки этого не делают, это не может быть претензией к самому языку.
Просто в Rust такие блоки кода намеренно выделены в блоки unsafe, чтобы быть заметнее. А в каком-нибудь Python вызов C-API легко затеряется среди тысяч строк кода.
Похоже вы отрицаете саму идею построения безопасного API поверх потенциально небезопасного кода.
Но если вы загляните в исходники стандартной библиотеки любого языка, то там будет и арифметика указателей, и ассемблерные вставки, и системные вызовы, что априори небезопасно. И тем не менее вызвать UB в C# например довольно трудно.
Вы написали
Я и искал try_compile. А сейчас вы скинули совсем другие макросы. И вы в скриншоте вырезали строку "Please do not use this.", что как-бы намекает..
Видимо вы не различаете декларативные и процедурные макросы. Последние по определению работают в отдельном процессе. Но вы писали про try_compile, который декларативный.
Этот макрос часть проекта https://github.com/scufflecloud/scuffle, нужен им для тестирования:
Вообще первый раз вижу, чтобы макрос делал fork, и нельзя ли было без него обойтись. В остальных 99% макросов никаких форков нет, и все в одном процессе.
А вы заявляете как будто любой макрос в Rust запускает что-то в отдельных процессах, что очевидная ложь. Вобщем продолжайте набрасывать дальше..
Аргументация в самой статье, о чем я и написал. Но в комментариях до моего первого поста суть статьи почти не обсуждали.
Менять же можно разными способами: добавляя новые ключи компиляции, внести в один из профилей безопасности и т.д. А старый функционал постепенно объявлять deprecated.
А теперь посмотрите, на мой первый пост. Минусующие (и вы тоже) даже не поняли, что я знаю как работает std::move по стандарту, и критикую именно стандарт. А заминусовали за то, что я как-бы не знаю стандарт.
Вместо того, чтобы паясничать, могли бы просто признать что были не правы про пропаганду. А вы не правы, как ни считай: ни по кол-ву крейтов, ни по кол-ву строк кода.
Итак?
Ваше образование почему-то не позволило вам прочитать внимательно текст по вашей же ссылке:
4 штуки никак нельзя назвать большим числом. А вот 127,000 шт по моей ссылке уже большое число.
Кроме того, если в 4 крейтах будет 1/100000000000000000000000 строчек unsafe, по вашей статистике будет 100% случаев unsafe.
Встает вопрос, какие ещё допущения вам позволяет ваше математическое образование =)
P.S.
С увеличением размера выборки до бесконечности (до фактического кол-ва крейтов) метод Монте-Карло превращается.. превращается в полноценную статистику, которую я уже приводил.
Интересно вы по выборке из 4 приложений отменили общую статистику по всем крейтам (127,000 шт). Большая разница (25% vs 81%) должна была вам тонко намекнуть, что 4 шт для статистики ничтожны.
Вот статистика по строчкам кода из 4 приложений еще куда ни шло, т.к. обеспечена статистически значимым числом: суммарно 109000 строк кода.
Итого 0,04% обоснованного (или 0,05% всего) unsafe кода - это я и называю "в прикладном коде unsafe практически не встречается". Делайте выводы математически правильно!
Господа минусующие, не могли бы вы аргументировать свою позицию?
Куда же вы пропали? Прошло уже 3 дня, на хабре вы бываете регулярно..
Я все еще жду от вас аргументации про пропаганду. Свой тезис я доказал общей статистикой, и вашим способом, по вашим же ссылкам.
Надеюсь на аргументированный ответ (но надежды уже тают..)
1) parity-db 20/24600 = 0.081%
Внутри вызовы mmap и libс. Обоснованно.
Еще 3 transmute, на первый взгляд можно и без них.
2) tabiew 11/7252 = 0,15%
Всё в тестах, и абсолютно не нужно. Можно использовать static_cell или атомарные переменные.
3) xi-editor 30/29356 = 0.11%
sse, avx, libc - какие-то оптимизации.
Еще 2 не нужных str::from_utf8_unchecked.
4) poem 0/47700 = 0%
Если выкинуть ненужные (на мой взгляд) unsafe, выйдет (17+28)/(24600+7252+29356+47700) = 0.04%
В 2 из 4 проектах можно обойтись без unsafe точно.
P.S. mmap очевидно нужен, c libc, sse и avx я не разбирался, тут уже нужно много времени потратить.
Легко. Цитирую:
Примерно 81% крейтов не содержат ни одной строчки unsafe. А среди остальных большинство - это FFI.
Теперь ваша очередь доказывать про пропаганду. Надеюсь получить аргументированный ответ.
Как и ожидалось, фразу про пропаганду вам подкрепить нечем.
Неужели так сложно сказать "я погорячился / я ошибся"?
Я вас прошу доказать вот эти ваши слова:
Потому что вы широко заявляете про пропаганду, но как пример приводите маленький проект, и обобщаете его на все проекты на Rust.
А я вам привел большой контрпример на 112kloc. Теперь, если вы стоите на своем, докажите на нескольких (больших) проектах.
Посмотрел. Похоже, что его транслировали из C в Rust (например этим), и потом добились того чтобы компилировался.
Я делаю такой вывод из того, что внутри написана реализация memset, memchr и юникода (лол). Так что ваш пример - это антипример.
P.S. Вот пример +- большого проекта (https://github.com/picodata/picodata), изначально написанного на Rust. На 112kloc Rust кода 238 строк unsafe (0.2%). Из них около 80% это плагин к tarantool, т.к. обращения к ffi.
Но restrict по умолчанию только в safe Rust. А в unsafe мы оказываемся ближе к С (но не на его уровне), и можно писать код на указателях, главное при переходе снова к ссылкам соблюдать ограничение restrict.
На практике за этим надо следить разработчикам библиотек, которые что-то оптимизируют через unsafe и указатели, а в прикладном коде unsafe практически не встречается.
Я считаю что это ошибка дизайна стандарта, и автор статьи тоже пытается это показать на примерах.
Причем не могу придумать ситуацию, где бы это было полезно. А значит можно было бы и поменять в новых версиях стандарта.
А вы точно прочитали статью? В конце раздела На сцене появляется C++11 ровно один указатель, и можно было бы заменить на std::string без изменения сути примера.
А суть в том, что на повторный std::move компилятор не выдает ошибку (и даже варнинг), и нужно много приседать, чтобы компилятор что-то заметил. Ито это не гарантируется.
Статью не читали, но осуждаете да?
На сколько я понимаю, GNU Coreutils не кроссплатформенный.
Возможно вы не знаете, но стандартная библиотека Rust тоже покрыта десятками тысяч тестов.
А если я подключу случайную библиотеку в Java, где гарантия, что она не вызовет внутри гонку данных? Или правильно вызовет С библиотеку, не приводя к UB.
Я думаю что требования для небезопасного кода одинаковые для всех языков: покрывать тестами, проверять санитайзерами, проводить фаззинг и т.д. Если библиотеки этого не делают, это не может быть претензией к самому языку.
Просто в Rust такие блоки кода намеренно выделены в блоки unsafe, чтобы быть заметнее. А в каком-нибудь Python вызов C-API легко затеряется среди тысяч строк кода.
Похоже вы отрицаете саму идею построения безопасного API поверх потенциально небезопасного кода.
Но если вы загляните в исходники стандартной библиотеки любого языка, то там будет и арифметика указателей, и ассемблерные вставки, и системные вызовы, что априори небезопасно. И тем не менее вызвать UB в C# например довольно трудно.
И? Там нет слова "неявное", что логично, т.к.
.into()
надо явно написать.Давайте приведу другой пример, тут уж должно быть абсолютно очевидно. Неявное приведение:
void func(uint8_t a) { ... }
func(-100)
Явное приведение с автоматическим выводом типа:
fn func(a: u8) { ... }
func((-100).into())
Если убрать
.into()
, то код не скомпилируется, т.к. в Rust сильная типизация, и неявных преобразований нет.