Rust: expand derive macros

This commit is contained in:
Paolo Tranquilli
2025-06-20 11:19:06 +02:00
parent cdd6245b98
commit e935bd6faf
32 changed files with 2856 additions and 794 deletions

View File

@@ -1,2 +1,2 @@
mod.rs 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7
top.rs 69c1fcaf0efea87feb898f32fdb7bcb842a22119b69ecedd61c2d946eb7e67de 69c1fcaf0efea87feb898f32fdb7bcb842a22119b69ecedd61c2d946eb7e67de
top.rs 78da6fde6bc6f66baf63b298b3d565d6a057b54e891f739a3510aff4563a9f1b 78da6fde6bc6f66baf63b298b3d565d6a057b54e891f739a3510aff4563a9f1b

View File

@@ -335,9 +335,11 @@ impl Addressable {
pub fn emit_extended_canonical_path(id: trap::Label<Self>, value: String, out: &mut trap::Writer) {
out.add_tuple("addressable_extended_canonical_paths", vec![id.into(), value.into()]);
}
pub fn emit_crate_origin(id: trap::Label<Self>, value: String, out: &mut trap::Writer) {
out.add_tuple("addressable_crate_origins", vec![id.into(), value.into()]);
}
}
impl trap::TrapClass for Addressable {
@@ -2058,9 +2060,11 @@ impl PathSegment {
pub fn emit_type_repr(id: trap::Label<Self>, value: trap::Label<TypeRepr>, out: &mut trap::Writer) {
out.add_tuple("path_segment_type_reprs", vec![id.into(), value.into()]);
}
pub fn emit_trait_type_repr(id: trap::Label<Self>, value: trap::Label<PathTypeRepr>, out: &mut trap::Writer) {
out.add_tuple("path_segment_trait_type_reprs", vec![id.into(), value.into()]);
}
}
impl trap::TrapClass for PathSegment {
@@ -2153,9 +2157,11 @@ impl Resolvable {
pub fn emit_resolved_path(id: trap::Label<Self>, value: String, out: &mut trap::Writer) {
out.add_tuple("resolvable_resolved_paths", vec![id.into(), value.into()]);
}
pub fn emit_resolved_crate_origin(id: trap::Label<Self>, value: String, out: &mut trap::Writer) {
out.add_tuple("resolvable_resolved_crate_origins", vec![id.into(), value.into()]);
}
}
impl trap::TrapClass for Resolvable {
@@ -5764,6 +5770,7 @@ impl Item {
pub fn emit_attribute_macro_expansion(id: trap::Label<Self>, value: trap::Label<MacroItems>, out: &mut trap::Writer) {
out.add_tuple("item_attribute_macro_expansions", vec![id.into(), value.into()]);
}
}
impl trap::TrapClass for Item {
@@ -8865,6 +8872,82 @@ impl From<trap::Label<YieldExpr>> for trap::Label<Element> {
}
}
#[derive(Debug)]
pub struct Adt {
_unused: ()
}
impl Adt {
pub fn emit_derive_macro_expansion(id: trap::Label<Self>, i: usize, value: trap::Label<MacroItems>, out: &mut trap::Writer) {
out.add_tuple("adt_derive_macro_expansions", vec![id.into(), i.into(), value.into()]);
}
pub fn emit_derive_macro_expansions(id: trap::Label<Self>, values: impl IntoIterator<Item=trap::Label<MacroItems>>, out: &mut trap::Writer) {
values
.into_iter()
.enumerate()
.for_each(|(i, value)| Self::emit_derive_macro_expansion(id, i, value, out));
}
}
impl trap::TrapClass for Adt {
fn class_name() -> &'static str { "Adt" }
}
impl From<trap::Label<Adt>> for trap::Label<Item> {
fn from(value: trap::Label<Adt>) -> Self {
// SAFETY: this is safe because in the dbscheme Adt is a subclass of Item
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Adt>> for trap::Label<Stmt> {
fn from(value: trap::Label<Adt>) -> Self {
// SAFETY: this is safe because in the dbscheme Adt is a subclass of Stmt
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Adt>> for trap::Label<AstNode> {
fn from(value: trap::Label<Adt>) -> Self {
// SAFETY: this is safe because in the dbscheme Adt is a subclass of AstNode
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Adt>> for trap::Label<Locatable> {
fn from(value: trap::Label<Adt>) -> Self {
// SAFETY: this is safe because in the dbscheme Adt is a subclass of Locatable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Adt>> for trap::Label<Element> {
fn from(value: trap::Label<Adt>) -> Self {
// SAFETY: this is safe because in the dbscheme Adt is a subclass of Element
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Adt>> for trap::Label<Addressable> {
fn from(value: trap::Label<Adt>) -> Self {
// SAFETY: this is safe because in the dbscheme Adt is a subclass of Addressable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
#[derive(Debug)]
pub struct BlockExpr {
pub id: trap::TrapId<BlockExpr>,
@@ -9088,6 +9171,7 @@ impl Const {
pub fn emit_has_implementation(id: trap::Label<Self>, out: &mut trap::Writer) {
out.add_tuple("const_has_implementation", vec![id.into()]);
}
}
impl trap::TrapClass for Const {
@@ -9157,103 +9241,6 @@ impl From<trap::Label<Const>> for trap::Label<Addressable> {
}
}
#[derive(Debug)]
pub struct Enum {
pub id: trap::TrapId<Enum>,
pub attrs: Vec<trap::Label<Attr>>,
pub generic_param_list: Option<trap::Label<GenericParamList>>,
pub name: Option<trap::Label<Name>>,
pub variant_list: Option<trap::Label<VariantList>>,
pub visibility: Option<trap::Label<Visibility>>,
pub where_clause: Option<trap::Label<WhereClause>>,
}
impl trap::TrapEntry for Enum {
fn extract_id(&mut self) -> trap::TrapId<Self> {
std::mem::replace(&mut self.id, trap::TrapId::Star)
}
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
out.add_tuple("enums", vec![id.into()]);
for (i, v) in self.attrs.into_iter().enumerate() {
out.add_tuple("enum_attrs", vec![id.into(), i.into(), v.into()]);
}
if let Some(v) = self.generic_param_list {
out.add_tuple("enum_generic_param_lists", vec![id.into(), v.into()]);
}
if let Some(v) = self.name {
out.add_tuple("enum_names", vec![id.into(), v.into()]);
}
if let Some(v) = self.variant_list {
out.add_tuple("enum_variant_lists", vec![id.into(), v.into()]);
}
if let Some(v) = self.visibility {
out.add_tuple("enum_visibilities", vec![id.into(), v.into()]);
}
if let Some(v) = self.where_clause {
out.add_tuple("enum_where_clauses", vec![id.into(), v.into()]);
}
}
}
impl trap::TrapClass for Enum {
fn class_name() -> &'static str { "Enum" }
}
impl From<trap::Label<Enum>> for trap::Label<Item> {
fn from(value: trap::Label<Enum>) -> Self {
// SAFETY: this is safe because in the dbscheme Enum is a subclass of Item
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Enum>> for trap::Label<Stmt> {
fn from(value: trap::Label<Enum>) -> Self {
// SAFETY: this is safe because in the dbscheme Enum is a subclass of Stmt
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Enum>> for trap::Label<AstNode> {
fn from(value: trap::Label<Enum>) -> Self {
// SAFETY: this is safe because in the dbscheme Enum is a subclass of AstNode
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Enum>> for trap::Label<Locatable> {
fn from(value: trap::Label<Enum>) -> Self {
// SAFETY: this is safe because in the dbscheme Enum is a subclass of Locatable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Enum>> for trap::Label<Element> {
fn from(value: trap::Label<Enum>) -> Self {
// SAFETY: this is safe because in the dbscheme Enum is a subclass of Element
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Enum>> for trap::Label<Addressable> {
fn from(value: trap::Label<Enum>) -> Self {
// SAFETY: this is safe because in the dbscheme Enum is a subclass of Addressable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
#[derive(Debug)]
pub struct ExternBlock {
pub id: trap::TrapId<ExternBlock>,
@@ -9507,6 +9494,7 @@ impl Function {
pub fn emit_has_implementation(id: trap::Label<Self>, out: &mut trap::Writer) {
out.add_tuple("function_has_implementation", vec![id.into()]);
}
}
impl trap::TrapClass for Function {
@@ -9792,6 +9780,7 @@ impl MacroCall {
pub fn emit_macro_call_expansion(id: trap::Label<Self>, value: trap::Label<AstNode>, out: &mut trap::Writer) {
out.add_tuple("macro_call_macro_call_expansions", vec![id.into(), value.into()]);
}
}
impl trap::TrapClass for MacroCall {
@@ -10515,112 +10504,6 @@ impl From<trap::Label<Static>> for trap::Label<Addressable> {
}
}
#[derive(Debug)]
pub struct Struct {
pub id: trap::TrapId<Struct>,
pub attrs: Vec<trap::Label<Attr>>,
pub field_list: Option<trap::Label<FieldList>>,
pub generic_param_list: Option<trap::Label<GenericParamList>>,
pub name: Option<trap::Label<Name>>,
pub visibility: Option<trap::Label<Visibility>>,
pub where_clause: Option<trap::Label<WhereClause>>,
}
impl trap::TrapEntry for Struct {
fn extract_id(&mut self) -> trap::TrapId<Self> {
std::mem::replace(&mut self.id, trap::TrapId::Star)
}
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
out.add_tuple("structs", vec![id.into()]);
for (i, v) in self.attrs.into_iter().enumerate() {
out.add_tuple("struct_attrs", vec![id.into(), i.into(), v.into()]);
}
if let Some(v) = self.field_list {
out.add_tuple("struct_field_lists_", vec![id.into(), v.into()]);
}
if let Some(v) = self.generic_param_list {
out.add_tuple("struct_generic_param_lists", vec![id.into(), v.into()]);
}
if let Some(v) = self.name {
out.add_tuple("struct_names", vec![id.into(), v.into()]);
}
if let Some(v) = self.visibility {
out.add_tuple("struct_visibilities", vec![id.into(), v.into()]);
}
if let Some(v) = self.where_clause {
out.add_tuple("struct_where_clauses", vec![id.into(), v.into()]);
}
}
}
impl trap::TrapClass for Struct {
fn class_name() -> &'static str { "Struct" }
}
impl From<trap::Label<Struct>> for trap::Label<Item> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of Item
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Struct>> for trap::Label<Stmt> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of Stmt
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Struct>> for trap::Label<AstNode> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of AstNode
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Struct>> for trap::Label<Locatable> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of Locatable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Struct>> for trap::Label<Element> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of Element
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Struct>> for trap::Label<Addressable> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of Addressable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Struct>> for trap::Label<VariantDef> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of VariantDef
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
#[derive(Debug)]
pub struct StructExpr {
pub id: trap::TrapId<StructExpr>,
@@ -11193,112 +11076,6 @@ impl From<trap::Label<TypeAlias>> for trap::Label<Addressable> {
}
}
#[derive(Debug)]
pub struct Union {
pub id: trap::TrapId<Union>,
pub attrs: Vec<trap::Label<Attr>>,
pub generic_param_list: Option<trap::Label<GenericParamList>>,
pub name: Option<trap::Label<Name>>,
pub struct_field_list: Option<trap::Label<StructFieldList>>,
pub visibility: Option<trap::Label<Visibility>>,
pub where_clause: Option<trap::Label<WhereClause>>,
}
impl trap::TrapEntry for Union {
fn extract_id(&mut self) -> trap::TrapId<Self> {
std::mem::replace(&mut self.id, trap::TrapId::Star)
}
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
out.add_tuple("unions", vec![id.into()]);
for (i, v) in self.attrs.into_iter().enumerate() {
out.add_tuple("union_attrs", vec![id.into(), i.into(), v.into()]);
}
if let Some(v) = self.generic_param_list {
out.add_tuple("union_generic_param_lists", vec![id.into(), v.into()]);
}
if let Some(v) = self.name {
out.add_tuple("union_names", vec![id.into(), v.into()]);
}
if let Some(v) = self.struct_field_list {
out.add_tuple("union_struct_field_lists", vec![id.into(), v.into()]);
}
if let Some(v) = self.visibility {
out.add_tuple("union_visibilities", vec![id.into(), v.into()]);
}
if let Some(v) = self.where_clause {
out.add_tuple("union_where_clauses", vec![id.into(), v.into()]);
}
}
}
impl trap::TrapClass for Union {
fn class_name() -> &'static str { "Union" }
}
impl From<trap::Label<Union>> for trap::Label<Item> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of Item
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Union>> for trap::Label<Stmt> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of Stmt
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Union>> for trap::Label<AstNode> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of AstNode
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Union>> for trap::Label<Locatable> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of Locatable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Union>> for trap::Label<Element> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of Element
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Union>> for trap::Label<Addressable> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of Addressable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Union>> for trap::Label<VariantDef> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of VariantDef
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
#[derive(Debug)]
pub struct Use {
pub id: trap::TrapId<Use>,
@@ -11384,6 +11161,112 @@ impl From<trap::Label<Use>> for trap::Label<Addressable> {
}
}
#[derive(Debug)]
pub struct Enum {
pub id: trap::TrapId<Enum>,
pub attrs: Vec<trap::Label<Attr>>,
pub generic_param_list: Option<trap::Label<GenericParamList>>,
pub name: Option<trap::Label<Name>>,
pub variant_list: Option<trap::Label<VariantList>>,
pub visibility: Option<trap::Label<Visibility>>,
pub where_clause: Option<trap::Label<WhereClause>>,
}
impl trap::TrapEntry for Enum {
fn extract_id(&mut self) -> trap::TrapId<Self> {
std::mem::replace(&mut self.id, trap::TrapId::Star)
}
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
out.add_tuple("enums", vec![id.into()]);
for (i, v) in self.attrs.into_iter().enumerate() {
out.add_tuple("enum_attrs", vec![id.into(), i.into(), v.into()]);
}
if let Some(v) = self.generic_param_list {
out.add_tuple("enum_generic_param_lists", vec![id.into(), v.into()]);
}
if let Some(v) = self.name {
out.add_tuple("enum_names", vec![id.into(), v.into()]);
}
if let Some(v) = self.variant_list {
out.add_tuple("enum_variant_lists", vec![id.into(), v.into()]);
}
if let Some(v) = self.visibility {
out.add_tuple("enum_visibilities", vec![id.into(), v.into()]);
}
if let Some(v) = self.where_clause {
out.add_tuple("enum_where_clauses", vec![id.into(), v.into()]);
}
}
}
impl trap::TrapClass for Enum {
fn class_name() -> &'static str { "Enum" }
}
impl From<trap::Label<Enum>> for trap::Label<Adt> {
fn from(value: trap::Label<Enum>) -> Self {
// SAFETY: this is safe because in the dbscheme Enum is a subclass of Adt
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Enum>> for trap::Label<Item> {
fn from(value: trap::Label<Enum>) -> Self {
// SAFETY: this is safe because in the dbscheme Enum is a subclass of Item
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Enum>> for trap::Label<Stmt> {
fn from(value: trap::Label<Enum>) -> Self {
// SAFETY: this is safe because in the dbscheme Enum is a subclass of Stmt
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Enum>> for trap::Label<AstNode> {
fn from(value: trap::Label<Enum>) -> Self {
// SAFETY: this is safe because in the dbscheme Enum is a subclass of AstNode
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Enum>> for trap::Label<Locatable> {
fn from(value: trap::Label<Enum>) -> Self {
// SAFETY: this is safe because in the dbscheme Enum is a subclass of Locatable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Enum>> for trap::Label<Element> {
fn from(value: trap::Label<Enum>) -> Self {
// SAFETY: this is safe because in the dbscheme Enum is a subclass of Element
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Enum>> for trap::Label<Addressable> {
fn from(value: trap::Label<Enum>) -> Self {
// SAFETY: this is safe because in the dbscheme Enum is a subclass of Addressable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
#[derive(Debug)]
pub struct ForExpr {
pub id: trap::TrapId<ForExpr>,
@@ -11562,6 +11445,236 @@ impl From<trap::Label<LoopExpr>> for trap::Label<Element> {
}
}
#[derive(Debug)]
pub struct Struct {
pub id: trap::TrapId<Struct>,
pub attrs: Vec<trap::Label<Attr>>,
pub field_list: Option<trap::Label<FieldList>>,
pub generic_param_list: Option<trap::Label<GenericParamList>>,
pub name: Option<trap::Label<Name>>,
pub visibility: Option<trap::Label<Visibility>>,
pub where_clause: Option<trap::Label<WhereClause>>,
}
impl trap::TrapEntry for Struct {
fn extract_id(&mut self) -> trap::TrapId<Self> {
std::mem::replace(&mut self.id, trap::TrapId::Star)
}
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
out.add_tuple("structs", vec![id.into()]);
for (i, v) in self.attrs.into_iter().enumerate() {
out.add_tuple("struct_attrs", vec![id.into(), i.into(), v.into()]);
}
if let Some(v) = self.field_list {
out.add_tuple("struct_field_lists_", vec![id.into(), v.into()]);
}
if let Some(v) = self.generic_param_list {
out.add_tuple("struct_generic_param_lists", vec![id.into(), v.into()]);
}
if let Some(v) = self.name {
out.add_tuple("struct_names", vec![id.into(), v.into()]);
}
if let Some(v) = self.visibility {
out.add_tuple("struct_visibilities", vec![id.into(), v.into()]);
}
if let Some(v) = self.where_clause {
out.add_tuple("struct_where_clauses", vec![id.into(), v.into()]);
}
}
}
impl trap::TrapClass for Struct {
fn class_name() -> &'static str { "Struct" }
}
impl From<trap::Label<Struct>> for trap::Label<Adt> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of Adt
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Struct>> for trap::Label<Item> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of Item
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Struct>> for trap::Label<Stmt> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of Stmt
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Struct>> for trap::Label<AstNode> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of AstNode
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Struct>> for trap::Label<Locatable> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of Locatable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Struct>> for trap::Label<Element> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of Element
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Struct>> for trap::Label<Addressable> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of Addressable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Struct>> for trap::Label<VariantDef> {
fn from(value: trap::Label<Struct>) -> Self {
// SAFETY: this is safe because in the dbscheme Struct is a subclass of VariantDef
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
#[derive(Debug)]
pub struct Union {
pub id: trap::TrapId<Union>,
pub attrs: Vec<trap::Label<Attr>>,
pub generic_param_list: Option<trap::Label<GenericParamList>>,
pub name: Option<trap::Label<Name>>,
pub struct_field_list: Option<trap::Label<StructFieldList>>,
pub visibility: Option<trap::Label<Visibility>>,
pub where_clause: Option<trap::Label<WhereClause>>,
}
impl trap::TrapEntry for Union {
fn extract_id(&mut self) -> trap::TrapId<Self> {
std::mem::replace(&mut self.id, trap::TrapId::Star)
}
fn emit(self, id: trap::Label<Self>, out: &mut trap::Writer) {
out.add_tuple("unions", vec![id.into()]);
for (i, v) in self.attrs.into_iter().enumerate() {
out.add_tuple("union_attrs", vec![id.into(), i.into(), v.into()]);
}
if let Some(v) = self.generic_param_list {
out.add_tuple("union_generic_param_lists", vec![id.into(), v.into()]);
}
if let Some(v) = self.name {
out.add_tuple("union_names", vec![id.into(), v.into()]);
}
if let Some(v) = self.struct_field_list {
out.add_tuple("union_struct_field_lists", vec![id.into(), v.into()]);
}
if let Some(v) = self.visibility {
out.add_tuple("union_visibilities", vec![id.into(), v.into()]);
}
if let Some(v) = self.where_clause {
out.add_tuple("union_where_clauses", vec![id.into(), v.into()]);
}
}
}
impl trap::TrapClass for Union {
fn class_name() -> &'static str { "Union" }
}
impl From<trap::Label<Union>> for trap::Label<Adt> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of Adt
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Union>> for trap::Label<Item> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of Item
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Union>> for trap::Label<Stmt> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of Stmt
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Union>> for trap::Label<AstNode> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of AstNode
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Union>> for trap::Label<Locatable> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of Locatable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Union>> for trap::Label<Element> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of Element
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Union>> for trap::Label<Addressable> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of Addressable
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
impl From<trap::Label<Union>> for trap::Label<VariantDef> {
fn from(value: trap::Label<Union>) -> Self {
// SAFETY: this is safe because in the dbscheme Union is a subclass of VariantDef
unsafe {
Self::from_untyped(value.as_untyped())
}
}
}
#[derive(Debug)]
pub struct WhileExpr {
pub id: trap::TrapId<WhileExpr>,

View File

@@ -16,7 +16,7 @@ use ra_ap_ide_db::RootDatabase;
use ra_ap_ide_db::line_index::{LineCol, LineIndex};
use ra_ap_parser::SyntaxKind;
use ra_ap_span::TextSize;
use ra_ap_syntax::ast::HasName;
use ra_ap_syntax::ast::{HasAttrs, HasName};
use ra_ap_syntax::{
AstNode, NodeOrToken, SyntaxElementChildren, SyntaxError, SyntaxNode, SyntaxToken, TextRange,
ast,
@@ -45,12 +45,15 @@ macro_rules! post_emit {
$self.extract_canonical_origin($node, $label.into());
};
(Struct, $self:ident, $node:ident, $label:ident) => {
$self.emit_derive_expansion($node, $label);
$self.extract_canonical_origin($node, $label.into());
};
(Enum, $self:ident, $node:ident, $label:ident) => {
$self.emit_derive_expansion($node, $label);
$self.extract_canonical_origin($node, $label.into());
};
(Union, $self:ident, $node:ident, $label:ident) => {
$self.emit_derive_expansion($node, $label);
$self.extract_canonical_origin($node, $label.into());
};
(Module, $self:ident, $node:ident, $label:ident) => {
@@ -250,6 +253,25 @@ impl<'a> Translator<'a> {
.emit_diagnostic(severity, tag, message, full_message, location);
}
}
pub fn emit_diagnostic_for_node(
&mut self,
node: &impl ast::AstNode,
severity: DiagnosticSeverity,
tag: String,
message: String,
full_message: String,
) {
let location = self.location_for_node(node);
self.emit_diagnostic(
severity,
tag,
message,
full_message,
location.unwrap_or(UNKNOWN_LOCATION),
);
}
pub fn emit_parse_error(&mut self, owner: &impl ast::AstNode, err: &SyntaxError) {
let owner_range: TextRange = owner.syntax().text_range();
let err_range = err.range();
@@ -726,6 +748,39 @@ impl<'a> Translator<'a> {
None
}
fn process_item_macro_expansion(
&mut self,
node: &impl ast::AstNode,
ExpandResult { value, err }: ExpandResult<SyntaxNode>,
) -> Option<Label<generated::MacroItems>> {
let semantics = self.semantics.unwrap(); // if we are here, we have semantics
self.emit_macro_expansion_parse_errors(node, &value);
if let Some(err) = err {
let rendered = err.render_to_string(semantics.db);
self.emit_diagnostic_for_node(
node,
DiagnosticSeverity::Warning,
"item_expansion".to_owned(),
format!("item expansion failed ({})", rendered.kind),
rendered.message,
);
}
if let Some(items) = ast::MacroItems::cast(value) {
self.emit_macro_items(&items)
} else {
let message =
"attribute or derive macro expansion cannot be cast to MacroItems".to_owned();
self.emit_diagnostic_for_node(
node,
DiagnosticSeverity::Warning,
"item_expansion".to_owned(),
message.clone(),
message,
);
None
}
}
fn emit_attribute_macro_expansion(
&mut self,
node: &ast::Item,
@@ -741,23 +796,8 @@ impl<'a> Translator<'a> {
// only expand the outermost attribute macro
return None;
}
let ExpandResult {
value: expanded, ..
} = semantics.expand_attr_macro(node)?;
self.emit_macro_expansion_parse_errors(node, &expanded);
let macro_items = ast::MacroItems::cast(expanded).or_else(|| {
let message = "attribute macro expansion cannot be cast to MacroItems".to_owned();
let location = self.location_for_node(node);
self.emit_diagnostic(
DiagnosticSeverity::Warning,
"item_expansion".to_owned(),
message.clone(),
message,
location.unwrap_or(UNKNOWN_LOCATION),
);
None
})?;
self.emit_macro_items(&macro_items)
let expansion = semantics.expand_attr_macro(node)?;
self.process_item_macro_expansion(node, expansion)
}
pub(crate) fn emit_item_expansion(&mut self, node: &ast::Item, label: Label<generated::Item>) {
@@ -785,4 +825,26 @@ impl<'a> Translator<'a> {
generated::Const::emit_has_implementation(label, &mut self.trap.writer);
}
}
pub(crate) fn emit_derive_expansion(
&mut self,
node: &(impl Into<ast::Adt> + Clone),
label: impl Into<Label<generated::Adt>> + Copy,
) {
let Some(semantics) = self.semantics else {
return;
};
let node: ast::Adt = node.clone().into();
let expansions = node
.attrs()
.filter_map(|attr| semantics.expand_derive_macro(&attr))
.flatten()
.filter_map(|expansion| self.process_item_macro_expansion(&node, expansion))
.collect::<Vec<_>>();
generated::Adt::emit_derive_macro_expansions(
label.into(),
expansions,
&mut self.trap.writer,
);
}
}