Add a macro for defaulted enum encoding, use it for hir::Defaultness and deduplicate the logic for other similar enums

This commit is contained in:
Oli Scherer 2025-11-19 16:02:12 +00:00
parent c489b92845
commit b93f2d8b26
4 changed files with 68 additions and 99 deletions

View file

@ -3841,8 +3841,12 @@ impl IsAsync {
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
#[derive(Default)]
pub enum Defaultness {
Default { has_value: bool },
Default {
has_value: bool,
},
#[default]
Final,
}
@ -4231,8 +4235,8 @@ impl fmt::Display for Safety {
#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
#[derive(Default)]
pub enum Constness {
Const,
#[default]
Const,
NotConst,
}

View file

@ -1753,7 +1753,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let item = tcx.associated_item(def_id);
if matches!(item.container, AssocContainer::Trait | AssocContainer::TraitImpl(_)) {
self.tables.defaultness.set_some(def_id.index, item.defaultness(tcx));
self.tables.defaultness.set(def_id.index, item.defaultness(tcx));
}
record!(self.tables.assoc_container[def_id] <- item.container);
@ -2155,7 +2155,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let header = tcx.impl_trait_header(def_id);
record!(self.tables.impl_trait_header[def_id] <- header);
self.tables.defaultness.set_some(def_id.index, tcx.defaultness(def_id));
self.tables.defaultness.set(def_id.index, tcx.defaultness(def_id));
let trait_ref = header.trait_ref.instantiate_identity();
let simplified_self_ty = fast_reject::simplify_type(

View file

@ -403,6 +403,7 @@ define_tables! {
asyncness: Table<DefIndex, ty::Asyncness>,
constness: Table<DefIndex, hir::Constness>,
safety: Table<DefIndex, hir::Safety>,
defaultness: Table<DefIndex, hir::Defaultness>,
- optional:
attributes: Table<DefIndex, LazyArray<hir::Attribute>>,
@ -436,7 +437,6 @@ define_tables! {
thir_abstract_const: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, ty::Const<'static>>>>,
impl_parent: Table<DefIndex, RawDefId>,
const_conditions: Table<DefIndex, LazyValue<ty::ConstConditions<'static>>>,
defaultness: Table<DefIndex, hir::Defaultness>,
// FIXME(eddyb) perhaps compute this on the fly if cheap enough?
coerce_unsized_info: Table<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>,
mir_const_qualif: Table<DefIndex, LazyValue<mir::ConstQualifs>>,

View file

@ -25,33 +25,6 @@ impl IsDefault for bool {
}
}
impl IsDefault for ty::Asyncness {
fn is_default(&self) -> bool {
match self {
ty::Asyncness::Yes => false,
ty::Asyncness::No => true,
}
}
}
impl IsDefault for hir::Constness {
fn is_default(&self) -> bool {
match self {
hir::Constness::Const => false,
hir::Constness::NotConst => true,
}
}
}
impl IsDefault for hir::Safety {
fn is_default(&self) -> bool {
match self {
hir::Safety::Safe => false,
hir::Safety::Unsafe => true,
}
}
}
impl IsDefault for u32 {
fn is_default(&self) -> bool {
*self == 0
@ -139,6 +112,43 @@ macro_rules! fixed_size_enum {
}
}
macro_rules! defaulted_enum {
($ty:ty { $(($($pat:tt)*))* } $( unreachable { $(($($upat:tt)*))+ } )?) => {
impl FixedSizeEncoding for $ty {
type ByteArray = [u8; 1];
#[inline]
fn from_bytes(b: &[u8; 1]) -> Self {
use $ty::*;
let val = match b[0] {
$(${index()} => $($pat)*,)*
_ => panic!("Unexpected {} code: {:?}", stringify!($ty), b[0]),
};
// Make sure the first entry is always the default value,
// and none of the other values are the default value
debug_assert_ne!((b[0] != 0), IsDefault::is_default(&val));
val
}
#[inline]
fn write_to_bytes(self, b: &mut [u8; 1]) {
debug_assert!(!IsDefault::is_default(&self));
use $ty::*;
b[0] = match self {
$($($pat)* => ${index()},)*
$($($($upat)*)|+ => unreachable!(),)?
};
debug_assert_ne!(b[0], 0);
}
}
impl IsDefault for $ty {
fn is_default(&self) -> bool {
<$ty as Default>::default() == *self
}
}
}
}
// Workaround; need const traits to construct bitflags in a const
macro_rules! const_macro_kinds {
($($name:ident),+$(,)?) => (MacroKinds::from_bits_truncate($(MacroKinds::$name.bits())|+))
@ -205,7 +215,7 @@ fixed_size_enum! {
}
}
fixed_size_enum! {
defaulted_enum! {
hir::Defaultness {
( Final )
( Default { has_value: false } )
@ -213,6 +223,27 @@ fixed_size_enum! {
}
}
defaulted_enum! {
ty::Asyncness {
( No )
( Yes )
}
}
defaulted_enum! {
hir::Constness {
( Const )
( NotConst )
}
}
defaulted_enum! {
hir::Safety {
( Unsafe )
( Safe )
}
}
fixed_size_enum! {
hir::CoroutineKind {
( Coroutine(hir::Movability::Movable) )
@ -301,72 +332,6 @@ impl FixedSizeEncoding for bool {
}
}
impl FixedSizeEncoding for ty::Asyncness {
type ByteArray = [u8; 1];
#[inline]
fn from_bytes(b: &[u8; 1]) -> Self {
match b[0] {
0 => ty::Asyncness::No,
1 => ty::Asyncness::Yes,
_ => unreachable!(),
}
}
#[inline]
fn write_to_bytes(self, b: &mut [u8; 1]) {
debug_assert!(!self.is_default());
b[0] = match self {
ty::Asyncness::No => 0,
ty::Asyncness::Yes => 1,
}
}
}
impl FixedSizeEncoding for hir::Constness {
type ByteArray = [u8; 1];
#[inline]
fn from_bytes(b: &[u8; 1]) -> Self {
match b[0] {
0 => hir::Constness::NotConst,
1 => hir::Constness::Const,
_ => unreachable!(),
}
}
#[inline]
fn write_to_bytes(self, b: &mut [u8; 1]) {
debug_assert!(!self.is_default());
b[0] = match self {
hir::Constness::NotConst => 0,
hir::Constness::Const => 1,
}
}
}
impl FixedSizeEncoding for hir::Safety {
type ByteArray = [u8; 1];
#[inline]
fn from_bytes(b: &[u8; 1]) -> Self {
match b[0] {
0 => hir::Safety::Unsafe,
1 => hir::Safety::Safe,
_ => unreachable!(),
}
}
#[inline]
fn write_to_bytes(self, b: &mut [u8; 1]) {
debug_assert!(!self.is_default());
b[0] = match self {
hir::Safety::Unsafe => 0,
hir::Safety::Safe => 1,
}
}
}
// NOTE(eddyb) there could be an impl for `usize`, which would enable a more
// generic `LazyValue<T>` impl, but in the general case we might not need / want
// to fit every `usize` in `u32`.