use cairo_lang_debug::debug::DebugWithDb;
use cairo_lang_filesystem::ids::CrateId;
pub use cairo_lang_filesystem::ids::UnstableSalsaId;
use cairo_lang_syntax::node::ast::TerminalIdentifierGreen;
use cairo_lang_syntax::node::db::SyntaxGroup;
use cairo_lang_syntax::node::helpers::{GetIdentifier, NameGreen};
use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
use cairo_lang_syntax::node::kind::SyntaxKind;
use cairo_lang_syntax::node::stable_ptr::SyntaxStablePtr;
use cairo_lang_syntax::node::{ast, Terminal, TypedSyntaxNode};
use cairo_lang_utils::{define_short_id, OptionFrom};
use salsa;
use smol_str::SmolStr;
use crate::db::DefsGroup;
use crate::diagnostic_utils::StableLocation;
pub trait LanguageElementId {
fn module_file_id(&self, db: &dyn DefsGroup) -> ModuleFileId;
fn untyped_stable_ptr(&self, db: &dyn DefsGroup) -> SyntaxStablePtrId;
fn parent_module(&self, db: &dyn DefsGroup) -> ModuleId {
self.module_file_id(db).0
}
fn file_index(&self, db: &dyn DefsGroup) -> FileIndex {
self.module_file_id(db).1
}
fn stable_location(&self, db: &dyn DefsGroup) -> StableLocation;
}
pub trait TopLevelLanguageElementId: LanguageElementId {
fn name(&self, db: &dyn DefsGroup) -> SmolStr;
fn full_path(&self, db: &dyn DefsGroup) -> String {
format!("{}::{}", self.parent_module(db).full_path(db), self.name(db))
}
}
macro_rules! define_language_element_id {
($short_id:ident, $long_id:ident, $ast_ty:ty, $lookup:ident $(, $name:ident)?) => {
define_language_element_id_partial!($short_id, $long_id, $ast_ty, $lookup $(, $name)?);
impl_top_level_language_element_id!($short_id, $lookup $(, $name)?);
};
}
macro_rules! define_language_element_id_partial {
($short_id:ident, $long_id:ident, $ast_ty:ty, $lookup:ident $(,$name:ident)?) => {
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct $long_id(pub ModuleFileId, pub <$ast_ty as TypedSyntaxNode>::StablePtr);
$(
impl $long_id {
pub fn $name(&self, db: &dyn DefsGroup) -> SmolStr {
let syntax_db = db.upcast();
let terminal_green = self.1.name_green(syntax_db);
terminal_green.identifier(syntax_db)
}
}
impl<'a, T: ?Sized + cairo_lang_utils::Upcast<dyn DefsGroup + 'a>> cairo_lang_debug::DebugWithDb<T>
for $long_id
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &T) -> std::fmt::Result {
let db: &(dyn DefsGroup + 'a) = db.upcast();
let $long_id(module_file_id, _stable_ptr) = self;
write!(
f,
"{}({}::{})",
stringify!($short_id),
module_file_id.0.full_path(db),
self.name(db)
)
}
}
)?
define_short_id!($short_id, $long_id, DefsGroup, $lookup);
impl $short_id {
pub fn stable_ptr(self, db: &dyn DefsGroup) -> <$ast_ty as TypedSyntaxNode>::StablePtr {
db.$lookup(self).1
}
$(
pub fn $name(&self, db: &dyn DefsGroup) -> SmolStr {
db.$lookup(*self).name(db)
}
)?
}
impl LanguageElementId for $short_id {
fn module_file_id(&self, db: &dyn DefsGroup) -> ModuleFileId {
db.$lookup(*self).0
}
fn untyped_stable_ptr(&self, db: &dyn DefsGroup) -> SyntaxStablePtrId {
self.stable_ptr(db).untyped()
}
fn stable_location(&self, db: &dyn DefsGroup) -> StableLocation {
let $long_id(module_file_id, stable_ptr) = db.$lookup(*self);
StableLocation { module_file_id, stable_ptr: stable_ptr.untyped() }
}
}
};
}
macro_rules! impl_top_level_language_element_id {
($short_id:ident, $lookup:ident $(,$name:ident)?) => {
$(
impl TopLevelLanguageElementId for $short_id {
fn $name(&self, db: &dyn DefsGroup) -> SmolStr {
db.$lookup(*self).name(db)
}
}
)?
};
}
macro_rules! define_language_element_id_as_enum {
(
#[toplevel]
$(#[doc = $doc:expr])*
pub enum $enum_name:ident {
$($variant:ident ($variant_ty:ty),)*
}
) => {
toplevel_enum! {
pub enum $enum_name {
$($variant($variant_ty),)*
}
}
define_language_element_id_as_enum! {
$(#[doc = $doc])*
pub enum $enum_name {
$($variant($variant_ty),)*
}
}
};
(
$(#[doc = $doc:expr])*
pub enum $enum_name:ident {
$($variant:ident ($variant_ty:ty),)*
}
) => {
$(#[doc = $doc])*
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum $enum_name {
$($variant($variant_ty),)*
}
impl<T: ?Sized + cairo_lang_utils::Upcast<dyn DefsGroup + 'static>> cairo_lang_debug::DebugWithDb<T>
for $enum_name
{
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
db: &T,
) -> std::fmt::Result {
let db : &(dyn DefsGroup + 'static) = db.upcast();
match self {
$(
$enum_name::$variant(id) => id.fmt(f, db),
)*
}
}
}
impl LanguageElementId for $enum_name {
fn module_file_id(&self, db: &dyn DefsGroup) -> ModuleFileId {
match self {
$(
$enum_name::$variant(id) => id.module_file_id(db),
)*
}
}
fn untyped_stable_ptr(&self, db: &dyn DefsGroup) -> SyntaxStablePtrId {
match self {
$(
$enum_name::$variant(id) => id.untyped_stable_ptr(db),
)*
}
}
fn stable_location(&self, db: &dyn DefsGroup) -> StableLocation {
match self {
$(
$enum_name::$variant(id) => id.stable_location(db),
)*
}
}
}
$(
impl OptionFrom<$enum_name> for $variant_ty {
fn option_from(other: $enum_name) -> Option<Self> {
if let $enum_name::$variant(id) = other {
Some(id)
} else {
None
}
}
}
)*
}
}
macro_rules! toplevel_enum {
(
pub enum $enum_name:ident {
$($variant:ident ($variant_ty:ty),)*
}
) => {
impl TopLevelLanguageElementId for $enum_name {
fn name(&self, db: &dyn DefsGroup) -> SmolStr {
match self {
$(
$enum_name::$variant(id) => id.name(db),
)*
}
}
}
}
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum ModuleId {
CrateRoot(CrateId),
Submodule(SubmoduleId),
}
impl ModuleId {
pub fn full_path(&self, db: &dyn DefsGroup) -> String {
match self {
ModuleId::CrateRoot(id) => db.lookup_intern_crate(*id).0.to_string(),
ModuleId::Submodule(id) => {
format!("{}::{}", id.parent_module(db).full_path(db), id.name(db))
}
}
}
pub fn owning_crate(&self, db: &dyn DefsGroup) -> CrateId {
match self {
ModuleId::CrateRoot(crate_id) => *crate_id,
ModuleId::Submodule(submodule) => submodule.parent_module(db).owning_crate(db),
}
}
}
impl DebugWithDb<dyn DefsGroup> for ModuleId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &dyn DefsGroup) -> std::fmt::Result {
write!(f, "ModuleId({})", self.full_path(db))
}
}
#[derive(Copy, Clone, Debug, Default, Hash, PartialEq, Eq)]
pub struct FileIndex(pub usize);
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub struct ModuleFileId(pub ModuleId, pub FileIndex);
define_language_element_id_as_enum! {
pub enum ModuleItemId {
Constant(ConstantId),
Submodule(SubmoduleId),
Use(UseId),
FreeFunction(FreeFunctionId),
Struct(StructId),
Enum(EnumId),
TypeAlias(TypeAliasId),
ImplAlias(ImplAliasId),
Trait(TraitId),
Impl(ImplDefId),
ExternType(ExternTypeId),
ExternFunction(ExternFunctionId),
}
}
define_language_element_id!(
SubmoduleId,
SubmoduleLongId,
ast::ItemModule,
lookup_intern_submodule,
name
);
impl UnstableSalsaId for SubmoduleId {
fn get_internal_id(&self) -> &salsa::InternId {
&self.0
}
}
define_language_element_id!(
ConstantId,
ConstantLongId,
ast::ItemConstant,
lookup_intern_constant,
name
);
define_language_element_id!(UseId, UseLongId, ast::UsePathLeaf, lookup_intern_use, name);
define_language_element_id!(
FreeFunctionId,
FreeFunctionLongId,
ast::FunctionWithBody,
lookup_intern_free_function,
name
);
impl UnstableSalsaId for FreeFunctionId {
fn get_internal_id(&self) -> &salsa::InternId {
&self.0
}
}
define_language_element_id!(ImplDefId, ImplDefLongId, ast::ItemImpl, lookup_intern_impl, name);
define_language_element_id_partial!(
ImplFunctionId,
ImplFunctionLongId,
ast::FunctionWithBody,
lookup_intern_impl_function,
name
);
impl ImplFunctionId {
pub fn impl_def_id(&self, db: &dyn DefsGroup) -> ImplDefId {
let ImplFunctionLongId(module_file_id, ptr) = db.lookup_intern_impl_function(*self);
let SyntaxStablePtr::Child { parent, .. } = db.lookup_intern_stable_ptr(ptr.untyped())
else {
panic!()
};
let SyntaxStablePtr::Child { parent, .. } = db.lookup_intern_stable_ptr(parent) else {
panic!()
};
let SyntaxStablePtr::Child { parent, .. } = db.lookup_intern_stable_ptr(parent) else {
panic!()
};
let impl_ptr = ast::ItemImplPtr(parent);
db.intern_impl(ImplDefLongId(module_file_id, impl_ptr))
}
}
impl UnstableSalsaId for ImplFunctionId {
fn get_internal_id(&self) -> &salsa::InternId {
&self.0
}
}
impl TopLevelLanguageElementId for ImplFunctionId {
fn full_path(&self, db: &dyn DefsGroup) -> String {
format!("{}::{}", self.impl_def_id(db).name(db), self.name(db))
}
fn name(&self, db: &dyn DefsGroup) -> SmolStr {
db.lookup_intern_impl_function(*self).name(db)
}
}
define_language_element_id_as_enum! {
pub enum FunctionWithBodyId {
Free(FreeFunctionId),
Impl(ImplFunctionId),
}
}
impl FunctionWithBodyId {
pub fn name(&self, db: &dyn DefsGroup) -> SmolStr {
match self {
FunctionWithBodyId::Free(free_function) => free_function.name(db),
FunctionWithBodyId::Impl(impl_function) => impl_function.name(db),
}
}
}
impl TopLevelLanguageElementId for FunctionWithBodyId {
fn name(&self, db: &dyn DefsGroup) -> SmolStr {
match self {
FunctionWithBodyId::Free(free_function_id) => {
db.lookup_intern_free_function(*free_function_id).name(db)
}
FunctionWithBodyId::Impl(impl_function_id) => {
db.lookup_intern_impl_function(*impl_function_id).name(db)
}
}
}
}
define_language_element_id!(
ExternFunctionId,
ExternFunctionLongId,
ast::ItemExternFunction,
lookup_intern_extern_function,
name
);
define_language_element_id!(StructId, StructLongId, ast::ItemStruct, lookup_intern_struct, name);
define_language_element_id!(EnumId, EnumLongId, ast::ItemEnum, lookup_intern_enum, name);
define_language_element_id!(
TypeAliasId,
TypeAliasLongId,
ast::ItemTypeAlias,
lookup_intern_type_alias,
name
);
define_language_element_id!(
ImplAliasId,
ImplAliasLongId,
ast::ItemImplAlias,
lookup_intern_impl_alias,
name
);
define_language_element_id!(
ExternTypeId,
ExternTypeLongId,
ast::ItemExternType,
lookup_intern_extern_type,
name
);
define_language_element_id!(TraitId, TraitLongId, ast::ItemTrait, lookup_intern_trait, name);
define_language_element_id_partial!(
TraitFunctionId,
TraitFunctionLongId,
ast::TraitItemFunction,
lookup_intern_trait_function,
name
);
impl TraitFunctionId {
pub fn trait_id(&self, db: &dyn DefsGroup) -> TraitId {
let TraitFunctionLongId(module_file_id, ptr) = db.lookup_intern_trait_function(*self);
let SyntaxStablePtr::Child { parent, .. } = db.lookup_intern_stable_ptr(ptr.untyped())
else {
panic!()
};
let SyntaxStablePtr::Child { parent, .. } = db.lookup_intern_stable_ptr(parent) else {
panic!()
};
let SyntaxStablePtr::Child { parent, .. } = db.lookup_intern_stable_ptr(parent) else {
panic!()
};
let trait_ptr = ast::ItemTraitPtr(parent);
db.intern_trait(TraitLongId(module_file_id, trait_ptr))
}
}
impl TopLevelLanguageElementId for TraitFunctionId {
fn full_path(&self, db: &dyn DefsGroup) -> String {
format!("{}::{}", self.trait_id(db).name(db), self.name(db))
}
fn name(&self, db: &dyn DefsGroup) -> SmolStr {
db.lookup_intern_trait_function(*self).name(db)
}
}
define_language_element_id!(MemberId, MemberLongId, ast::Member, lookup_intern_member, name);
define_language_element_id!(VariantId, VariantLongId, ast::Variant, lookup_intern_variant, name);
define_language_element_id_as_enum! {
pub enum VarId {
Param(ParamId),
Local(LocalVarId),
}
}
define_language_element_id!(ParamId, ParamLongId, ast::Param, lookup_intern_param, name);
define_language_element_id!(
GenericParamId,
GenericParamLongId,
ast::GenericParam,
lookup_intern_generic_param
);
impl GenericParamLongId {
pub fn name(&self, db: &dyn SyntaxGroup) -> SmolStr {
let SyntaxStablePtr::Child { key_fields, .. } = db.lookup_intern_stable_ptr(self.1.0)
else {
unreachable!()
};
let name_green = TerminalIdentifierGreen(key_fields[0]);
name_green.identifier(db)
}
pub fn kind(&self, db: &dyn SyntaxGroup) -> GenericKind {
let SyntaxStablePtr::Child { kind, .. } = db.lookup_intern_stable_ptr(self.1.0) else {
unreachable!()
};
match kind {
SyntaxKind::GenericParamType => GenericKind::Type,
SyntaxKind::GenericParamConst => GenericKind::Const,
SyntaxKind::GenericParamImpl => GenericKind::Impl,
_ => unreachable!(),
}
}
pub fn generic_item(&self, db: &dyn DefsGroup) -> GenericItemId {
let SyntaxStablePtr::Child { parent, .. } = db.lookup_intern_stable_ptr(self.1.0) else {
panic!()
};
let SyntaxStablePtr::Child { parent, .. } = db.lookup_intern_stable_ptr(parent) else {
panic!()
};
let SyntaxStablePtr::Child { parent, .. } = db.lookup_intern_stable_ptr(parent) else {
panic!()
};
GenericItemId::from_ptr(db, self.0, parent)
}
}
impl GenericParamId {
pub fn name(&self, db: &dyn DefsGroup) -> SmolStr {
db.lookup_intern_generic_param(*self).name(db.upcast())
}
pub fn kind(&self, db: &dyn DefsGroup) -> GenericKind {
db.lookup_intern_generic_param(*self).kind(db.upcast())
}
pub fn generic_item(&self, db: &dyn DefsGroup) -> GenericItemId {
db.lookup_intern_generic_param(*self).generic_item(db.upcast())
}
}
impl DebugWithDb<dyn DefsGroup> for GenericParamLongId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &dyn DefsGroup) -> std::fmt::Result {
write!(
f,
"GenericParam{}({}::{})",
self.kind(db.upcast()),
self.generic_item(db).full_path(db),
self.name(db.upcast())
)
}
}
define_language_element_id_as_enum! {
#[toplevel]
pub enum GenericItemId {
FreeFunc(FreeFunctionId),
ExternFunc(ExternFunctionId),
TraitFunc(TraitFunctionId),
ImplFunc(ImplFunctionId),
Trait(TraitId),
Impl(ImplDefId),
Struct(StructId),
Enum(EnumId),
ExternType(ExternTypeId),
TypeAlias(TypeAliasId),
ImplAlias(ImplAliasId),
}
}
impl GenericItemId {
pub fn from_ptr(
db: &dyn DefsGroup,
module_file: ModuleFileId,
stable_ptr: SyntaxStablePtrId,
) -> Self {
let SyntaxStablePtr::Child { parent: parent0, kind, .. } =
db.lookup_intern_stable_ptr(stable_ptr)
else {
panic!()
};
match kind {
SyntaxKind::FunctionDeclaration => {
let SyntaxStablePtr::Child { parent: parent1, kind, .. } =
db.lookup_intern_stable_ptr(parent0)
else {
panic!()
};
match kind {
SyntaxKind::FunctionWithBody => {
let SyntaxStablePtr::Child { parent: parent2, .. } =
db.lookup_intern_stable_ptr(parent1)
else {
panic!()
};
match db.lookup_intern_stable_ptr(parent2) {
SyntaxStablePtr::Root => GenericItemId::FreeFunc(
db.intern_free_function(FreeFunctionLongId(
module_file,
ast::FunctionWithBodyPtr(parent0),
)),
),
SyntaxStablePtr::Child { kind, .. } => match kind {
SyntaxKind::ModuleBody => GenericItemId::FreeFunc(
db.intern_free_function(FreeFunctionLongId(
module_file,
ast::FunctionWithBodyPtr(parent0),
)),
),
SyntaxKind::ImplBody => GenericItemId::ImplFunc(
db.intern_impl_function(ImplFunctionLongId(
module_file,
ast::FunctionWithBodyPtr(parent0),
)),
),
_ => panic!(),
},
}
}
SyntaxKind::ItemExternFunction => {
GenericItemId::ExternFunc(db.intern_extern_function(ExternFunctionLongId(
module_file,
ast::ItemExternFunctionPtr(parent0),
)))
}
SyntaxKind::TraitItemFunction => {
GenericItemId::TraitFunc(db.intern_trait_function(TraitFunctionLongId(
module_file,
ast::TraitItemFunctionPtr(parent0),
)))
}
_ => panic!(),
}
}
SyntaxKind::ItemImpl => GenericItemId::Impl(
db.intern_impl(ImplDefLongId(module_file, ast::ItemImplPtr(stable_ptr))),
),
SyntaxKind::ItemTrait => GenericItemId::Trait(
db.intern_trait(TraitLongId(module_file, ast::ItemTraitPtr(stable_ptr))),
),
SyntaxKind::ItemStruct => GenericItemId::Struct(
db.intern_struct(StructLongId(module_file, ast::ItemStructPtr(stable_ptr))),
),
SyntaxKind::ItemEnum => GenericItemId::Enum(
db.intern_enum(EnumLongId(module_file, ast::ItemEnumPtr(stable_ptr))),
),
SyntaxKind::ItemExternType => GenericItemId::ExternType(db.intern_extern_type(
ExternTypeLongId(module_file, ast::ItemExternTypePtr(stable_ptr)),
)),
SyntaxKind::ItemTypeAlias => GenericItemId::TypeAlias(db.intern_type_alias(
TypeAliasLongId(module_file, ast::ItemTypeAliasPtr(stable_ptr)),
)),
SyntaxKind::ItemImplAlias => GenericItemId::ImplAlias(db.intern_impl_alias(
ImplAliasLongId(module_file, ast::ItemImplAliasPtr(stable_ptr)),
)),
_ => panic!(),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum GenericKind {
Type,
Const,
Impl,
}
impl std::fmt::Display for GenericKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
GenericKind::Type => write!(f, "Type"),
GenericKind::Const => write!(f, "Const"),
GenericKind::Impl => write!(f, "Impl"),
}
}
}
define_language_element_id!(
LocalVarId,
LocalVarLongId,
ast::TerminalIdentifier,
lookup_intern_local_var
);
impl DebugWithDb<dyn DefsGroup> for LocalVarLongId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &dyn DefsGroup) -> std::fmt::Result {
let syntax_db = db.upcast();
let LocalVarLongId(module_file_id, ptr) = self;
let file_id = db.module_file(*module_file_id).map_err(|_| std::fmt::Error)?;
let root = db.file_syntax(file_id).map_err(|_| std::fmt::Error)?;
let text = ast::TerminalIdentifier::from_ptr(syntax_db, &root, *ptr).text(syntax_db);
write!(f, "LocalVarId({}::{})", module_file_id.0.full_path(db), text)
}
}
define_language_element_id_as_enum! {
#[toplevel]
pub enum FunctionTitleId {
Free(FreeFunctionId),
Extern(ExternFunctionId),
Trait(TraitFunctionId),
Impl(ImplFunctionId),
}
}
impl FunctionTitleId {
pub fn format(&self, db: &dyn DefsGroup) -> String {
let function_name = match *self {
FunctionTitleId::Free(_) | FunctionTitleId::Extern(_) => self.name(db).into(),
FunctionTitleId::Trait(id) => id.full_path(db),
FunctionTitleId::Impl(id) => id.full_path(db),
};
format!("{}::{}", self.parent_module(db).full_path(db), function_name)
}
}
define_language_element_id_as_enum! {
#[toplevel]
pub enum GenericTypeId {
Struct(StructId),
Enum(EnumId),
Extern(ExternTypeId),
}
}
impl GenericTypeId {
pub fn format(&self, db: &dyn DefsGroup) -> String {
format!("{}::{}", self.parent_module(db).full_path(db), self.name(db))
}
}
impl OptionFrom<ModuleItemId> for GenericTypeId {
fn option_from(item: ModuleItemId) -> Option<Self> {
match item {
ModuleItemId::Struct(id) => Some(GenericTypeId::Struct(id)),
ModuleItemId::Enum(id) => Some(GenericTypeId::Enum(id)),
ModuleItemId::ExternType(id) => Some(GenericTypeId::Extern(id)),
ModuleItemId::Constant(_)
| ModuleItemId::Submodule(_)
| ModuleItemId::TypeAlias(_)
| ModuleItemId::ImplAlias(_)
| ModuleItemId::Use(_)
| ModuleItemId::FreeFunction(_)
| ModuleItemId::Trait(_)
| ModuleItemId::Impl(_)
| ModuleItemId::ExternFunction(_) => None,
}
}
}
impl From<GenericItemId> for LookupItemId {
fn from(item: GenericItemId) -> Self {
match item {
GenericItemId::FreeFunc(id) => LookupItemId::ModuleItem(ModuleItemId::FreeFunction(id)),
GenericItemId::ExternFunc(id) => {
LookupItemId::ModuleItem(ModuleItemId::ExternFunction(id))
}
GenericItemId::TraitFunc(id) => LookupItemId::TraitFunction(id),
GenericItemId::ImplFunc(id) => LookupItemId::ImplFunction(id),
GenericItemId::Trait(id) => LookupItemId::ModuleItem(ModuleItemId::Trait(id)),
GenericItemId::Impl(id) => LookupItemId::ModuleItem(ModuleItemId::Impl(id)),
GenericItemId::Struct(id) => LookupItemId::ModuleItem(ModuleItemId::Struct(id)),
GenericItemId::Enum(id) => LookupItemId::ModuleItem(ModuleItemId::Enum(id)),
GenericItemId::ExternType(id) => LookupItemId::ModuleItem(ModuleItemId::ExternType(id)),
GenericItemId::TypeAlias(id) => LookupItemId::ModuleItem(ModuleItemId::TypeAlias(id)),
GenericItemId::ImplAlias(id) => LookupItemId::ModuleItem(ModuleItemId::ImplAlias(id)),
}
}
}
define_language_element_id_as_enum! {
pub enum LookupItemId {
ModuleItem(ModuleItemId),
ImplFunction(ImplFunctionId),
TraitFunction(TraitFunctionId),
}
}