Блог*
#prog #rust #моё Во время решения одной из задач Advent of Code мне пришлось решать довольно заковыристую в плане владения задачу: требовалось связать цепочку интерпретаторов так, чтобы данные, выдаваемые одним экземпляром интерпретатора, использовались в…
#prog #rust #моё
В конце этой заметки я сказал, что планирую расширить код до поддержки
Теперь попытаемся использовать данный тип:
Хочу особо отметить, что мы получили UB, не написав (как пользователь) unsafe-код и не вызвав unsafe-код напрямую, поэтому наш код unsound.
В конце этой заметки я сказал, что планирую расширить код до поддержки
impl BorrowMut<VecDeque<T>>
. Теперь я понимаю, что это несколько неосмотрительно: код в unsafe полагается на то, что адрес, по которому лежат данные, не меняется. В случае impl BorrowMut
такой гарантии уже нет. Для доказательства того, что подобный вариант является unsound, предположим, что MutPair уже реализовал подобный функционал (это изменение я, с вашего позволения, опущу, потому что это чисто механическое изменение кода) и рассмотрим следующий тип:#[derive(Default)]
struct DeqWrapper<T> {
inner: VecDeque<T>,
}
Для него можно написать следующие реализации Borrow
и BorrowMut
:impl<T> Borrow<VecDeque<T>> for DeqWrapper<T> {
fn borrow(&self) -> &VecDeque<T> {
&self.inner
}
}
impl<T> BorrowMut<VecDeque<T>> for DeqWrapper<T> {
fn borrow_mut(&mut self) -> &mut VecDeque<T> {
self.inner.clear();
&mut self.inner
}
}
Да, это отвратительно, да, так никто (я надеюсь) не пишет. Но принципиально нас ничего от этого не ограждает. Хочу отметить, что код выше не содержит unsafe
.Теперь попытаемся использовать данный тип:
let wrapper = DeqWrapper::<i32>::default();
wrapper.inner.push_back(0);
wrapper.inner.push_back(1);
let mut mut_pair = MutPair::new(wrapper).unwrap(); // (1)
let _ = mut_pair.get(); // (2)
Что тут происходит? В (1) мы делаем внутри MutPair::new
проверку длины дека. Так как при этом мы используем .borrow()
, DeqWrapper
даёт ссылку на поле inner
, длина которого как раз достаточна, поэтому MutPair
возвращает Ok
и .unwrap()
не паникует. В (2) мы вызываем .borrow_mut()
, из дека удаляется данные, MutPair::get
использует get_mut
, предполагая, что данные есть, и — вуаля! — мы получаем ссылку на неинициализированные данные! Что является UB в Rust.Хочу особо отметить, что мы получили UB, не написав (как пользователь) unsafe-код и не вызвав unsafe-код напрямую, поэтому наш код unsound.
Блог*
#prog #rust #моё В конце этой заметки я сказал, что планирую расширить код до поддержки impl BorrowMut<VecDeque<T>>. Теперь я понимаю, что это несколько неосмотрительно: код в unsafe полагается на то, что адрес, по которому лежат данные, не меняется. В случае…
В чём же проблема? Наш код слепо доверял реализации
Каковы решения? Лично я вижу такие:
1) Объявить методы
2) Оставить код как есть. Вполне рабочий вариант, но не исключено, что для кого-то это окажется недостаточно гибким.
3) Обобщить код относительно sealed-трейта и включить в него только доверенные реализации (для
99) Требовать от типов реализовать трейт, который не только даёт мутабельную ссылку на
BorrowMut
, чего делать не стоит (unsafe не должен доверять safe).Каковы решения? Лично я вижу такие:
1) Объявить методы
MutPair
как unsafe
. В принципе, вариант, но это немного лишает смысла эту абстракцию.2) Оставить код как есть. Вполне рабочий вариант, но не исключено, что для кого-то это окажется недостаточно гибким.
3) Обобщить код относительно sealed-трейта и включить в него только доверенные реализации (для
VecDeque<T>
и &mut VecDeque<T>
). Тоже рабочий вариант (если я таки буду публиковать этот код на crates.io, то, вероятно, так и поступил бы), но это выглядит несколько избыточным решением + страдает эргономика: пользователю теперь надо импортировать нужный трейт, который он(а) не может реализовать.99) Требовать от типов реализовать трейт, который не только даёт мутабельную ссылку на
VecDeque
, но и требует доказательство вменяемости такой реализации. К сожалению, этот вариант сильно превосходит текущие возможности Rust и навряд ли когда-то будет осуществлён.rust-lang.github.io
Future proofing - Rust API Guidelines
This is a set of recommendations on how to design and present APIs for the Rust programming language.
#prog #video
Как писать тесты (если быть более точным — тесты для property-based тестирования).
Лично для меня поразила идея metamorphic testing — простая и вместе с тем плодотворная.
https://youtu.be/zvRAyq5wj38
Как писать тесты (если быть более точным — тесты для property-based тестирования).
Лично для меня поразила идея metamorphic testing — простая и вместе с тем плодотворная.
https://youtu.be/zvRAyq5wj38
YouTube
John Hughes - How to specify it! A guide to writing properties of pure functions | Code Mesh LDN 19
This video was recorded at Code Mesh LDN 19 - http://bit.ly/37xc3Nr
Get involved in Code Sync's next conference - http://bit.ly/2Mcm4aS
---
HOW TO SPECIFY IT! A GUIDE TO WRITING PROPERTIES OF PURE FUNCTIONS
by John Hughes
ABSTRACT
Property-based testing…
Get involved in Code Sync's next conference - http://bit.ly/2Mcm4aS
---
HOW TO SPECIFY IT! A GUIDE TO WRITING PROPERTIES OF PURE FUNCTIONS
by John Hughes
ABSTRACT
Property-based testing…
Напоминаю: DRM — это рак
habr.com/ru/company/dcmiran/blog/484718/
habr.com/ru/post/208390/
habr.com/ru/post/171849/
habr.com/ru/post/364775/
habr.com/ru/company/dcmiran/blog/484718/
habr.com/ru/post/208390/
habr.com/ru/post/171849/
habr.com/ru/post/364775/
Хабр
Современные принтеры HP отказываются работать без подписки на чернила
Покупателям струйных принтеров следует быть осторожными. Современные модели продаются с программным модулем DRM. Принтер перестанет работать, если вы не оплатили подписку на чернила В...
В копилку когнитивных искажений: ru.wikipedia.org/wiki/Парадокс_Абилина
Кажется, нужен новый тег... #psy?
Кажется, нужен новый тег... #psy?
Wikipedia
Парадокс Абилина
группа людей может принять решение, противоречащее возможному выбору любого из членов группы
#prog #article
As closing thoughts: this blog post is not intended to start a flame war, nor is it intended to be an assault on dynamically typed programming. There are many patterns in dynamically-typed languages that are genuinely difficult to translate into a statically-typed context, and I think discussions of those patterns can be productive. The purpose of this blog post is to clarify why one particular discussion is not productive, so please: stop making these arguments. There are much more productive conversations to have about typing than this.
https://lexi-lambda.github.io/blog/2020/01/19/no-dynamic-type-systems-are-not-inherently-more-open/
As closing thoughts: this blog post is not intended to start a flame war, nor is it intended to be an assault on dynamically typed programming. There are many patterns in dynamically-typed languages that are genuinely difficult to translate into a statically-typed context, and I think discussions of those patterns can be productive. The purpose of this blog post is to clarify why one particular discussion is not productive, so please: stop making these arguments. There are much more productive conversations to have about typing than this.
https://lexi-lambda.github.io/blog/2020/01/19/no-dynamic-type-systems-are-not-inherently-more-open/
Forwarded from Aleksandr Razumov
Ну и правильно писать на го нифига не просто, весь этот маркетинговый булщит работает только под хорошим менторством и ревью от синьеров
#article #retroit
Разбор электронных часов, использовавшихся на "Союзе". Спойлер: схема занимает несколько плат, большинство покрыто чипами.
http://www.righto.com/2020/01/inside-digital-clock-from-soyuz.html
Разбор электронных часов, использовавшихся на "Союзе". Спойлер: схема занимает несколько плат, большинство покрыто чипами.
http://www.righto.com/2020/01/inside-digital-clock-from-soyuz.html
Righto
Inside the digital clock from a Soyuz spacecraft
We recently obtained a clock that flew on a Soyuz space mission. 1 The clock, manufactured in 1984, is much more complex inside than you'd ...