use std::fmt::Debug;
use crate::{
common::{HasNodeId, ItemId, SpanId},
context::with_cx,
diagnostic::EmissionNode,
ffi::FfiOption,
private::Sealed,
span::{HasSpan, Ident, Span},
CtorBlocker,
};
use super::expr::ExprKind;
mod extern_crate_item;
pub use self::extern_crate_item::ExternCrateItem;
mod mod_item;
pub use mod_item::ModItem;
mod static_item;
pub use self::static_item::StaticItem;
mod use_item;
pub use self::use_item::*;
mod const_item;
pub use self::const_item::ConstItem;
mod fn_item;
pub use fn_item::*;
mod ty_alias_item;
pub use ty_alias_item::*;
mod adt_item;
pub use adt_item::*;
mod trait_item;
pub use trait_item::*;
mod impl_item;
pub use impl_item::*;
mod extern_block_item;
pub use extern_block_item::*;
mod unstable_item;
pub use unstable_item::*;
pub trait ItemData<'ast>: Debug + EmissionNode<'ast> + HasSpan<'ast> + HasNodeId + Sealed {
fn id(&self) -> ItemId;
fn visibility(&self) -> &Visibility<'ast>;
fn ident(&self) -> Option<&Ident<'ast>>;
fn as_item(&'ast self) -> ItemKind<'ast>;
fn attrs(&self); }
#[repr(C)]
#[non_exhaustive]
#[derive(Debug, Copy, Clone)]
pub enum ItemKind<'ast> {
Mod(&'ast ModItem<'ast>),
ExternCrate(&'ast ExternCrateItem<'ast>),
Use(&'ast UseItem<'ast>),
Static(&'ast StaticItem<'ast>),
Const(&'ast ConstItem<'ast>),
Fn(&'ast FnItem<'ast>),
TyAlias(&'ast TyAliasItem<'ast>),
Struct(&'ast StructItem<'ast>),
Enum(&'ast EnumItem<'ast>),
Union(&'ast UnionItem<'ast>),
Trait(&'ast TraitItem<'ast>),
Impl(&'ast ImplItem<'ast>),
ExternBlock(&'ast ExternBlockItem<'ast>),
Unstable(&'ast UnstableItem<'ast>),
}
impl<'ast> ItemKind<'ast> {
impl_item_type_fn!(ItemKind: id() -> ItemId);
impl_item_type_fn!(ItemKind: span() -> &Span<'ast>);
impl_item_type_fn!(ItemKind: visibility() -> &Visibility<'ast>);
impl_item_type_fn!(ItemKind: ident() -> Option<&Ident<'ast>>);
impl_item_type_fn!(ItemKind: attrs() -> ());
}
crate::span::impl_spanned_for!(ItemKind<'ast>);
crate::common::impl_identifiable_for!(ItemKind<'ast>);
#[non_exhaustive]
#[derive(Debug, Copy, Clone)]
pub enum AssocItemKind<'ast> {
TyAlias(&'ast TyAliasItem<'ast>, CtorBlocker),
Const(&'ast ConstItem<'ast>, CtorBlocker),
Fn(&'ast FnItem<'ast>, CtorBlocker),
}
impl<'ast> AssocItemKind<'ast> {
impl_item_type_fn!(AssocItemKind: id() -> ItemId);
impl_item_type_fn!(AssocItemKind: span() -> &Span<'ast>);
impl_item_type_fn!(AssocItemKind: visibility() -> &Visibility<'ast>);
impl_item_type_fn!(AssocItemKind: ident() -> Option<&Ident<'ast>>);
impl_item_type_fn!(AssocItemKind: attrs() -> ());
impl_item_type_fn!(AssocItemKind: as_item() -> ItemKind<'ast>);
}
crate::span::impl_spanned_for!(AssocItemKind<'ast>);
crate::common::impl_identifiable_for!(AssocItemKind<'ast>);
impl<'ast> From<AssocItemKind<'ast>> for ItemKind<'ast> {
fn from(value: AssocItemKind<'ast>) -> Self {
match value {
AssocItemKind::TyAlias(item, ..) => ItemKind::TyAlias(item),
AssocItemKind::Const(item, ..) => ItemKind::Const(item),
AssocItemKind::Fn(item, ..) => ItemKind::Fn(item),
}
}
}
#[non_exhaustive]
#[derive(Debug, Copy, Clone)]
pub enum ExternItemKind<'ast> {
Static(&'ast StaticItem<'ast>, CtorBlocker),
Fn(&'ast FnItem<'ast>, CtorBlocker),
}
impl<'ast> ExternItemKind<'ast> {
impl_item_type_fn!(ExternItemKind: id() -> ItemId);
impl_item_type_fn!(ExternItemKind: span() -> &Span<'ast>);
impl_item_type_fn!(ExternItemKind: visibility() -> &Visibility<'ast>);
impl_item_type_fn!(ExternItemKind: ident() -> Option<&Ident<'ast>>);
impl_item_type_fn!(ExternItemKind: attrs() -> ());
impl_item_type_fn!(ExternItemKind: as_item() -> ItemKind<'ast>);
}
crate::span::impl_spanned_for!(ExternItemKind<'ast>);
crate::common::impl_identifiable_for!(ExternItemKind<'ast>);
impl<'ast> From<ExternItemKind<'ast>> for ItemKind<'ast> {
fn from(value: ExternItemKind<'ast>) -> Self {
match value {
ExternItemKind::Static(item, ..) => ItemKind::Static(item),
ExternItemKind::Fn(item, ..) => ItemKind::Fn(item),
}
}
}
macro_rules! impl_item_type_fn {
(ItemKind: $method:ident () -> $return_ty:ty) => {
impl_item_type_fn!((ItemKind) $method() -> $return_ty,
Mod, ExternCrate, Use, Static, Const, Fn, TyAlias, Struct, Enum,
Union, Trait, Impl, ExternBlock, Unstable
);
};
(AssocItemKind: $method:ident () -> $return_ty:ty) => {
impl_item_type_fn!((AssocItemKind) $method() -> $return_ty,
TyAlias, Const, Fn
);
};
(ExternItemKind: $method:ident () -> $return_ty:ty) => {
impl_item_type_fn!((ExternItemKind) $method() -> $return_ty,
Static, Fn
);
};
(($self:ident) $method:ident () -> $return_ty:ty $(, $item:ident)+) => {
pub fn $method(&self) -> $return_ty {
match self {
$($self::$item(data, ..) => data.$method(),)*
}
}
};
}
use impl_item_type_fn;
#[repr(C)]
#[derive(Debug)]
#[cfg_attr(feature = "driver-api", visibility::make(pub))]
#[cfg_attr(feature = "driver-api", derive(typed_builder::TypedBuilder))]
struct CommonItemData<'ast> {
id: ItemId,
span: SpanId,
vis: Visibility<'ast>,
ident: Ident<'ast>,
}
macro_rules! impl_item_data {
($self_name:ident, $enum_name:ident) => {
impl<'ast> super::ItemData<'ast> for $self_name<'ast> {
fn id(&self) -> crate::ast::item::ItemId {
self.data.id
}
fn visibility(&self) -> &crate::ast::item::Visibility<'ast> {
&self.data.vis
}
fn ident(&self) -> Option<&crate::span::Ident<'ast>> {
Some(&self.data.ident)
}
fn as_item(&'ast self) -> crate::ast::item::ItemKind<'ast> {
$crate::ast::item::ItemKind::$enum_name(self)
}
fn attrs(&self) {}
}
impl<'ast> $crate::span::HasSpan<'ast> for $self_name<'ast> {
fn span(&self) -> &crate::span::Span<'ast> {
$crate::context::with_cx(self, |cx| cx.span(self.data.span))
}
}
$crate::common::impl_identifiable_for!($self_name<'ast>, use $crate::ast::item::ItemData);
impl $crate::private::Sealed for $self_name<'_> {}
impl<'ast> From<&'ast $self_name<'ast>> for crate::ast::item::ItemKind<'ast> {
fn from(value: &'ast $self_name<'ast>) -> Self {
$crate::ast::item::ItemKind::$enum_name(value)
}
}
};
}
use impl_item_data;
#[repr(C)]
#[derive(Debug)]
#[cfg_attr(feature = "driver-api", derive(typed_builder::TypedBuilder))]
pub struct Visibility<'ast> {
#[cfg_attr(feature = "driver-api", builder(setter(into), default))]
span: FfiOption<SpanId>,
sem: crate::sem::Visibility<'ast>,
}
impl<'ast> Visibility<'ast> {
pub fn span(&self) -> Option<&Span<'ast>> {
self.span.copy().map(|span| with_cx(self, |cx| cx.span(span)))
}
pub fn semantics(&self) -> &crate::sem::Visibility<'ast> {
&self.sem
}
}
#[repr(C)]
#[derive(Debug)]
pub struct Body<'ast> {
owner: ItemId,
expr: ExprKind<'ast>,
}
impl<'ast> Body<'ast> {
pub fn owner(&self) -> ItemId {
self.owner
}
pub fn expr(&self) -> ExprKind<'ast> {
self.expr
}
}
#[cfg(feature = "driver-api")]
impl<'ast> Body<'ast> {
pub fn new(owner: ItemId, expr: ExprKind<'ast>) -> Self {
Self { owner, expr }
}
}
#[cfg(all(test, target_arch = "x86_64", target_pointer_width = "64"))]
mod test {
use crate::test::assert_size_of;
use super::*;
use expect_test::expect;
#[test]
fn test_item_struct_size() {
assert_size_of::<ModItem<'_>>(&expect!["80"]);
assert_size_of::<ExternCrateItem<'_>>(&expect!["72"]);
assert_size_of::<UseItem<'_>>(&expect!["88"]);
assert_size_of::<StaticItem<'_>>(&expect!["104"]);
assert_size_of::<ConstItem<'_>>(&expect!["96"]);
assert_size_of::<FnItem<'_>>(&expect!["168"]);
assert_size_of::<TyAliasItem<'_>>(&expect!["136"]);
assert_size_of::<StructItem<'_>>(&expect!["120"]);
assert_size_of::<EnumItem<'_>>(&expect!["112"]);
assert_size_of::<UnionItem<'_>>(&expect!["112"]);
assert_size_of::<TraitItem<'_>>(&expect!["136"]);
assert_size_of::<ImplItem<'_>>(&expect!["168"]);
assert_size_of::<ExternBlockItem<'_>>(&expect!["88"]);
assert_size_of::<UnstableItem<'_>>(&expect!["72"]);
}
}