
Size: a a a



vis в макросах сопоставляется с описанием видимости определения, в том числе и пустым.macro_rules! accept_with_vis {
    ($vis:vis struct $name:ident;) => {}
}
accept_with_vis!{struct Foo;}
vis в макросах сопоставляется с описанием видимости определения, в том числе и пустым.macro_rules! accept_with_vis {
    ($vis:vis struct $name:ident;) => {}
}
accept_with_vis!{struct Foo;}macro_rules! accept_just_vis {
    ($vis:vis) => {}
}
accept_just_vis!{}
Drop, нельзя деструктурировать. Однако надо отметить, что если тип поля реализует Copy, то к этому полю можно обратиться, в том числе и пре деструктуризации, при этом значение этого поля скопируется. Проиллюстрирую только что сказанное:struct NonCopy;
struct Dropping<T>(T, NonCopy);
impl<T> Drop for Dropping<T> {
    fn drop(&mut self) {
        println!("dropped");
    }
}
fn main() {
    // ⬇️ если раскомментировать эту строку, то программа не скомпилируется с E0509
    // let Dropping(_non_copy, _) = Dropping(NonCopy, NonCopy);
    // А вот это — компилируется и печатает "dropped".
    // Обратите внимание, паттерн `_`  *не* перемещает значение.
    let Dropping(_x, _) = Dropping(0_u32, NonCopy);
}
Где это может выстрелить? При написании биндингов к сишным либам. Одна их техник обеспечения инкапсуляции в C — это определение структуры в заголовочном файле без определения её полей. Это позволяет получить доступ к полям структуры только там, где дано её определение, а внешний код может обращаться к ней лишь по указателю. И указатель — это Copy-тип, да.extern "C" {
    // extern types ещё не стабилизированы, так что
    // в реальной библиотеке, скорее всего, будут использовать *mut std::ffi::c_void
type Some_C_Struct;Что произойдёт, если мы попытаемся деструктурировать
fn c_lib_release_resources(arg: *mut Some_C_Struct);
}
struct Handle(*mut Some_C_Struct);
impl Drop for Handle {
fn drop(&mut self) {
unsafe { c_lib_release_resources(self.0) }
}
}
Handle? Скажем, нам зачем-то потребовалась реализация метода leak:impl Handle {
    fn leak(self) -> *mut Some_C_Struct {
        // Здесь мы разбираем значение, но так как указатель — Copy-тип,
        // имя ptr привязывается к копии значения, перемещения не происходит.
        let Handle(ptr) = self; // <-- после этой точки с запятой кончается время жизни self, и вызывается деструктор
        // Ура, у нас на руках невалидный указатель!
        ptr
    }
}
Что можно с этим сделать? Использовать ManuallyDrop. Этот тип предотвращает вызов деструктора (а также деструктуризацию, поскольку у него приватные поля), но при этом не предотвращает доступ к полям значения внутри (через Deref). Возникает вопрос, почему не использовать std::mem::forget? В принципе, в документации подробно расписано, но если коротко, то std::mem::forget значительно сложнее корректно использовать.




Vec 🎉. Первый шаг на пути к стандартным коллекциям с полностью настраиваемым аллокатором.








