Lower anonymous structs or unions to HIR

This commit is contained in:
Frank King 2024-01-04 21:53:06 +08:00
parent 084ce5bdb5
commit 879a1e5713
38 changed files with 288 additions and 174 deletions

View file

@ -756,6 +756,13 @@ impl<'hir> Map<'hir> {
}
}
pub fn expect_field(self, id: HirId) -> &'hir FieldDef<'hir> {
match self.tcx.hir_node(id) {
Node::Field(field) => field,
_ => bug!("expected field, found {}", self.node_to_string(id)),
}
}
pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> {
match self.tcx.hir_owner_node(id) {
OwnerNode::ForeignItem(item) => item,

View file

@ -50,6 +50,8 @@ bitflags! {
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8;
/// Indicates whether the type is `UnsafeCell`.
const IS_UNSAFE_CELL = 1 << 9;
/// Indicates whether the type is anonymous.
const IS_ANONYMOUS = 1 << 10;
}
}
rustc_data_structures::external_bitflags_debug! { AdtFlags }
@ -233,8 +235,12 @@ impl AdtDefData {
kind: AdtKind,
variants: IndexVec<VariantIdx, VariantDef>,
repr: ReprOptions,
is_anonymous: bool,
) -> Self {
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
debug!(
"AdtDef::new({:?}, {:?}, {:?}, {:?}, {:?})",
did, kind, variants, repr, is_anonymous
);
let mut flags = AdtFlags::NO_ADT_FLAGS;
if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) {
@ -267,6 +273,9 @@ impl AdtDefData {
if Some(did) == tcx.lang_items().unsafe_cell_type() {
flags |= AdtFlags::IS_UNSAFE_CELL;
}
if is_anonymous {
flags |= AdtFlags::IS_ANONYMOUS;
}
AdtDefData { did, variants, flags, repr }
}
@ -365,6 +374,12 @@ impl<'tcx> AdtDef<'tcx> {
self.flags().contains(AdtFlags::IS_MANUALLY_DROP)
}
/// Returns `true` if this is an anonymous adt
#[inline]
pub fn is_anonymous(self) -> bool {
self.flags().contains(AdtFlags::IS_ANONYMOUS)
}
/// Returns `true` if this type has a destructor.
pub fn has_dtor(self, tcx: TyCtxt<'tcx>) -> bool {
self.destructor(tcx).is_some()

View file

@ -715,8 +715,16 @@ impl<'tcx> TyCtxt<'tcx> {
kind: AdtKind,
variants: IndexVec<VariantIdx, ty::VariantDef>,
repr: ReprOptions,
is_anonymous: bool,
) -> ty::AdtDef<'tcx> {
self.mk_adt_def_from_data(ty::AdtDefData::new(self, did, kind, variants, repr))
self.mk_adt_def_from_data(ty::AdtDefData::new(
self,
did,
kind,
variants,
repr,
is_anonymous,
))
}
/// Allocates a read-only byte or string literal for `mir::interpret`.

View file

@ -1130,6 +1130,8 @@ bitflags! {
/// Indicates whether this variant was obtained as part of recovering from
/// a syntactic error. May be incomplete or bogus.
const IS_RECOVERED = 1 << 1;
/// Indicates whether this variant has unnamed fields.
const HAS_UNNAMED_FIELDS = 1 << 2;
}
}
rustc_data_structures::external_bitflags_debug! { VariantFlags }
@ -1143,7 +1145,7 @@ pub struct VariantDef {
/// `DefId` that identifies the variant's constructor.
/// If this variant is a struct variant, then this is `None`.
pub ctor: Option<(CtorKind, DefId)>,
/// Variant or struct name.
/// Variant or struct name, maybe empty for anonymous adt (struct or union).
pub name: Symbol,
/// Discriminant of this variant.
pub discr: VariantDiscr,
@ -1180,11 +1182,12 @@ impl VariantDef {
parent_did: DefId,
recovered: bool,
is_field_list_non_exhaustive: bool,
has_unnamed_fields: bool,
) -> Self {
debug!(
"VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?},
fields = {:?}, adt_kind = {:?}, parent_did = {:?})",
name, variant_did, ctor, discr, fields, adt_kind, parent_did,
fields = {:?}, adt_kind = {:?}, parent_did = {:?}, has_unnamed_fields = {:?})",
name, variant_did, ctor, discr, fields, adt_kind, parent_did, has_unnamed_fields,
);
let mut flags = VariantFlags::NO_VARIANT_FLAGS;
@ -1196,6 +1199,10 @@ impl VariantDef {
flags |= VariantFlags::IS_RECOVERED;
}
if has_unnamed_fields {
flags |= VariantFlags::HAS_UNNAMED_FIELDS;
}
VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags }
}
@ -1211,6 +1218,12 @@ impl VariantDef {
self.flags.intersects(VariantFlags::IS_RECOVERED)
}
/// Does this variant contains unnamed fields
#[inline]
pub fn has_unnamed_fields(&self) -> bool {
self.flags.intersects(VariantFlags::HAS_UNNAMED_FIELDS)
}
/// Computes the `Ident` of this variant by looking up the `Span`
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())