LINUX.ORG.RU

Автор Wayland композитора Way Cooler переписывает своё детище с Rust на C

 , ,


2

9

Как-то давно смотрел список Wayland композиторов, в нём был проект Way-Cooler, примечательный тем, что декларировался как духовный наследник AwesomeWM и проект использовал Rust. Но недавно я набрёл на пост автора с грустными новостями. В новостях про Rust часто просят привести примеры ПО, разрабатываемого на этом языке, т.е. многим интересен опыт реального применения этого языка. Именно таким опытом и делится автор по ссылке выше.

Для Ъ я попробую перевести пару самых главных, на мой взгляд, тезисов из поста. Надеюсь мой перевод не исказит смысл оригинала.

Автор на протяжении примерно года писал биндинг к библиотеке wlroots, за это время он внёс более 1000 изменений и в итоге репозиторий wlroots-rs содержал более 11 тысяч строк Rust кода, при чём это не просто копипаста одного куска для каждой сущности библиотеки, автор написал несколько макросов, один из которых сам же назвал уродливым. Автор пишет, что все 11 тысяч строк это просто обёртки, которые занимаются управлением памяти и при этом они не покрывают и половины API wlroots. Кроме того, автор заметил, что разобраться и пользоваться плодом его трудов довольно сложно и некоторые отказываются от использования wlroots-rs в пользу wlroots.

Основными проблемами при написании обёртки для wlroots автор называет описание модели владения объектами wlroots на языке Rust. По ссылке автор показывает несколько примеров кода, которые демонстрируют проблему. Кроме того, автор не видит возможности написать на Safe Rust расширение протокола Wayland.

В итоге автор принял непростое решение переписать Way-Cooler на C. Автор упоминает некоторые другие проекты, столкнувшиеся с аналогичной проблемой написания биндингов, которые приняли противоположное решение – переписать библиотеки на Rust.

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

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

Тогда как в Scala каждый может собственный набор операторов определять.

Проблема кастомных операторов только в неучах, которые ФП не выучили и начали велосипеды лепить.

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

неасиляторы C++

А его можно осилить? Все эти рассказы про безопасный, современный С++ с умными указателями и санитайзерами - это прекрасно, только в реальности они создают больше проблем, чем решают. Тут только на вчера был очередной топик на эту тему.

И я молчу про экосистему. Да, свой код можно вылизать до безупречности? А что делать с зависимостями? Rust решает эту проблему.

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

Проблема кастомных операторов только в неучах

Проблема, на самом деле в том, что нет возможности защиться от неучей. Но есть языки, которые более толерантны к таковым. Например, это Java или Go. А есть языки, которые совсем к таковым не толерантны: C и C++ ярчайшие примеры.

Что характерно, Scala скорее относится к нетолерантным языкам.

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

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

Самый читаемый язык - это, конечно, же D

void main()
{
    import std.stdio, std.string, std.algorithm, std.conv;

    // Reduce the RPN expression using a stack
    readln.split.fold!((stack, op)
    {
        switch (op)
        {
            // Generate operator switch cases statically
            static foreach (c; "+-*/")
                case [c]:
                    return stack[0 .. $ - 2] ~
                        mixin("stack[$ - 2] " ~ c ~
                            " stack[$ - 1]");
            default: return stack ~ op.to!real;
        }
    })((real[]).init).writeln;
}

Это?!

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

А его можно осилить?

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

А что делать с зависимостями?

Использовать то, что есть. Начиная от svn:externals или git submodules, заканчивая vcpkg, conan, hunter и т.д.

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

Не судите окружающих по себе.

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

Использовать то, что есть.

Я не про пакетный менеджер, а про то, что rust распространяет свои гарантии на все зависимости. В C++ мы же может гарантировать корректность только своего кода.

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

и санитайзерами - это прекрасно, только в реальности они создают больше проблем, чем решают.

Можно услышать про проблемы, которые создают санитайзеры и статические анализаторы?

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

Посчитал свои проекты, тоже под 50к получается.

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

Количество багов в плюсовом коде говорит строго об обратном.

Вы еще скажите, что есть кодовые базы, лишенные багов. Баги есть везде.

Ну и не нужно путать списки уязвимостей для C-шного и C++ного кода.

Тем не менее, изначальный поинт про неасиляторов C++ был в том, что из C++ на Rust переходят те, кто не может освоить классы и наследование, шаблоны и constexpr. Если программируешь на убогом подмножестве, называемом «C с классами», то смысла оставаться в C++ нет. Никаких возможностей + куча способов отстрелить себе ноги.

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

а про то, что rust распространяет свои гарантии на все зависимости

На кону мочало. Вы сейчас опять про сказки о safe rust не смотря на (потенциальное) наличие кучи unsafa под капотом.

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

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

Починил. Ах да, я забыл: это ж не язык кривой, это людишки неправильные.

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

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

статические анализаторы

Я не видел стат. анализаторы которые бы понимали код в той же мере, что и rustc. Есть такие, которые гарантирую отсутствие use-after-move?

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

Суть safe кода не в том, что весь код — safe, а в том, что только малая часть кода unsafe. Ты решил упороться на манер Царя? Ну, удачи на этом нелёгком пути.

i-rinat ★★★★★
()
Ответ на: комментарий от Deleted

Ах да, я забыл: это ж не язык кривой, это людишки неправильные.

Если C++ настолько плох, почему куча софта, которым пользуются миллиарды людей по всему миру, написана на C++, а не на прекрасных и безопасных альтернативах?

Ответ простой: в своей нише для C++ не было достойных альтернатив (даже не смотря на наличие таких языков, как Ada, Modula-2, ObjectPascal, Eiffel, D). Одна появилась всего несколько лет назад — это Rust. Но и у той, помимо высокого порога входа еще и проблемы с интеграцией с уже существующим вокруг софтом (о чем, собственно, обсуждающаяся здесь заметка).

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

Эта «толерантность» на самом деле стоит очень дорого.

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

А было бы интересно. Именно применительно к long и char.

Хмм. Чую подвох в вопросе) Ну ничего, учиться никогда не поздно, а ошибки я признавать умею.

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

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

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

И какое отношение это имеет к статическому анализу?

Я не видел стат. анализаторы которые бы понимали код в той же мере, что и rustc.

Это не ответ на вопрос о проблемах, которые привносит использование статических анализаторов.

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

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

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

А вообще это фрагмент кода из корпоративного долгостроя. Кто его писал я не знаю.

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

А чего ты тогда так нападаешь на Rust?

Где?

Меня давно утомило то, что пропагандой Rust-а занимаются люди с очень странным восприятием реальности. Когда сумасшедшие начинают рекламировать хорошую вещь, то невольно начинаешь опасаться этой самой вещи.

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

Тем не менее, изначальный поинт про неасиляторов C++ был в том, что из C++ на Rust переходят те, кто не может освоить классы и наследование, шаблоны и constexpr.

Есть большие сомнения что с такими способностями можно осилить раст у которого и кроме borrow checker есть и нетривиальные генерики и алгебраические типы данных.

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

кто так и не смог осилить C++ в достаточной степени

То есть, почти всех. Так?

Вот смотрел я как-то код одного персонажа, он там сырые указатели использовал и new. Я ему — не делай так, используй unique_ptr, он обеспечит удаление при исключениях и явно указывает владельца ресурса. Думаешь, помогло? Нет. Убрать я этого персонажа из проекта не могу, он как бы главный там. И таких перлов у него в коде регулярно много.

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

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

i-rinat ★★★★★
()
Ответ на: комментарий от eao197

Человек пришёл в Rust-тред и рассказал о своём опыте использования Rust, из-за чего ты начал бросаться на него с матами. Ты уверен, что правильно расставил флажки сумасшествия по участникам треда?

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

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

В C и C++ char — это такой же целочисленный тип, как и long. И при возврате char-а производится автоматическое расширение значения до размерности long-а.

Подвох можно ожидать, емнип, разве что в случае, когда char (по умолчанию знаковый) возвращается в качестве unsigned long-а. А вот для знаковых char и long что-то я проблем не припомню.

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

Зачем сразу думать о людях плохо?

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

i-rinat ★★★★★
()
Ответ на: комментарий от eao197

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

Какие возможности делают его хотя бы частично безопасным? Инвалидация итераторов, move с тонной исключений (типа move + unique_ptr), 100-и-1 способ выстрелить себе в ногу с помощью string_view, бесполезный и опасный std::optional, неюзабильный std::variant, дорогой shared_ptr, бесполезный noexcept. И это всё C++17, а не какая-то сишка с классами.

с переиспользованием старых библиотек

Которые написаны до C++11? ЗСБ.

Вы сейчас опять про сказки о safe rust не смотря на (потенциальное) наличие кучи unsafa под капотом.
кучи

Вы про std? Ибо для остального есть forbid unsafe, cargo geiger и grep.

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

То есть, почти всех. Так?

Нет. Просто не нужно отдельных упортых персонажей (которых, возможно, процентов 10 или 20 от общей массы) рассматривать как общий случай.

eao197 ★★★★★
()
Ответ на: комментарий от i-rinat

Из него можно вырасти

Или на оборот. См. Эдик или Iron_Bug.

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

Это не ответ на вопрос о проблемах, которые привносит использование статических анализаторов

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

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

Советую на досуге посмотреть код harfbuzz (да и любого проекта, которому больше 10 лет). Там вообще эпично. Фактически Си с шаблонами. То есть используется C++11 компилятор, при этом от C++ только шаблоны. Даже std/stl нет. Ну и паря лямбд в новом коде.

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

И я молчу про экосистему. Да, свой код можно вылизать до безупречности? А что делать с зависимостями? Rust решает эту проблему.

Да ну, даже код без unsafe может быть с критической проблемой:

Rust’s memory safety guarantees make it difficult, but not impossible, to accidentally create memory that is never cleaned up (known as a memory leak).

И дальше

Preventing memory leaks entirely is not one of Rust’s guarantees in the same way that disallowing data races at compile time is, meaning memory leaks are memory safe in Rust.

напоминает пресловутую стабильную ветку Debian. Где софт с багами (для которых есть фиксы в upstream), но зато с гарантированно стабильными.

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

из-за чего ты начал бросаться на него с матами.

Не нужно путать. Он начал нести ерунду. А то, что в этой ерунде он еще и рассказал про опыт работы с Rust-ом, сам факт наличия ерунды не отменяет.

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

Отвратительно, но раст не лучше в плане читаемости, хоть и далеко не так уродлив.

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

А вообще это фрагмент кода из корпоративного долгостроя. Кто его писал я не знаю.

каким боком это к драйверам Linux относится ? переменная char места не сэкономит а на большинстве процессоров работать будет медленней чем int - у них нет обрезков вместо регистров как на x86, компилятор будет для них дополнительный код генерировть.

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

Ну, я глянул на rosetta code решение этой проблемы различными языками. D хорош. Очень хорош. Picolisp ещё классный.

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

Иначе в чем укор?

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

Rust гарантирует отсутствие проблем с безопасностью и гонок данных. Утечки в список решаемых проблем не входят, ибо std::forget не unsafe.

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

Он давно утверждает что это не он агрессивен, это все вокруг дураки. «Человек с очень странным восприятием реальности» (c).

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

Ну да, неявное приведение типов же никто не отменял, так что char вернуть вместо long это штатная ситуация. А я про случай, когда вместо char возвращается long. И С, и С++ это позволяют сделать, я, может ошибаюсь, конечно, не гуру и не п*дый программист я, но по мне так произойдет потеря старших байт в этом случае. Причем ошибка выявится неявно только когда эти старшие байты начнут использоваться, т.е. через n лет после написания кода. Когда человек уже на пенсии. А D (полагаю и Rust тоже) заставит программиста разобраться в этом случае, так как выдаст ошибку. Пример:

char foo() {
    long i = 0xFF00000000000000;
    return i;
}

int main()
{
    return foo();
}
С оптимизацией -03 умный компилятор сгенерирует:
foo():
        xor     eax, eax
        ret
main:
        xor     eax, eax
        ret
Ну очевидно же, что это не то, что имел в виду программист, правильно? Ведь результат должен быть -72057594037927936.

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

Иначе в чем укор?

Это был намёк на то, что говнокодить можно на любом языке. Читабельность языка самого по себе какая-то абстрактная характеристика.

Picolisp

Увы, у меня аллергия на скобочки.

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

Странно, ведь это же одна из центральных проблем кода на C/C++. Отсутствие решение которой ведёт к необходимости создания сложного софта по нахождению утечек (или адаптирование имеющегося), тормозов при работе этого софта, траты времени на анализ полученных результатов.

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

Ты сейчас о чем вообще? Я про то, что сишечка и плюсы позволяют вернуть переменную типа long из функции, которая возвращает пусть не char, если тебе так он не нравится, а например int. С потерей старших байт.

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

Какие возможности делают его хотя бы частично безопасным?

А кто вам сказал, что «возможности» == «безопасность». Если вам нужна безопасность в принципе, то C++ вам вряд ли нужен. По крайней мере обычный C++, не обложенный какими-нибудь MISRA.

Возможности – это, например:

  • возможность сделать на шаблонах декларативное описание пайплайна обработки данных. Где в compile-time будет проверяться, что тип результата предыдущей стадии совпадает с типом входа на следующей стадии;
  • возможность сделать на шаблонах policy-based design, где наличие или отсутствие какого-либо типа в параметрах (или использование одного типа вместо другого) включает или отключает ту или иную функциональность. Например, указал my_server<null_logger> и нет кода по логированию вообще;
  • возможность сделать проверку того, что при работе с каким-то объектом пользователь вызвал тот или иной метод;
  • возможность сделать аналог Go-ных каналов и средства работы с ними (вроде аналога Go-шного select-а);

И т.д., и т.п.

Ничего этого на «C с классами» не сделать. А даже если и попытаться, то все проверки уйдут в run-time. Со всеми вытекающими.

Какие-то вещи из этого могут повысить безопасность кода. Но C++, в принципе, не про безопасность.

Которые написаны до C++11? ЗСБ.

И что? Есть какой-нибудь древний софт, решающий специфическую задачу. Он работает. Его легко переиспользовать. Вы бы, наверное, шашки наголо и бросились бы его на Rust-е переписывать?

Ибо для остального есть forbid unsafe, cargo geiger и grep.

Ну вот в каком-то из Rust-овских обсуждений бросили ссылку на некий крэйт с реализацией эффективной lock-free очереди. У которой по капотом все на unsafe.

Вы тупо запретите ее использовать потому, что forbid unsafe?

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

Хорошо, какие проблемы привносят санитайзеры?

Стат. анализаторы для C/C++ в принципе бесполезные.

От оно чё, Михалыч. А мужики-то и не знают.

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

это же одна из центральных проблем кода на C/C++

Сейчас придёт царь eao197 и расскажет что вывсёврёти.

Но справедливости ради, создать утечку в safe rust можно только двумя способами: циклические ссылки и forget. То есть шанс нарваться на подобную проблему катастрофически мал.

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

Я про то, что сишечка и плюсы позволяют вернуть переменную типа long из функции, которая возвращает пусть не char

а я про драйверы Linux если что. Кстати компилятор в таком случае выдаст варнинг о несоотвтетсвии типов.

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

А я про случай, когда вместо char возвращается long.

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

А то, что в C есть неявные преобразования типов (мне особенно нравится неявный каст void* к любому другому типу указателей) — это как раз одна из причин, почему C говно.

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