Почему Rust использует два байта для представления этого перечисления, когда нужен только один? - PullRequest
0 голосов
/ 03 февраля 2019

Кажется, он достаточно умен, чтобы использовать только один байт для A, но недостаточно умен, чтобы использовать один байт для B, даже если существует только 8 * 8 = 64 возможностей.Есть ли способ уговорить Руста разобраться с этим или мне нужно вручную реализовать более компактный макет?

Ссылка для игровой площадки.

#![allow(dead_code)]

enum A {
    L,
    UL,
    U,
    UR,
    R,
    DR,
    D,
    DL,
}

enum B {
    C(A, A),
}

fn main() {
    println!("{:?}", std::mem::size_of::<A>()); // prints 1
    println!("{:?}", std::mem::size_of::<B>()); // prints 2
}

1 Ответ

0 голосов
/ 03 февраля 2019

Оба байта необходимы для сохранения возможности заимствовать элементы структуры.

Тип в Rust не является идеальным набором значений: он имеет макет данных, описывающий способ хранения значений.Одно из «правил», регулирующих язык, заключается в том, что размещение типа внутри struct или enum не меняет его макет данных: он имеет такой же макет внутри другого типа, как и автономный, что позволяет вам брать ссылкиструктурировать элементы и использовать их взаимозаменяемо с любой другой ссылкой. *

Нет способа поместить два A в один байт, удовлетворяя этому ограничению, потому что размер A равен одному целому байту -Вы не можете адресовать часть байта, даже с repr(packed).Неиспользованные биты просто остаются неиспользованными (если только они не могут быть переназначены для хранения тега enum путем заполнения ниши).

* Ну, repr(packed) может фактически сделать это неверным. Взятие ссылки на упакованное поле может привести к неопределенному поведению , даже в безопасном коде!

...