Блог*
#music Я всё ещё считаю, что Bytenommer незаслуженно непопулярен. И этот трек, пожалуй, пока что наилучшее из того, что он сделал. youtube.com/watch?v=Lp2TxF8KTOM
YouTube
9bit Chiptune: Bytenommer – It was the Best of Times
Happy new year 2023 with a new tune!
The chime sample is from pjcohen at Freesound: https://freesound.org/people/pjcohen/sounds/414558/
Twitter: https://twitter.com/bytenommer
Soundcloud: https://soundcloud.com/user-565017399
#9bit #fakebit #8bit #chiptune…
The chime sample is from pjcohen at Freesound: https://freesound.org/people/pjcohen/sounds/414558/
Twitter: https://twitter.com/bytenommer
Soundcloud: https://soundcloud.com/user-565017399
#9bit #fakebit #8bit #chiptune…
Forwarded from Awful Rust snippets for fun and profit
kinda obvious in retrospect
playground
there’s one deref missing and the whole Box gets coerced to dyn Any
playground
🤯5🤬1
Forwarded from Discussing Rust snippets for fun and profit
Awful Rust snippets for fun and profit
from lib never-say-never GitHub
причём это в целом усложнение
pub trait Get { type Never; }
impl<R> Get for fn() -> R { type Never = R; }
pub type Never = <fn() -> ! as Get>::Never;👍4
#prog #rust и абсолютно точная и при этом бестолковая ошибка.
Пусть есть вот такой код:
Посмотрим ещё раз на blanket impl для
Запомним это и перейдём к декларации
Что же происходит в реализации по умолчанию метода
* Компилятор не находит реализации
* ...поэтому также ищет impl-ы, которые позволят скомпилировать со взятием ссылки (то есть фактически
* ...находит, поскольку у нас есть blanket impl, предоставляющий метод
* ...проверяет корректность кода
* ...и наталкивается на ошибку, поскольку для взятия мутабельной ссылки от значения нужно, чтобы само значение было мутабельным, а биндинг
В итоге компилятор и выдаёт такую ошибку, к вящему неудовольствию того несчастного, которому не повезёт напороться на такую ситуацию.
Для сравнения: в C++ нельзя присваивать новое значение this (именно самому
Пусть есть вот такой код:
trait Modify {
fn modify(&mut self);
}
impl<T> Modify for T {
fn modify(&mut self) {
// ...
}
}
trait Foo {
fn mute(&mut self) {
self.modify();
}
}
Этот код не компилируется и выдаёт вот такое сообщение об ошибке:error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
--> src/lib.rs:13:9
|
13 | self.modify();
| ^^^^^^^^^^^^^ cannot borrow as mutable
На первый взгляд это выглядит, как полная чепуха: у нас же &mut self, параметр прямо объявлен мутабельным! Однако не всё так просто.Посмотрим ещё раз на blanket impl для
Modify:impl<T> Modify for T {
fn modify(&mut self) {
// ...
}
}
Тут написано, что трейт Modify реализовывается для некоторого типа T. А вот что тут не написано — так это то, что T удовлетворяет ограничению Sized. Этот трейт — единственный, который добавляется к обобщённым параметрам по умолчанию и, соответственно, Rust имеет синтаксис для того, чтобы это ограничение убрать: ?Sized.Запомним это и перейдём к декларации
Foo:trait Foo {
fn mute(&mut self) {
self.modify();
}
}
Метод mute имеет реализацию по умолчанию, и так как метод, для которого эта реализация имеется, определён на Self, этот тип не получает никаких ограничений вовсе, в том числе и Sized (и об этом сказано в документации к Sized). Но это не значит, что метод вызвать нельзя! Синтаксис вызова метода может брать ссылку на значение для того, чтобы удовлетворить сигнатуре метода. А подходящая реализация, как ни странно, имеется! Потому что T в impl<T> Modify for T покрывает любые (Sized) типы. Вообще любые. В том числе и... Ссылки.Что же происходит в реализации по умолчанию метода
mute?* Компилятор не находит реализации
Modify для Self...* ...поэтому также ищет impl-ы, которые позволят скомпилировать со взятием ссылки (то есть фактически
(&mut self).modify())...* ...находит, поскольку у нас есть blanket impl, предоставляющий метод
modify для &mut Self (а ссылка — всегда Sized тип)...* ...проверяет корректность кода
<&mut Self as Modify>::modify(&mut self)...* ...и наталкивается на ошибку, поскольку для взятия мутабельной ссылки от значения нужно, чтобы само значение было мутабельным, а биндинг
self — который можно написать явно, как fn mute(self_: &mut Self) { ... } (и за вычетом потери возможности использования синтаксиса вызова через точку это определение эквивалентно) — сам мутабельным не является.В итоге компилятор и выдаёт такую ошибку, к вящему неудовольствию того несчастного, которому не повезёт напороться на такую ситуацию.
Для сравнения: в C++ нельзя присваивать новое значение this (именно самому
this, а не тому, на что this указывает).GitHub
Improve compile error for borrowing mut while missing Sized trait bound · Issue #93078 · rust-lang/rust
Given the following code: trait Modify { fn modify(&mut self) ; } impl<T> Modify for T { fn modify(&mut self) { // ... } } trait Foo { fn mute(&mut self) { sel...
👍10🔥1
Блог*
#prog #rust и абсолютно точная и при этом бестолковая ошибка. Пусть есть вот такой код: trait Modify { fn modify(&mut self); } impl<T> Modify for T { fn modify(&mut self) { // ... } } trait Foo { fn mute(&mut self) { self.modify();…
Пока писал пост — вспомнил анекдот про математика и воздушный шар. Попытался найти текст и обнаружил, что к нему придумали продолжение:
...
— А вы, похоже, из управленцев, — заметил математик.
— Я действительно топ-менеджер серьезной компании, — воспрял воздухоплаватель, — Но как вы догадались? Вы видели меня по телевизору?
— Зачем? — удивился математик, — Судите сами: вы не понимаете ни где вы находитесь, ни что вам следует делать, в этом вы полагаетесь на нижестоящих. Спрашивая совета у эксперта, вы ни на секунду не задумываетесь, способны ли вы понять его ответ, и когда оказывается, что это не так — вы возмущаетесь вместо того, чтобы переспросить. Вы находитесь ровно в том же положении, что и до моего ответа, но теперь почему-то обвиняете в этом меня. Наконец, вы находитесь выше других только благодаря дутому пузырю, и если с ним что-то случится — падение станет для вас фатальным.
...
— А вы, похоже, из управленцев, — заметил математик.
— Я действительно топ-менеджер серьезной компании, — воспрял воздухоплаватель, — Но как вы догадались? Вы видели меня по телевизору?
— Зачем? — удивился математик, — Судите сами: вы не понимаете ни где вы находитесь, ни что вам следует делать, в этом вы полагаетесь на нижестоящих. Спрашивая совета у эксперта, вы ни на секунду не задумываетесь, способны ли вы понять его ответ, и когда оказывается, что это не так — вы возмущаетесь вместо того, чтобы переспросить. Вы находитесь ровно в том же положении, что и до моего ответа, но теперь почему-то обвиняете в этом меня. Наконец, вы находитесь выше других только благодаря дутому пузырю, и если с ним что-то случится — падение станет для вас фатальным.
😁21👍5❤2
Блог*
#prog #rust #rustlib #article Toward fearless cargo update I recently built cargo-semver-checks, a linter that ensures crates adhere to semantic versioning. This is why and how I built it. В FAQ также есть сравнение с аналогичными инструментами.
#prog #rust #rustlib #article
cargo-semver-checks today and in 2023
Following semver in Rust is a perfect example of a workflow worth automating:
* Important to get right, painful if done wrong: cargo requires all crates to follow semver, so breaking semver in one crate can have a ripple effect across the ecosystem. But if done right, semver is completely invisible.
* Countless complex rules: There are hundreds of ways to cause a breaking change, many of them non-obvious.
* Code that violates semver doesn't look wrong: No code reviewer can be expected to reliably flag most of the semver issues, even assuming they are well-versed in all the semver rules. The evidence on this point is particularly overwhelming (1, 2, 3, 4, 5).
Some might say the solution is to "git gud". I deeply respect operational excellence, but this is not the way.
Civilization advances at the rate at which we develop robust abstractions. I am writing this on a computer I cannot build, under a blanket I cannot weave, having enjoyed a meal with ingredients I cannot grow. I dedicated ten years to math competitions, and I can't even calculate a logarithm by hand! Can you?
Gatekeeping to only include people with a PhD in "Semver in Rust" won't cut it.
Yosh Wuyts quotes another Rust contributor as saying: "The job of an expert is to learn everything about a field there is to learn, and then distill it so that others don't have to." I couldn't agree more!
cargo-semver-checks today and in 2023
Following semver in Rust is a perfect example of a workflow worth automating:
* Important to get right, painful if done wrong: cargo requires all crates to follow semver, so breaking semver in one crate can have a ripple effect across the ecosystem. But if done right, semver is completely invisible.
* Countless complex rules: There are hundreds of ways to cause a breaking change, many of them non-obvious.
* Code that violates semver doesn't look wrong: No code reviewer can be expected to reliably flag most of the semver issues, even assuming they are well-versed in all the semver rules. The evidence on this point is particularly overwhelming (1, 2, 3, 4, 5).
Some might say the solution is to "git gud". I deeply respect operational excellence, but this is not the way.
Civilization advances at the rate at which we develop robust abstractions. I am writing this on a computer I cannot build, under a blanket I cannot weave, having enjoyed a meal with ingredients I cannot grow. I dedicated ten years to math competitions, and I can't even calculate a logarithm by hand! Can you?
Gatekeeping to only include people with a PhD in "Semver in Rust" won't cut it.
Yosh Wuyts quotes another Rust contributor as saying: "The job of an expert is to learn everything about a field there is to learn, and then distill it so that others don't have to." I couldn't agree more!
predr.ag
cargo-semver-checks today and in 2023
40,000 downloads, 30 lints, and many prevented semver issues in the real world. We're just getting started.
👍5