1.94K subscribers
3.49K photos
136 videos
15 files
3.72K links
Блог со звёздочкой.

Много репостов, немножко программирования.

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
#prog #rust #rustreleasenotes

Вышла версия Rust 1.90.0!.. Больше недели назад. В свою защиту могу сказать, что в этой версии заметных для большинства пользователей изменений в языке и нету.

Как всегда, тут только избранные части, всё остальное в детальных заметках о релизе.

▪️Как и было обещано, для таргета x86_64-unknown-linux-gnu теперь по умолчанию используется более быстрый линкер lld.

▪️В качестве расширения к методам, добавленным в Rust 1.66.0, добавили методы uX::*_sub_signed (wrapping, checked, overflowing и saturating варианты) для корректного вычитания чисел с разной знаковостью.

▪️CString, CStr и Cow<CStr> теперь можно сравнивать на равенство между собой. Нет, PartialOrd между ними не реализован. Нет, я не знаю, почему.

▪️Старый PR докатился до стейбла: в const-контексте наконец можно вызывать reverse на слайсах. Также теперь там можно вызывать на числах с плавающей точкой различные методы для округления и fract для извлечения дробной части.

▪️Реализацию Default для iter::Fuse привели в соответствие с документацией: теперь default создаёт Fuse, оборачивающий значение по умолчанию внутреннего итератора, вместо создания всегда пустого итератора.

▪️Реализации io::Write для TcpStream и UnixStream теперь на Linux пишут данные с флагом MSG_NOSIGNAL. Это означает, что запись в померший нижележащий сокет теперь возвращает EPIPE — или, в терминах Rust, io::Error, у которого kind() возвращает ErrorKind::BrokenPipe. Данное изменение делает поведение консистентным с тем, как сокеты ведут себя в других местах в std.

▪️Компилятор теперь не даёт скомпилировать код, который упоминает ABI, неподдерживаемый на целевой платформе.
👍61
#prog #rust #article

From Rust to Reality: The Hidden Journey of fetch_max

Why would Rust provide fetch_max as a built-in intrinsic? Intrinsics usually exist to leverage specific hardware instructions. But x86-64 doesn't have an atomic max instruction. So there had to be a CAS loop somewhere in the pipeline.

<...>

So I started digging. What I found was a fascinating journey through five distinct layers of compiler transformations, each one peeling back another level of abstraction, until I found exactly where that loop materialized. Let me share what I discovered.
3
😁16🤣2👎1🤔1
#prog #rust #rustlib #article

I Wrote A String Type

Статья, рассказывающая о принципиальном устройстве byteyarn — оптимизированного типа для строк, который умещается в 16 байт, имеет small string optimisation и имеет нишу, позволяющую не увеличивать размер при оборачивании в Option
👍6🤔1
😁17👏8🔥1
#prog #rust #rustlib #ml #abnormalprogramming

unwrap_or_ai

Tired of manually handling unwrap() results? Let AI do the heavy lifting!
🤩19🤡2
#prog #cpp #rust #article

Why we didn't rewrite our feed handler in Rust

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

Первое касается ограничений borrow checker-а. Вот какой пример приводят:

fn process_source(sources: Vec<Source>) {
for source in sources {
let mut buffer: Vec<&[u8]> = Vec::new();
let data: Vec<u8> = source.fetch_data();
buffer.extend(data.split(splitter));
process_data(&buffer);
}
}


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

error[E0597]: `data` does not live long enough
--> src/lib.rs:32:23
|
31 | let data: Vec<u8> = source.fetch_data();
| ---- binding `data` declared here
32 | buffer.extend(data.split(splitter));
| ------ ^^^^ borrowed value does not live long enough
| |
| borrow later used here
33 | process_data(&buffer);
34 | }
| - `data` dropped here while still borrowed


Второй паттерн — самоссылающиеся структуры, известная больная тема в Rust.

Третий паттерн — множество определений разных версий и унифицированный код для работы с ними (из-за необходимости поддержки разных версий схем обмена данных, насколько я понял). Пример из статьи на C++:

struct RecV1 {
uint32_t x;
uint32_t y;
}

struct RecV2 {
uint32_t x;
uint32_t y;
uint32_t z;
}


Унифицированный код для работы с обоими этими типами можно написать при помощи шаблонов:

template <typename T>
T InitRec() {
T res;
res.x = 1;
res.y = 2;
if constexpr(std::is_same_v<T, RecV2>()) {
res.z = 3;
}
return res;
}


Нетрудно видеть, как это обобщается на случай большего количества полей и различных версий. В Rust можно попробовать сделать нечто подобное, но это вырождается в бойлерплейт, облегчать который приходится макросами — иными словами, попытка повторить шаблоны из C++.
👍10🤡5🔥1
#prog #rust #abnormalprogramming

fibonacci-numbers crate with self-recursive dependencies

I have created a crate called fibonacci-numbers. There are 187 different major versions of the crate, each exporting the Fibonacci number corresponding to that version.
<...>
Version 186 depends on version 184 and 185 and exports the largest Fibonacci number that fits in a u128:


pub const VALUE: u128 = fib184::VALUE + fib185::VALUE;
😁28🔥7🤡3🤯1
#prog #rust

rustc_codegen_gcc: Progress Report #38

В rustc_codegen_gcc теперь работает LTO, в том числе и cross-language! 🎉
😢16👍9🌚3
#prog #rust #article

A Little Rust Trait Limitation

I stumbled across a … bug(?) … a limitation(?) … an issue(!) with the Rust compiler. Fortunately, I was able to find out what was going on in the Rust programming language forum. I thought this issue was interesting enough and subtle enough to try to explain to my blog audience.

<...>

This isn’t an explanation of why this limitation is necessary or fundamental, because it isn’t – it’s a limitation that could, and maybe at some point will be, fixed.
😢14