Remove most of the item tree

I'm joking, but now that the def map is the only thing that uses the item tree, we can remove a lot of things from it that aren't needed for the def map.
This commit is contained in:
Chayim Refael Friedman 2025-05-21 13:42:48 +03:00
parent ed0b4506dd
commit 0a1a78cb87
4 changed files with 52 additions and 443 deletions

View File

@ -29,7 +29,6 @@
//!
//! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its
//! surface syntax.
#![allow(unexpected_cfgs)]
mod lower;
mod pretty;
@ -51,7 +50,7 @@ use hir_expand::{
mod_path::{ModPath, PathKind},
name::Name,
};
use intern::{Interned, Symbol};
use intern::Interned;
use la_arena::{Arena, Idx, RawIdx};
use rustc_hash::FxHashMap;
use smallvec::SmallVec;
@ -237,7 +236,6 @@ impl ItemTree {
structs,
unions,
enums,
variants,
consts,
statics,
traits,
@ -258,7 +256,6 @@ impl ItemTree {
structs.shrink_to_fit();
unions.shrink_to_fit();
enums.shrink_to_fit();
variants.shrink_to_fit();
consts.shrink_to_fit();
statics.shrink_to_fit();
traits.shrink_to_fit();
@ -310,7 +307,6 @@ struct ItemTreeData {
structs: Arena<Struct>,
unions: Arena<Union>,
enums: Arena<Enum>,
variants: Arena<Variant>,
consts: Arena<Const>,
statics: Arena<Static>,
traits: Arena<Trait>,
@ -340,41 +336,15 @@ pub enum AttrOwner {
ModItem(ModItem),
/// Inner attributes of the source file.
TopLevel,
Variant(FileItemTreeId<Variant>),
// while not relevant to early name resolution, fields can contain visibility
Field(FieldParent, ItemTreeFieldId),
}
impl AttrOwner {
pub fn make_field_indexed(parent: FieldParent, idx: usize) -> Self {
AttrOwner::Field(parent, ItemTreeFieldId::from_raw(RawIdx::from_u32(idx as u32)))
impl From<ModItem> for AttrOwner {
#[inline]
fn from(value: ModItem) -> Self {
AttrOwner::ModItem(value)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum FieldParent {
Struct(FileItemTreeId<Struct>),
Union(FileItemTreeId<Union>),
EnumVariant(FileItemTreeId<Variant>),
}
pub type ItemTreeFieldId = Idx<Field>;
macro_rules! from_attrs {
( $( $var:ident($t:ty) ),+ $(,)? ) => {
$(
impl From<$t> for AttrOwner {
fn from(t: $t) -> AttrOwner {
AttrOwner::$var(t)
}
}
)+
};
}
from_attrs!(ModItem(ModItem), Variant(FileItemTreeId<Variant>));
/// Trait implemented by all nodes in the item tree.
pub trait ItemTreeNode: Clone {
type Source: AstIdNode;
@ -383,7 +353,6 @@ pub trait ItemTreeNode: Clone {
/// Looks up an instance of `Self` in an item tree.
fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self;
fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner;
}
pub struct FileItemTreeId<N>(Idx<N>);
@ -547,10 +516,6 @@ macro_rules! mod_items {
fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self {
&tree.data().$fld[index]
}
fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner {
AttrOwner::ModItem(ModItem::$typ(id))
}
}
impl Index<Idx<$typ>> for ItemTree {
@ -624,22 +589,6 @@ impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
}
}
impl ItemTreeNode for Variant {
type Source = ast::Variant;
fn ast_id(&self) -> FileAstId<Self::Source> {
self.ast_id
}
fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self {
&tree.data().variants[index]
}
fn attr_owner(id: FileItemTreeId<Self>) -> AttrOwner {
AttrOwner::Variant(id)
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Use {
pub visibility: RawVisibilityId,
@ -712,7 +661,6 @@ pub struct ExternCrate {
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ExternBlock {
pub abi: Option<Symbol>,
pub ast_id: FileAstId<ast::ExternBlock>,
pub children: Box<[ModItem]>,
}
@ -728,7 +676,6 @@ pub struct Function {
pub struct Struct {
pub name: Name,
pub visibility: RawVisibilityId,
pub fields: Box<[Field]>,
pub shape: FieldsShape,
pub ast_id: FileAstId<ast::Struct>,
}
@ -737,7 +684,6 @@ pub struct Struct {
pub struct Union {
pub name: Name,
pub visibility: RawVisibilityId,
pub fields: Box<[Field]>,
pub ast_id: FileAstId<ast::Union>,
}
@ -745,18 +691,9 @@ pub struct Union {
pub struct Enum {
pub name: Name,
pub visibility: RawVisibilityId,
pub variants: Range<FileItemTreeId<Variant>>,
pub ast_id: FileAstId<ast::Enum>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Variant {
pub name: Name,
pub fields: Box<[Field]>,
pub shape: FieldsShape,
pub ast_id: FileAstId<ast::Variant>,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum FieldsShape {
Record,
@ -788,16 +725,6 @@ impl VisibilityExplicitness {
}
}
// FIXME: Remove this from item tree?
/// A single field of an enum variant or struct
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Field {
pub name: Name,
pub visibility: RawVisibilityId,
// FIXME: Not an item tree property
pub is_unsafe: bool,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Const {
/// `None` for `const _: () = ();`
@ -817,7 +744,6 @@ pub struct Static {
pub struct Trait {
pub name: Name,
pub visibility: RawVisibilityId,
pub items: Box<[AssocItem]>,
pub ast_id: FileAstId<ast::Trait>,
}
@ -830,7 +756,6 @@ pub struct TraitAlias {
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Impl {
pub items: Box<[AssocItem]>,
pub ast_id: FileAstId<ast::Impl>,
}
@ -971,76 +896,3 @@ impl UseTree {
}
}
}
macro_rules! impl_froms {
($e:ident { $($v:ident ($t:ty)),* $(,)? }) => {
$(
impl From<$t> for $e {
fn from(it: $t) -> $e {
$e::$v(it)
}
}
)*
}
}
impl ModItem {
pub fn as_assoc_item(&self) -> Option<AssocItem> {
match self {
ModItem::Use(_)
| ModItem::ExternCrate(_)
| ModItem::ExternBlock(_)
| ModItem::Struct(_)
| ModItem::Union(_)
| ModItem::Enum(_)
| ModItem::Static(_)
| ModItem::Trait(_)
| ModItem::TraitAlias(_)
| ModItem::Impl(_)
| ModItem::Mod(_)
| ModItem::MacroRules(_)
| ModItem::Macro2(_) => None,
&ModItem::MacroCall(call) => Some(AssocItem::MacroCall(call)),
&ModItem::Const(konst) => Some(AssocItem::Const(konst)),
&ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(alias)),
&ModItem::Function(func) => Some(AssocItem::Function(func)),
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum AssocItem {
Function(FileItemTreeId<Function>),
TypeAlias(FileItemTreeId<TypeAlias>),
Const(FileItemTreeId<Const>),
MacroCall(FileItemTreeId<MacroCall>),
}
impl_froms!(AssocItem {
Function(FileItemTreeId<Function>),
TypeAlias(FileItemTreeId<TypeAlias>),
Const(FileItemTreeId<Const>),
MacroCall(FileItemTreeId<MacroCall>),
});
impl From<AssocItem> for ModItem {
fn from(item: AssocItem) -> Self {
match item {
AssocItem::Function(it) => it.into(),
AssocItem::TypeAlias(it) => it.into(),
AssocItem::Const(it) => it.into(),
AssocItem::MacroCall(it) => it.into(),
}
}
}
impl AssocItem {
pub fn ast_id(self, tree: &ItemTree) -> FileAstId<ast::AssocItem> {
match self {
AssocItem::Function(id) => tree[id].ast_id.upcast(),
AssocItem::TypeAlias(id) => tree[id].ast_id.upcast(),
AssocItem::Const(id) => tree[id].ast_id.upcast(),
AssocItem::MacroCall(id) => tree[id].ast_id.upcast(),
}
}
}

View File

@ -8,23 +8,22 @@ use hir_expand::{
name::AsName,
span_map::{SpanMap, SpanMapRef},
};
use intern::{Symbol, sym};
use la_arena::Arena;
use span::{AstIdMap, SyntaxContext};
use syntax::{
AstNode,
ast::{self, HasModuleItem, HasName, IsString},
ast::{self, HasModuleItem, HasName},
};
use triomphe::Arc;
use crate::{
db::DefDatabase,
item_tree::{
AssocItem, AttrOwner, Const, Enum, ExternBlock, ExternCrate, Field, FieldParent,
FieldsShape, FileItemTreeId, Function, Idx, Impl, ImportAlias, Interned, ItemTree,
ItemTreeData, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, ModPath, Name, Range,
RawAttrs, RawIdx, RawVisibility, RawVisibilityId, Static, Struct, StructKind, Trait,
TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, Variant, VisibilityExplicitness,
AttrOwner, Const, Enum, ExternBlock, ExternCrate, FieldsShape, FileItemTreeId, Function,
Idx, Impl, ImportAlias, Interned, ItemTree, ItemTreeData, Macro2, MacroCall, MacroRules,
Mod, ModItem, ModKind, ModPath, RawAttrs, RawVisibility, RawVisibilityId, Static, Struct,
StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
VisibilityExplicitness,
},
};
@ -163,118 +162,23 @@ impl<'a> Ctx<'a> {
}
}
fn lower_assoc_item(&mut self, item_node: &ast::AssocItem) -> Option<AssocItem> {
let item: AssocItem = match item_node {
ast::AssocItem::Fn(ast) => self.lower_function(ast).map(Into::into),
ast::AssocItem::TypeAlias(ast) => self.lower_type_alias(ast).map(Into::into),
ast::AssocItem::Const(ast) => Some(self.lower_const(ast).into()),
ast::AssocItem::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
}?;
let attrs = RawAttrs::new(self.db, item_node, self.span_map());
self.add_attrs(
match item {
AssocItem::Function(it) => AttrOwner::ModItem(ModItem::Function(it)),
AssocItem::TypeAlias(it) => AttrOwner::ModItem(ModItem::TypeAlias(it)),
AssocItem::Const(it) => AttrOwner::ModItem(ModItem::Const(it)),
AssocItem::MacroCall(it) => AttrOwner::ModItem(ModItem::MacroCall(it)),
},
attrs,
);
Some(item)
}
fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<FileItemTreeId<Struct>> {
let visibility = self.lower_visibility(strukt);
let name = strukt.name()?.as_name();
let ast_id = self.source_ast_id_map.ast_id(strukt);
let (fields, kind, attrs) = self.lower_fields(&strukt.kind());
let res = Struct { name, visibility, fields, shape: kind, ast_id };
let shape = adt_shape(strukt.kind());
let res = Struct { name, visibility, shape, ast_id };
let id = id(self.data().structs.alloc(res));
for (idx, attr) in attrs {
self.add_attrs(
AttrOwner::Field(
FieldParent::Struct(id),
Idx::from_raw(RawIdx::from_u32(idx as u32)),
),
attr,
);
}
Some(id)
}
fn lower_fields(
&mut self,
strukt_kind: &ast::StructKind,
) -> (Box<[Field]>, FieldsShape, Vec<(usize, RawAttrs)>) {
match strukt_kind {
ast::StructKind::Record(it) => {
let mut fields = vec![];
let mut attrs = vec![];
for (i, field) in it.fields().enumerate() {
let data = self.lower_record_field(&field);
fields.push(data);
let attr = RawAttrs::new(self.db, &field, self.span_map());
if !attr.is_empty() {
attrs.push((i, attr))
}
}
(fields.into(), FieldsShape::Record, attrs)
}
ast::StructKind::Tuple(it) => {
let mut fields = vec![];
let mut attrs = vec![];
for (i, field) in it.fields().enumerate() {
let data = self.lower_tuple_field(i, &field);
fields.push(data);
let attr = RawAttrs::new(self.db, &field, self.span_map());
if !attr.is_empty() {
attrs.push((i, attr))
}
}
(fields.into(), FieldsShape::Tuple, attrs)
}
ast::StructKind::Unit => (Box::default(), FieldsShape::Unit, Vec::default()),
}
}
fn lower_record_field(&mut self, field: &ast::RecordField) -> Field {
let name = match field.name() {
Some(name) => name.as_name(),
None => Name::missing(),
};
let visibility = self.lower_visibility(field);
Field { name, visibility, is_unsafe: field.unsafe_token().is_some() }
}
fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleField) -> Field {
let name = Name::new_tuple_field(idx);
let visibility = self.lower_visibility(field);
Field { name, visibility, is_unsafe: false }
}
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
let visibility = self.lower_visibility(union);
let name = union.name()?.as_name();
let ast_id = self.source_ast_id_map.ast_id(union);
let (fields, _, attrs) = match union.record_field_list() {
Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)),
None => (Box::default(), FieldsShape::Record, Vec::default()),
};
let res = Union { name, visibility, fields, ast_id };
let res = Union { name, visibility, ast_id };
let id = id(self.data().unions.alloc(res));
for (idx, attr) in attrs {
self.add_attrs(
AttrOwner::Field(
FieldParent::Union(id),
Idx::from_raw(RawIdx::from_u32(idx as u32)),
),
attr,
);
}
Some(id)
}
@ -282,48 +186,11 @@ impl<'a> Ctx<'a> {
let visibility = self.lower_visibility(enum_);
let name = enum_.name()?.as_name();
let ast_id = self.source_ast_id_map.ast_id(enum_);
let variants = match &enum_.variant_list() {
Some(variant_list) => self.lower_variants(variant_list),
None => {
FileItemTreeId(self.next_variant_idx())..FileItemTreeId(self.next_variant_idx())
}
};
let res = Enum { name, visibility, variants, ast_id };
let res = Enum { name, visibility, ast_id };
let id = id(self.data().enums.alloc(res));
Some(id)
}
fn lower_variants(&mut self, variants: &ast::VariantList) -> Range<FileItemTreeId<Variant>> {
let start = self.next_variant_idx();
for variant in variants.variants() {
let idx = self.lower_variant(&variant);
self.add_attrs(id(idx).into(), RawAttrs::new(self.db, &variant, self.span_map()));
}
let end = self.next_variant_idx();
FileItemTreeId(start)..FileItemTreeId(end)
}
fn lower_variant(&mut self, variant: &ast::Variant) -> Idx<Variant> {
let name = match variant.name() {
Some(name) => name.as_name(),
None => Name::missing(),
};
let (fields, kind, attrs) = self.lower_fields(&variant.kind());
let ast_id = self.source_ast_id_map.ast_id(variant);
let res = Variant { name, fields, shape: kind, ast_id };
let id = self.data().variants.alloc(res);
for (idx, attr) in attrs {
self.add_attrs(
AttrOwner::Field(
FieldParent::EnumVariant(FileItemTreeId(id)),
Idx::from_raw(RawIdx::from_u32(idx as u32)),
),
attr,
);
}
id
}
fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>> {
let visibility = self.lower_visibility(func);
let name = func.name()?.as_name();
@ -390,14 +257,7 @@ impl<'a> Ctx<'a> {
let visibility = self.lower_visibility(trait_def);
let ast_id = self.source_ast_id_map.ast_id(trait_def);
let items = trait_def
.assoc_item_list()
.into_iter()
.flat_map(|list| list.assoc_items())
.filter_map(|item_node| self.lower_assoc_item(&item_node))
.collect();
let def = Trait { name, visibility, items, ast_id };
let def = Trait { name, visibility, ast_id };
let id = id(self.data().traits.alloc(def));
Some(id)
}
@ -417,16 +277,9 @@ impl<'a> Ctx<'a> {
fn lower_impl(&mut self, impl_def: &ast::Impl) -> FileItemTreeId<Impl> {
let ast_id = self.source_ast_id_map.ast_id(impl_def);
// We cannot use `assoc_items()` here as that does not include macro calls.
let items = impl_def
.assoc_item_list()
.into_iter()
.flat_map(|it| it.assoc_items())
.filter_map(|item| self.lower_assoc_item(&item))
.collect();
// Note that trait impls don't get implicit `Self` unlike traits, because here they are a
// type alias rather than a type parameter, so this is handled by the resolver.
let res = Impl { items, ast_id };
let res = Impl { ast_id };
id(self.data().impls.alloc(res))
}
@ -489,7 +342,6 @@ impl<'a> Ctx<'a> {
fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> FileItemTreeId<ExternBlock> {
let ast_id = self.source_ast_id_map.ast_id(block);
let abi = block.abi().map(lower_abi);
let children: Box<[_]> = block.extern_item_list().map_or(Box::new([]), |list| {
list.extern_items()
.filter_map(|item| {
@ -510,7 +362,7 @@ impl<'a> Ctx<'a> {
.collect()
});
let res = ExternBlock { abi, ast_id, children };
let res = ExternBlock { ast_id, children };
id(self.data().extern_blocks.alloc(res))
}
@ -520,20 +372,6 @@ impl<'a> Ctx<'a> {
});
self.data().vis.alloc(vis)
}
fn next_variant_idx(&self) -> Idx<Variant> {
Idx::from_raw(RawIdx::from(
self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32),
))
}
}
fn lower_abi(abi: ast::Abi) -> Symbol {
match abi.abi_string() {
Some(tok) => Symbol::intern(tok.text_without_quotes()),
// `extern` default to be `extern "C"`.
_ => sym::C,
}
}
struct UseTreeLowering<'a> {
@ -647,3 +485,11 @@ pub(crate) fn visibility_from_ast(
};
RawVisibility::Module(Interned::new(path), VisibilityExplicitness::Explicit)
}
fn adt_shape(kind: StructKind) -> FieldsShape {
match kind {
StructKind::Record(_) => FieldsShape::Record,
StructKind::Tuple(_) => FieldsShape::Tuple,
StructKind::Unit => FieldsShape::Unit,
}
}

View File

@ -2,15 +2,13 @@
use std::fmt::{self, Write};
use la_arena::{Idx, RawIdx};
use span::{Edition, ErasedFileAstId};
use crate::{
item_tree::{
AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldParent,
FieldsShape, FileItemTreeId, Function, Impl, ItemTree, Macro2, MacroCall, MacroRules, Mod,
ModItem, ModKind, RawAttrs, RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias,
Union, Use, UseTree, UseTreeKind, Variant,
AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, FieldsShape, Function, Impl,
ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, RawAttrs, RawVisibilityId,
Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
},
visibility::RawVisibility,
};
@ -118,44 +116,14 @@ impl Printer<'_> {
};
}
fn print_fields(&mut self, parent: FieldParent, kind: FieldsShape, fields: &[Field]) {
let edition = self.edition;
fn print_fields(&mut self, kind: FieldsShape) {
match kind {
FieldsShape::Record => {
self.whitespace();
w!(self, "{{");
self.indented(|this| {
for (idx, Field { name, visibility, is_unsafe }) in fields.iter().enumerate() {
this.print_attrs_of(
AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
"\n",
);
this.print_visibility(*visibility);
if *is_unsafe {
w!(this, "unsafe ");
}
wln!(this, "{},", name.display(self.db, edition));
}
});
w!(self, "}}");
w!(self, "{{ ... }}");
}
FieldsShape::Tuple => {
w!(self, "(");
self.indented(|this| {
for (idx, Field { name, visibility, is_unsafe }) in fields.iter().enumerate() {
this.print_attrs_of(
AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
"\n",
);
this.print_visibility(*visibility);
if *is_unsafe {
w!(this, "unsafe ");
}
wln!(this, "{},", name.display(self.db, edition));
}
});
w!(self, ")");
w!(self, "(...)");
}
FieldsShape::Unit => {}
}
@ -214,13 +182,9 @@ impl Printer<'_> {
wln!(self, ";");
}
ModItem::ExternBlock(it) => {
let ExternBlock { abi, ast_id, children } = &self.tree[it];
let ExternBlock { ast_id, children } = &self.tree[it];
self.print_ast_id(ast_id.erase());
w!(self, "extern ");
if let Some(abi) = abi {
w!(self, "\"{}\" ", abi);
}
w!(self, "{{");
w!(self, "extern {{");
self.indented(|this| {
for child in &**children {
this.print_mod_item(*child);
@ -235,11 +199,11 @@ impl Printer<'_> {
wln!(self, "fn {};", name.display(self.db, self.edition));
}
ModItem::Struct(it) => {
let Struct { visibility, name, fields, shape: kind, ast_id } = &self.tree[it];
let Struct { visibility, name, shape: kind, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
w!(self, "struct {}", name.display(self.db, self.edition));
self.print_fields(FieldParent::Struct(it), *kind, fields);
self.print_fields(*kind);
if matches!(kind, FieldsShape::Record) {
wln!(self);
} else {
@ -247,30 +211,18 @@ impl Printer<'_> {
}
}
ModItem::Union(it) => {
let Union { name, visibility, fields, ast_id } = &self.tree[it];
let Union { name, visibility, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
w!(self, "union {}", name.display(self.db, self.edition));
self.print_fields(FieldParent::Union(it), FieldsShape::Record, fields);
self.print_fields(FieldsShape::Record);
wln!(self);
}
ModItem::Enum(it) => {
let Enum { name, visibility, variants, ast_id } = &self.tree[it];
let Enum { name, visibility, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
w!(self, "enum {} {{", name.display(self.db, self.edition));
let edition = self.edition;
self.indented(|this| {
for variant in FileItemTreeId::range_iter(variants.clone()) {
let Variant { name, fields, shape: kind, ast_id } = &this.tree[variant];
this.print_ast_id(ast_id.erase());
this.print_attrs_of(variant, "\n");
w!(this, "{}", name.display(self.db, edition));
this.print_fields(FieldParent::EnumVariant(variant), *kind, fields);
wln!(this, ",");
}
});
wln!(self, "}}");
w!(self, "enum {} {{ ... }}", name.display(self.db, self.edition));
}
ModItem::Const(it) => {
let Const { name, visibility, ast_id } = &self.tree[it];
@ -293,16 +245,10 @@ impl Printer<'_> {
wln!(self);
}
ModItem::Trait(it) => {
let Trait { name, visibility, items, ast_id } = &self.tree[it];
let Trait { name, visibility, ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
w!(self, "trait {} {{", name.display(self.db, self.edition));
self.indented(|this| {
for item in &**items {
this.print_mod_item((*item).into());
}
});
wln!(self, "}}");
w!(self, "trait {} {{ ... }}", name.display(self.db, self.edition));
}
ModItem::TraitAlias(it) => {
let TraitAlias { name, visibility, ast_id } = &self.tree[it];
@ -311,15 +257,9 @@ impl Printer<'_> {
wln!(self, "trait {} = ..;", name.display(self.db, self.edition));
}
ModItem::Impl(it) => {
let Impl { items, ast_id } = &self.tree[it];
let Impl { ast_id } = &self.tree[it];
self.print_ast_id(ast_id.erase());
w!(self, "impl {{");
self.indented(|this| {
for item in &**items {
this.print_mod_item((*item).into());
}
});
wln!(self, "}}");
w!(self, "impl {{ ... }}");
}
ModItem::TypeAlias(it) => {
let TypeAlias { name, visibility, ast_id } = &self.tree[it];

View File

@ -73,10 +73,10 @@ extern "C" {
fn ex_fn();
}
"#,
expect![[r##"
expect![[r#"
#[on_extern_block]
// AstId: ExternBlock[0000, 0]
extern "C" {
extern {
#[on_extern_type]
// AstId: TypeAlias[9FDF, 0]
pub(self) type ExType;
@ -89,7 +89,7 @@ extern "C" {
// AstId: Fn[452D, 0]
pub(self) fn ex_fn;
}
"##]],
"#]],
);
}
@ -129,39 +129,16 @@ enum E {
#[derive(Debug)]
// AstId: Struct[C7A1, 0]
pub(self) struct Struct {
#[doc = " fld docs"]
pub(self) fld,
}
pub(self) struct Struct { ... }
// AstId: Struct[DAC2, 0]
pub(self) struct Tuple(
#[attr]
pub(self) 0,
);
pub(self) struct Tuple(...);
// AstId: Union[2DBB, 0]
pub(self) union Ize {
pub(self) a,
pub(self) b,
}
pub(self) union Ize { ... }
// AstId: Enum[7FF8, 0]
pub(self) enum E {
// AstId: Variant[C717, 0]
#[doc = " comment on Unit"]
Unit,
// AstId: Variant[AEAB, 0]
#[doc = " comment on Tuple"]
Tuple(
pub(self) 0,
),
// AstId: Variant[4B1B, 0]
Struct {
#[doc = " comment on a: u8"]
pub(self) a,
},
}
pub(self) enum E { ... }
"#]],
);
}
@ -197,13 +174,7 @@ trait Tr: SuperTrait + 'lifetime {
pub(self) fn f;
// AstId: Trait[2998, 0]
pub(self) trait Tr {
// AstId: TypeAlias[9F08, 0]
pub(self) type Assoc;
// AstId: Fn[6C0C, 0]
pub(self) fn method;
}
pub(self) trait Tr { ... }
"#]],
);
}