Size: a a a

Rust — русскоговорящее сообществo

2020 March 19

Э

Эрик in Rust — русскоговорящее сообществo
Вафель
Я же правильно понимаю, что ссылку на массив можно безопасно превратить в ссылку на меньший массив?

let arr = [0, 1, 2, 3];
let link: &[i32; 4] = &arr;
let sub: &[i32; 2] = unsafe { &*(link as *const [i32; 4]).cast::<[i32; 2]>() };
Там проблема с лайфтаймом может выползти и use-after-free, если неаккуратно делать. Я бы сделал функцию, которая явно берёт лайфтайм уже существующий.

unsafe fn to_lesser<'a, T: Sized, U: Sized>(reference: &'a T) -> &'a U {
   &*(reference as *const T as *const U)
}
источник

Э

Эрик in Rust — русскоговорящее сообществo
А если тебе надо сделать референс на Sized из ссылки на !Sized слайс, то тут скорее

unsafe fn sliceref_to_arref<'a, T: Sized, A: Sized>(s: &'a [T], index: usize) -> &'a A {
   &*((s.as_ptr() as *const T).add(index) as *const A)
}
источник

Э

Эрик in Rust — русскоговорящее сообществo
Ну и разумеется, во втором случае можно напихать

debug_assert!(s.len() > index);
debug_assert!((s.len() - index) * mem::size_of::<T>() >= mem::size_of::<A>());
источник

Э

Эрик in Rust — русскоговорящее сообществo
Хотя первый ассерт запаникует, если ты скастуешь &[T] с .len() == 0 в &[T; 0]. Но это какое-то извращение.
источник

M

Marat in Rust — русскоговорящее сообществo
есть struct B, у него есть функция next(&mut self) -> &A, которая возвращает ссылку на некоторый объект, срок жизни которой сохраняется вплоть до повторного вызова функции next() (ну и дропа self, естественно),  как это лучше всего описать средствами языка?
источник

p

polunin.ai in Rust — русскоговорящее сообществo
реализуй Iterator для B
источник

p

polunin.ai in Rust — русскоговорящее сообществo
получишь заодно бесплатно кучу комбинаторов
источник

MB

Mikail Bagishov in Rust — русскоговорящее сообществo
polunin.ai
реализуй Iterator для B
У итератора сигнатура fn next(&mut self) -> T
А тут fn next<'a>(&'a mut self) -> T + 'a
источник

M

Marat in Rust — русскоговорящее сообществo
Mikail Bagishov
У итератора сигнатура fn next(&mut self) -> T
А тут fn next<'a>(&'a mut self) -> T + 'a
вот да, почему по лайфтаймам нельзя кастомизировать трейты?
источник

MB

Mikail Bagishov in Rust — русскоговорящее сообществo
Marat
вот да, почему по лайфтаймам нельзя кастомизировать трейты?
потому что это совсем другой трейт получается.
источник

p

polunin.ai in Rust — русскоговорящее сообществo
Marat
вот да, почему по лайфтаймам нельзя кастомизировать трейты?
лайфтаймы являются частью типа
источник

MB

Mikail Bagishov in Rust — русскоговорящее сообществo
Я не в первый раз слышу, чтобы кто-то хотел такой вид итераторов. Но не помню библиотеку, которая объявляла бы такой трейт.
Но примерную сигнатуру я тебе показал.
источник

MS

Mikola Summer Duck in Rust — русскоговорящее сообществo
Разве не
impl<'a> Iterator for &'a B {
   type Item = &'a A;
}


эдит: не
источник

MS

Mikola Summer Duck in Rust — русскоговорящее сообществo
источник

p

polunin.ai in Rust — русскоговорящее сообществo
impl<'a, 'b> Iterator for TokenStream<'a, 'b> {
   type Item = &'a Token<'b>;
}

у меня вот так вот
источник

p

polunin.ai in Rust — русскоговорящее сообществo
pub struct TokenStream<'a, 'b> {
   raw: &'a [Token<'b>],
   cur_index: usize,
}
источник

M

Marat in Rust — русскоговорящее сообществo
У меня ругался, что 'b ничем не ограничен
источник

M

Marat in Rust — русскоговорящее сообществo
Хотя я его внутрь struct B не вносил, надо было наверно
источник

В

Вафель in Rust — русскоговорящее сообществo
Эрик
Там проблема с лайфтаймом может выползти и use-after-free, если неаккуратно делать. Я бы сделал функцию, которая явно берёт лайфтайм уже существующий.

unsafe fn to_lesser<'a, T: Sized, U: Sized>(reference: &'a T) -> &'a U {
   &*(reference as *const T as *const U)
}
Мне кажется мы друг друга не правильно поняли...

Дело не в функции (оно и так всё вынесено) а в вопросе — чтобы превратить slice: &[T] в &[T; N] нужно чтобы было верно slice.len() >= N, или всё же slice.len() == N?

Ну и да, вместо
unsafe fn to_lesser<'a, T: Sized, U: Sized>(reference: &'a T) -> &'a U {
   &*(reference as *const T as *const U)
}

Можно просто написать

unsafe fn ref_transmute<T, U>(reference: &T) -> &U {
   mem::transmute::<&T, &U>(reference)
}
источник

BD

Berkus Decker in Rust — русскоговорящее сообществo
Marat
Хотя я его внутрь struct B не вносил, надо было наверно
а где он жил тогда, ты ж его лайфтайм указываешь
источник