Unnamed repository; edit this file 'description' to name the repository.
Remove Params and Fields from AstIdMap
Lukas Wirth 2024-07-25
parent 200a01a · commit 9cbafa2
-rw-r--r--crates/hir-def/src/attr.rs26
-rw-r--r--crates/hir-def/src/body.rs16
-rw-r--r--crates/hir-def/src/data.rs42
-rw-r--r--crates/hir-def/src/data/adt.rs125
-rw-r--r--crates/hir-def/src/item_tree.rs173
-rw-r--r--crates/hir-def/src/item_tree/lower.rs213
-rw-r--r--crates/hir-def/src/item_tree/pretty.rs129
-rw-r--r--crates/hir-def/src/item_tree/tests.rs35
-rw-r--r--crates/hir-def/src/nameres/collector.rs27
-rw-r--r--crates/hir-def/src/nameres/diagnostics.rs15
-rw-r--r--crates/hir-def/src/nameres/path_resolution.rs8
-rw-r--r--crates/hir-def/src/src.rs19
-rw-r--r--crates/hir-ty/src/infer.rs4
-rw-r--r--crates/hir/src/display.rs13
-rw-r--r--crates/hir/src/lib.rs92
-rw-r--r--crates/span/src/ast_id.rs6
16 files changed, 494 insertions, 449 deletions
diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs
index b0f16ad6f4..ba88495e14 100644
--- a/crates/hir-def/src/attr.rs
+++ b/crates/hir-def/src/attr.rs
@@ -20,7 +20,7 @@ use triomphe::Arc;
use crate::{
db::DefDatabase,
- item_tree::{AttrOwner, Fields, ItemTreeNode},
+ item_tree::{AttrOwner, FieldParent, ItemTreeNode},
lang_item::LangItem,
nameres::{ModuleOrigin, ModuleSource},
src::{HasChildSource, HasSource},
@@ -76,40 +76,36 @@ impl Attrs {
let mut res = ArenaMap::default();
let crate_graph = db.crate_graph();
- let (fields, item_tree, krate) = match v {
+ let item_tree;
+ let (parent, fields, krate) = match v {
VariantId::EnumVariantId(it) => {
let loc = it.lookup(db);
let krate = loc.parent.lookup(db).container.krate;
- let item_tree = loc.id.item_tree(db);
+ item_tree = loc.id.item_tree(db);
let variant = &item_tree[loc.id.value];
- (variant.fields.clone(), item_tree, krate)
+ (FieldParent::Variant(loc.id.value), &variant.fields, krate)
}
VariantId::StructId(it) => {
let loc = it.lookup(db);
let krate = loc.container.krate;
- let item_tree = loc.id.item_tree(db);
+ item_tree = loc.id.item_tree(db);
let struct_ = &item_tree[loc.id.value];
- (struct_.fields.clone(), item_tree, krate)
+ (FieldParent::Struct(loc.id.value), &struct_.fields, krate)
}
VariantId::UnionId(it) => {
let loc = it.lookup(db);
let krate = loc.container.krate;
- let item_tree = loc.id.item_tree(db);
+ item_tree = loc.id.item_tree(db);
let union_ = &item_tree[loc.id.value];
- (union_.fields.clone(), item_tree, krate)
+ (FieldParent::Union(loc.id.value), &union_.fields, krate)
}
};
- let fields = match fields {
- Fields::Record(fields) | Fields::Tuple(fields) => fields,
- Fields::Unit => return Arc::new(res),
- };
-
let cfg_options = &crate_graph[krate].cfg_options;
let mut idx = 0;
- for field in fields {
- let attrs = item_tree.attrs(db, krate, field.into());
+ for (id, _field) in fields.iter().enumerate() {
+ let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, id));
if attrs.is_cfg_enabled(cfg_options) {
res.insert(Idx::from_raw(RawIdx::from(idx)), attrs);
idx += 1;
diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs
index 3486928e41..9e1bff98f8 100644
--- a/crates/hir-def/src/body.rs
+++ b/crates/hir-def/src/body.rs
@@ -11,7 +11,7 @@ use std::ops::{Deref, Index};
use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
use hir_expand::{name::Name, InFile};
-use la_arena::{Arena, ArenaMap};
+use la_arena::{Arena, ArenaMap, Idx, RawIdx};
use rustc_hash::FxHashMap;
use smallvec::SmallVec;
use span::MacroFileId;
@@ -24,6 +24,7 @@ use crate::{
hir::{
dummy_expr_id, Binding, BindingId, Expr, ExprId, Label, LabelId, Pat, PatId, RecordFieldPat,
},
+ item_tree::AttrOwner,
nameres::DefMap,
path::{ModPath, Path},
src::HasSource,
@@ -136,16 +137,23 @@ impl Body {
let data = db.function_data(f);
let f = f.lookup(db);
let src = f.source(db);
- params = src.value.param_list().map(|param_list| {
+ params = src.value.param_list().map(move |param_list| {
let item_tree = f.id.item_tree(db);
let func = &item_tree[f.id.value];
let krate = f.container.module(db).krate;
let crate_graph = db.crate_graph();
(
param_list,
- func.params.clone().map(move |param| {
+ (0..func.params.len()).map(move |idx| {
item_tree
- .attrs(db, krate, param.into())
+ .attrs(
+ db,
+ krate,
+ AttrOwner::Param(
+ f.id.value,
+ Idx::from_raw(RawIdx::from(idx as u32)),
+ ),
+ )
.is_cfg_enabled(&crate_graph[krate].cfg_options)
}),
)
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs
index 37506b6cdc..a03140e2a9 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -7,6 +7,7 @@ use hir_expand::{
name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
};
use intern::{sym, Interned, Symbol};
+use la_arena::{Idx, RawIdx};
use smallvec::SmallVec;
use syntax::{ast, Parse};
use triomphe::Arc;
@@ -58,32 +59,15 @@ impl FunctionData {
let crate_graph = db.crate_graph();
let cfg_options = &crate_graph[krate].cfg_options;
- let enabled_params = func
- .params
- .clone()
- .filter(|&param| item_tree.attrs(db, krate, param.into()).is_cfg_enabled(cfg_options));
-
- // If last cfg-enabled param is a `...` param, it's a varargs function.
- let is_varargs = enabled_params
- .clone()
- .next_back()
- .map_or(false, |param| item_tree[param].type_ref.is_none());
+ let attr_owner = |idx| {
+ item_tree::AttrOwner::Param(loc.id.value, Idx::from_raw(RawIdx::from(idx as u32)))
+ };
let mut flags = func.flags;
- if is_varargs {
- flags |= FnFlags::IS_VARARGS;
- }
if flags.contains(FnFlags::HAS_SELF_PARAM) {
// If there's a self param in the syntax, but it is cfg'd out, remove the flag.
- let is_cfgd_out = match func.params.clone().next() {
- Some(param) => {
- !item_tree.attrs(db, krate, param.into()).is_cfg_enabled(cfg_options)
- }
- None => {
- stdx::never!("fn HAS_SELF_PARAM but no parameters allocated");
- true
- }
- };
+ let is_cfgd_out =
+ !item_tree.attrs(db, krate, attr_owner(0usize)).is_cfg_enabled(cfg_options);
if is_cfgd_out {
cov_mark::hit!(cfgd_out_self_param);
flags.remove(FnFlags::HAS_SELF_PARAM);
@@ -101,9 +85,14 @@ impl FunctionData {
Arc::new(FunctionData {
name: func.name.clone(),
- params: enabled_params
- .clone()
- .filter_map(|id| item_tree[id].type_ref.clone())
+ params: func
+ .params
+ .iter()
+ .enumerate()
+ .filter(|&(idx, _)| {
+ item_tree.attrs(db, krate, attr_owner(idx)).is_cfg_enabled(cfg_options)
+ })
+ .map(|(_, param)| param.type_ref.clone())
.collect(),
ret_type: func.ret_type.clone(),
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
@@ -629,7 +618,8 @@ impl<'a> AssocItemCollector<'a> {
if !attrs.is_cfg_enabled(self.expander.cfg_options()) {
self.diagnostics.push(DefDiagnostic::unconfigured_code(
self.module_id.local_id,
- InFile::new(self.expander.current_file_id(), item.ast_id(item_tree).erase()),
+ tree_id,
+ ModItem::from(item).into(),
attrs.cfg().unwrap(),
self.expander.cfg_options().clone(),
));
diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs
index cc6e408b65..827cce706b 100644
--- a/crates/hir-def/src/data/adt.rs
+++ b/crates/hir-def/src/data/adt.rs
@@ -7,7 +7,7 @@ use either::Either;
use hir_expand::{
name::{AsName, Name},
- HirFileId, InFile,
+ InFile,
};
use intern::{sym, Interned};
use la_arena::Arena;
@@ -18,7 +18,9 @@ use triomphe::Arc;
use crate::{
builtin_type::{BuiltinInt, BuiltinUint},
db::DefDatabase,
- item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
+ item_tree::{
+ AttrOwner, Field, FieldParent, FieldsShape, ItemTree, ModItem, RawVisibilityId, TreeId,
+ },
lang_item::LangItem,
lower::LowerCtx,
nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
@@ -211,20 +213,25 @@ impl StructData {
}
let strukt = &item_tree[loc.id.value];
- let (variant_data, diagnostics) = lower_fields(
+ let (data, diagnostics) = lower_fields(
db,
krate,
- loc.id.file_id(),
loc.container.local_id,
+ loc.id.tree_id(),
&item_tree,
&db.crate_graph()[krate].cfg_options,
+ FieldParent::Struct(loc.id.value),
&strukt.fields,
None,
);
(
Arc::new(StructData {
name: strukt.name.clone(),
- variant_data: Arc::new(variant_data),
+ variant_data: Arc::new(match strukt.shape {
+ FieldsShape::Record => VariantData::Record(data),
+ FieldsShape::Tuple => VariantData::Tuple(data),
+ FieldsShape::Unit => VariantData::Unit,
+ }),
repr,
visibility: item_tree[strukt.visibility].clone(),
flags,
@@ -256,20 +263,21 @@ impl StructData {
}
let union = &item_tree[loc.id.value];
- let (variant_data, diagnostics) = lower_fields(
+ let (data, diagnostics) = lower_fields(
db,
krate,
- loc.id.file_id(),
loc.container.local_id,
+ loc.id.tree_id(),
&item_tree,
&db.crate_graph()[krate].cfg_options,
+ FieldParent::Union(loc.id.value),
&union.fields,
None,
);
(
Arc::new(StructData {
name: union.name.clone(),
- variant_data: Arc::new(variant_data),
+ variant_data: Arc::new(VariantData::Record(data)),
repr,
visibility: item_tree[union.visibility].clone(),
flags,
@@ -336,13 +344,14 @@ impl EnumVariantData {
let item_tree = loc.id.item_tree(db);
let variant = &item_tree[loc.id.value];
- let (var_data, diagnostics) = lower_fields(
+ let (data, diagnostics) = lower_fields(
db,
krate,
- loc.id.file_id(),
container.local_id,
+ loc.id.tree_id(),
&item_tree,
&db.crate_graph()[krate].cfg_options,
+ FieldParent::Variant(loc.id.value),
&variant.fields,
Some(item_tree[loc.parent.lookup(db).id.value].visibility),
);
@@ -350,7 +359,11 @@ impl EnumVariantData {
(
Arc::new(EnumVariantData {
name: variant.name.clone(),
- variant_data: Arc::new(var_data),
+ variant_data: Arc::new(match variant.shape {
+ FieldsShape::Record => VariantData::Record(data),
+ FieldsShape::Tuple => VariantData::Tuple(data),
+ FieldsShape::Unit => VariantData::Unit,
+ }),
}),
DefDiagnostics::new(diagnostics),
)
@@ -396,21 +409,23 @@ pub enum StructKind {
Unit,
}
+// FIXME This is only used for mapping back source now?
pub(crate) fn lower_struct(
db: &dyn DefDatabase,
trace: &mut Trace<FieldData, Either<ast::TupleField, ast::RecordField>>,
ast: &InFile<ast::StructKind>,
krate: CrateId,
item_tree: &ItemTree,
- fields: &Fields,
+ parent: FieldParent,
) -> StructKind {
let ctx = LowerCtx::new(db, ast.file_id);
- match (&ast.value, fields) {
- (ast::StructKind::Tuple(fl), Fields::Tuple(fields)) => {
+ match &ast.value {
+ ast::StructKind::Tuple(fl) => {
let cfg_options = &db.crate_graph()[krate].cfg_options;
- for ((i, fd), item_tree_id) in fl.fields().enumerate().zip(fields.clone()) {
- if !item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options) {
+ for (i, fd) in fl.fields().enumerate() {
+ let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, i));
+ if !attrs.is_cfg_enabled(cfg_options) {
continue;
}
@@ -427,10 +442,11 @@ pub(crate) fn lower_struct(
}
StructKind::Tuple
}
- (ast::StructKind::Record(fl), Fields::Record(fields)) => {
+ ast::StructKind::Record(fl) => {
let cfg_options = &db.crate_graph()[krate].cfg_options;
- for (fd, item_tree_id) in fl.fields().zip(fields.clone()) {
- if !item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options) {
+ for (i, fd) in fl.fields().enumerate() {
+ let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, i));
+ if !attrs.is_cfg_enabled(cfg_options) {
continue;
}
@@ -454,65 +470,32 @@ pub(crate) fn lower_struct(
fn lower_fields(
db: &dyn DefDatabase,
krate: CrateId,
- current_file_id: HirFileId,
container: LocalModuleId,
+ tree_id: TreeId,
item_tree: &ItemTree,
cfg_options: &CfgOptions,
- fields: &Fields,
+ parent: FieldParent,
+ fields: &[Field],
override_visibility: Option<RawVisibilityId>,
-) -> (VariantData, Vec<DefDiagnostic>) {
+) -> (Arena<FieldData>, Vec<DefDiagnostic>) {
let mut diagnostics = Vec::new();
- match fields {
- Fields::Record(flds) => {
- let mut arena = Arena::new();
- for field_id in flds.clone() {
- let attrs = item_tree.attrs(db, krate, field_id.into());
- let field = &item_tree[field_id];
- if attrs.is_cfg_enabled(cfg_options) {
- arena.alloc(lower_field(item_tree, field, override_visibility));
- } else {
- diagnostics.push(DefDiagnostic::unconfigured_code(
- container,
- InFile::new(
- current_file_id,
- match field.ast_id {
- FieldAstId::Record(it) => it.erase(),
- FieldAstId::Tuple(it) => it.erase(),
- },
- ),
- attrs.cfg().unwrap(),
- cfg_options.clone(),
- ))
- }
- }
- (VariantData::Record(arena), diagnostics)
- }
- Fields::Tuple(flds) => {
- let mut arena = Arena::new();
- for field_id in flds.clone() {
- let attrs = item_tree.attrs(db, krate, field_id.into());
- let field = &item_tree[field_id];
- if attrs.is_cfg_enabled(cfg_options) {
- arena.alloc(lower_field(item_tree, field, override_visibility));
- } else {
- diagnostics.push(DefDiagnostic::unconfigured_code(
- container,
- InFile::new(
- current_file_id,
- match field.ast_id {
- FieldAstId::Record(it) => it.erase(),
- FieldAstId::Tuple(it) => it.erase(),
- },
- ),
- attrs.cfg().unwrap(),
- cfg_options.clone(),
- ))
- }
- }
- (VariantData::Tuple(arena), diagnostics)
+ let mut arena = Arena::new();
+ for (idx, field) in fields.iter().enumerate() {
+ let attr_owner = AttrOwner::make_field_indexed(parent, idx);
+ let attrs = item_tree.attrs(db, krate, attr_owner);
+ if attrs.is_cfg_enabled(cfg_options) {
+ arena.alloc(lower_field(item_tree, field, override_visibility));
+ } else {
+ diagnostics.push(DefDiagnostic::unconfigured_code(
+ container,
+ tree_id,
+ attr_owner,
+ attrs.cfg().unwrap(),
+ cfg_options.clone(),
+ ))
}
- Fields::Unit => (VariantData::Unit, diagnostics),
}
+ (arena, diagnostics)
}
fn lower_field(
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 479beea4a9..f6709680d0 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -47,7 +47,7 @@ use base_db::CrateId;
use either::Either;
use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
use intern::{Interned, Symbol};
-use la_arena::{Arena, Idx, IdxRange, RawIdx};
+use la_arena::{Arena, Idx, RawIdx};
use once_cell::sync::OnceCell;
use rustc_hash::FxHashMap;
use smallvec::SmallVec;
@@ -218,9 +218,7 @@ impl ItemTree {
extern_crates,
extern_blocks,
functions,
- params,
structs,
- fields,
unions,
enums,
variants,
@@ -241,9 +239,7 @@ impl ItemTree {
extern_crates.shrink_to_fit();
extern_blocks.shrink_to_fit();
functions.shrink_to_fit();
- params.shrink_to_fit();
structs.shrink_to_fit();
- fields.shrink_to_fit();
unions.shrink_to_fit();
enums.shrink_to_fit();
variants.shrink_to_fit();
@@ -295,9 +291,7 @@ struct ItemTreeData {
extern_crates: Arena<ExternCrate>,
extern_blocks: Arena<ExternBlock>,
functions: Arena<Function>,
- params: Arena<Param>,
structs: Arena<Struct>,
- fields: Arena<Field>,
unions: Arena<Union>,
enums: Arena<Enum>,
variants: Arena<Variant>,
@@ -315,7 +309,7 @@ struct ItemTreeData {
vis: ItemVisibilities,
}
-#[derive(Debug, Eq, PartialEq, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum AttrOwner {
/// Attributes on an item.
ModItem(ModItem),
@@ -323,12 +317,28 @@ pub enum AttrOwner {
TopLevel,
Variant(FileItemTreeId<Variant>),
- Field(Idx<Field>),
- Param(Idx<Param>),
+ Field(FieldParent, ItemTreeFieldId),
+ Param(FileItemTreeId<Function>, ItemTreeParamId),
TypeOrConstParamData(GenericModItem, LocalTypeOrConstParamId),
LifetimeParamData(GenericModItem, LocalLifetimeParamId),
}
+impl AttrOwner {
+ pub fn make_field_indexed(parent: FieldParent, idx: usize) -> Self {
+ AttrOwner::Field(parent, ItemTreeFieldId::from_raw(RawIdx::from_u32(idx as u32)))
+ }
+}
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub enum FieldParent {
+ Struct(FileItemTreeId<Struct>),
+ Union(FileItemTreeId<Union>),
+ Variant(FileItemTreeId<Variant>),
+}
+
+pub type ItemTreeParamId = Idx<Param>;
+pub type ItemTreeFieldId = Idx<Field>;
+
macro_rules! from_attrs {
( $( $var:ident($t:ty) ),+ $(,)? ) => {
$(
@@ -341,12 +351,7 @@ macro_rules! from_attrs {
};
}
-from_attrs!(
- ModItem(ModItem),
- Variant(FileItemTreeId<Variant>),
- Field(Idx<Field>),
- Param(Idx<Param>),
-);
+from_attrs!(ModItem(ModItem), Variant(FileItemTreeId<Variant>));
/// Trait implemented by all nodes in the item tree.
pub trait ItemTreeNode: Clone {
@@ -365,7 +370,7 @@ pub trait GenericsItemTreeNode: ItemTreeNode {
pub struct FileItemTreeId<N>(Idx<N>);
impl<N> FileItemTreeId<N> {
- pub fn range_iter(range: Range<Self>) -> impl Iterator<Item = Self> {
+ pub fn range_iter(range: Range<Self>) -> impl Iterator<Item = Self> + Clone {
(range.start.index().into_raw().into_u32()..range.end.index().into_raw().into_u32())
.map(RawIdx::from_u32)
.map(Idx::from_raw)
@@ -417,18 +422,18 @@ impl TreeId {
Self { file, block }
}
- pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
+ pub fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
match self.block {
Some(block) => db.block_item_tree(block),
None => db.file_item_tree(self.file),
}
}
- pub(crate) fn file_id(self) -> HirFileId {
+ pub fn file_id(self) -> HirFileId {
self.file
}
- pub(crate) fn is_block(self) -> bool {
+ pub fn is_block(self) -> bool {
self.block.is_some()
}
}
@@ -505,6 +510,27 @@ macro_rules! mod_items {
)+
}
+ impl ModItem {
+ pub fn ast_id(&self, tree: &ItemTree) -> FileAstId<ast::Item> {
+ match self {
+ $(ModItem::$typ(it) => tree[it.index()].ast_id().upcast()),+
+ }
+ }
+ }
+
+ impl GenericModItem {
+ pub fn ast_id(&self, tree: &ItemTree) -> FileAstId<ast::AnyHasGenericParams> {
+ match self {
+ $(
+ $(
+ #[cfg_attr(ignore_fragment, $generic_params)]
+ GenericModItem::$typ(it) => tree[it.index()].ast_id().upcast(),
+ )?
+ )+
+ }
+ }
+ }
+
impl From<GenericModItem> for ModItem {
fn from(id: GenericModItem) -> ModItem {
match id {
@@ -596,22 +622,6 @@ mod_items! {
Macro2 in macro_defs -> ast::MacroDef,
}
-macro_rules! impl_index {
- ( $($fld:ident: $t:ty),+ $(,)? ) => {
- $(
- impl Index<Idx<$t>> for ItemTree {
- type Output = $t;
-
- fn index(&self, index: Idx<$t>) -> &Self::Output {
- &self.data().$fld[index]
- }
- }
- )+
- };
-}
-
-impl_index!(fields: Field, variants: Variant, params: Param);
-
impl Index<RawVisibilityId> for ItemTree {
type Output = RawVisibility;
fn index(&self, index: RawVisibilityId) -> &Self::Output {
@@ -723,7 +733,7 @@ pub struct Function {
pub visibility: RawVisibilityId,
pub explicit_generic_params: Interned<GenericParams>,
pub abi: Option<Symbol>,
- pub params: IdxRange<Param>,
+ pub params: Box<[Param]>,
pub ret_type: Interned<TypeRef>,
pub ast_id: FileAstId<ast::Fn>,
pub(crate) flags: FnFlags,
@@ -731,15 +741,7 @@ pub struct Function {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Param {
- /// This is [`None`] for varargs
- pub type_ref: Option<Interned<TypeRef>>,
- pub ast_id: ParamAstId,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum ParamAstId {
- Param(FileAstId<ast::Param>),
- SelfParam(FileAstId<ast::SelfParam>),
+ pub type_ref: Interned<TypeRef>,
}
bitflags::bitflags! {
@@ -760,7 +762,8 @@ pub struct Struct {
pub name: Name,
pub visibility: RawVisibilityId,
pub generic_params: Interned<GenericParams>,
- pub fields: Fields,
+ pub fields: Box<[Field]>,
+ pub shape: FieldsShape,
pub ast_id: FileAstId<ast::Struct>,
}
@@ -769,7 +772,7 @@ pub struct Union {
pub name: Name,
pub visibility: RawVisibilityId,
pub generic_params: Interned<GenericParams>,
- pub fields: Fields,
+ pub fields: Box<[Field]>,
pub ast_id: FileAstId<ast::Union>,
}
@@ -782,6 +785,29 @@ pub struct Enum {
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,
+ Tuple,
+ Unit,
+}
+
+/// A single field of an enum variant or struct
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Field {
+ pub name: Name,
+ pub type_ref: Interned<TypeRef>,
+ pub visibility: RawVisibilityId,
+}
+
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Const {
/// `None` for `const _: () = ();`
@@ -1039,28 +1065,6 @@ impl ModItem {
&ModItem::Function(func) => Some(AssocItem::Function(func)),
}
}
-
- pub fn ast_id(&self, tree: &ItemTree) -> FileAstId<ast::Item> {
- match self {
- ModItem::Use(it) => tree[it.index()].ast_id().upcast(),
- ModItem::ExternCrate(it) => tree[it.index()].ast_id().upcast(),
- ModItem::ExternBlock(it) => tree[it.index()].ast_id().upcast(),
- ModItem::Function(it) => tree[it.index()].ast_id().upcast(),
- ModItem::Struct(it) => tree[it.index()].ast_id().upcast(),
- ModItem::Union(it) => tree[it.index()].ast_id().upcast(),
- ModItem::Enum(it) => tree[it.index()].ast_id().upcast(),
- ModItem::Const(it) => tree[it.index()].ast_id().upcast(),
- ModItem::Static(it) => tree[it.index()].ast_id().upcast(),
- ModItem::Trait(it) => tree[it.index()].ast_id().upcast(),
- ModItem::TraitAlias(it) => tree[it.index()].ast_id().upcast(),
- ModItem::Impl(it) => tree[it.index()].ast_id().upcast(),
- ModItem::TypeAlias(it) => tree[it.index()].ast_id().upcast(),
- ModItem::Mod(it) => tree[it.index()].ast_id().upcast(),
- ModItem::MacroCall(it) => tree[it.index()].ast_id().upcast(),
- ModItem::MacroRules(it) => tree[it.index()].ast_id().upcast(),
- ModItem::Macro2(it) => tree[it.index()].ast_id().upcast(),
- }
- }
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
@@ -1099,32 +1103,3 @@ impl AssocItem {
}
}
}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct Variant {
- pub name: Name,
- pub fields: Fields,
- pub ast_id: FileAstId<ast::Variant>,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum Fields {
- Record(IdxRange<Field>),
- Tuple(IdxRange<Field>),
- Unit,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum FieldAstId {
- Record(FileAstId<ast::RecordField>),
- Tuple(FileAstId<ast::TupleField>),
-}
-
-/// A single field of an enum variant or struct
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct Field {
- pub name: Name,
- pub type_ref: Interned<TypeRef>,
- pub visibility: RawVisibilityId,
- pub ast_id: FieldAstId,
-}
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index 67092ae0c0..c9e9719c90 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -17,12 +17,12 @@ use crate::{
db::DefDatabase,
generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance},
item_tree::{
- AssocItem, AttrOwner, Const, Either, Enum, ExternBlock, ExternCrate, Field, FieldAstId,
- Fields, FileItemTreeId, FnFlags, Function, GenericArgs, GenericModItem, Idx, IdxRange,
- Impl, ImportAlias, Interned, ItemTree, ItemTreeData, ItemTreeNode, Macro2, MacroCall,
- MacroRules, Mod, ModItem, ModKind, ModPath, Mutability, Name, Param, ParamAstId, Path,
- Range, RawAttrs, RawIdx, RawVisibilityId, Static, Struct, StructKind, Trait, TraitAlias,
- TypeAlias, Union, Use, UseTree, UseTreeKind, Variant,
+ AssocItem, AttrOwner, Const, Either, Enum, ExternBlock, ExternCrate, Field, FieldParent,
+ FieldsShape, FileItemTreeId, FnFlags, Function, GenericArgs, GenericModItem, Idx, Impl,
+ ImportAlias, Interned, ItemTree, ItemTreeData, Macro2, MacroCall, MacroRules, Mod, ModItem,
+ ModKind, ModPath, Mutability, Name, Param, Path, Range, RawAttrs, RawIdx, RawVisibilityId,
+ Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
+ Variant,
},
path::AssociatedTypeBinding,
type_ref::{LifetimeRef, TraitBoundModifier, TraitRef, TypeBound, TypeRef},
@@ -30,7 +30,7 @@ use crate::{
LocalLifetimeParamId, LocalTypeOrConstParamId,
};
-fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> {
+fn id<N>(index: Idx<N>) -> FileItemTreeId<N> {
FileItemTreeId(index)
}
@@ -193,82 +193,98 @@ impl<'a> Ctx<'a> {
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 = self.lower_fields(&strukt.kind());
+ let (fields, kind, attrs) = self.lower_fields(&strukt.kind());
let generic_params = self.lower_generic_params(HasImplicitSelf::No, strukt);
- let res = Struct { name, visibility, generic_params, fields, ast_id };
+ let res = Struct { name, visibility, generic_params, fields, shape: kind, 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,
+ );
+ }
self.write_generic_params_attributes(id.into());
Some(id)
}
- fn lower_fields(&mut self, strukt_kind: &ast::StructKind) -> Fields {
+ fn lower_fields(
+ &mut self,
+ strukt_kind: &ast::StructKind,
+ ) -> (Box<[Field]>, FieldsShape, Vec<(usize, RawAttrs)>) {
match strukt_kind {
ast::StructKind::Record(it) => {
- let range = self.lower_record_fields(it);
- Fields::Record(range)
+ 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.upcast(), &field, self.span_map());
+ if !attr.is_empty() {
+ attrs.push((i, attr))
+ }
+ }
+ (fields.into(), FieldsShape::Record, attrs)
}
ast::StructKind::Tuple(it) => {
- let range = self.lower_tuple_fields(it);
- Fields::Tuple(range)
- }
- ast::StructKind::Unit => Fields::Unit,
- }
- }
-
- fn lower_record_fields(&mut self, fields: &ast::RecordFieldList) -> IdxRange<Field> {
- let start = self.next_field_idx();
- for field in fields.fields() {
- if let Some(data) = self.lower_record_field(&field) {
- let idx = self.data().fields.alloc(data);
- self.add_attrs(
- idx.into(),
- RawAttrs::new(self.db.upcast(), &field, self.span_map()),
- );
+ 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.upcast(), &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()),
}
- let end = self.next_field_idx();
- IdxRange::new(start..end)
}
- fn lower_record_field(&mut self, field: &ast::RecordField) -> Option<Field> {
- let name = field.name()?.as_name();
+ 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);
let type_ref = self.lower_type_ref_opt(field.ty());
- let ast_id = FieldAstId::Record(self.source_ast_id_map.ast_id(field));
- let res = Field { name, type_ref, visibility, ast_id };
- Some(res)
- }
- fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldList) -> IdxRange<Field> {
- let start = self.next_field_idx();
- for (i, field) in fields.fields().enumerate() {
- let data = self.lower_tuple_field(i, &field);
- let idx = self.data().fields.alloc(data);
- self.add_attrs(idx.into(), RawAttrs::new(self.db.upcast(), &field, self.span_map()));
- }
- let end = self.next_field_idx();
- IdxRange::new(start..end)
+ Field { name, type_ref, visibility }
}
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);
let type_ref = self.lower_type_ref_opt(field.ty());
- let ast_id = FieldAstId::Tuple(self.source_ast_id_map.ast_id(field));
- Field { name, type_ref, visibility, ast_id }
+ Field { name, type_ref, visibility }
}
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 = match union.record_field_list() {
+ let (fields, _, attrs) = match union.record_field_list() {
Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)),
- None => Fields::Record(IdxRange::new(self.next_field_idx()..self.next_field_idx())),
+ None => (Box::default(), FieldsShape::Record, Vec::default()),
};
let generic_params = self.lower_generic_params(HasImplicitSelf::No, union);
let res = Union { name, visibility, generic_params, fields, 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,
+ );
+ }
self.write_generic_params_attributes(id.into());
Some(id)
}
@@ -293,24 +309,35 @@ impl<'a> Ctx<'a> {
fn lower_variants(&mut self, variants: &ast::VariantList) -> Range<FileItemTreeId<Variant>> {
let start = self.next_variant_idx();
for variant in variants.variants() {
- if let Some(data) = self.lower_variant(&variant) {
- let idx = self.data().variants.alloc(data);
- self.add_attrs(
- id(idx).into(),
- RawAttrs::new(self.db.upcast(), &variant, self.span_map()),
- );
- }
+ let idx = self.lower_variant(&variant);
+ self.add_attrs(
+ id(idx).into(),
+ RawAttrs::new(self.db.upcast(), &variant, self.span_map()),
+ );
}
let end = self.next_variant_idx();
FileItemTreeId(start)..FileItemTreeId(end)
}
- fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> {
- let name = variant.name()?.as_name();
- let fields = self.lower_fields(&variant.kind());
+ 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, ast_id };
- Some(res)
+ 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::Variant(FileItemTreeId(id)),
+ Idx::from_raw(RawIdx::from_u32(idx as u32)),
+ ),
+ attr,
+ );
+ }
+ id
}
fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>> {
@@ -318,9 +345,20 @@ impl<'a> Ctx<'a> {
let name = func.name()?.as_name();
let mut has_self_param = false;
- let start_param = self.next_param_idx();
+ let mut has_var_args = false;
+ let mut params = vec![];
+ let mut attrs = vec![];
+ let mut push_attr = |idx, attr: RawAttrs| {
+ if !attr.is_empty() {
+ attrs.push((idx, attr))
+ }
+ };
if let Some(param_list) = func.param_list() {
if let Some(self_param) = param_list.self_param() {
+ push_attr(
+ params.len(),
+ RawAttrs::new(self.db.upcast(), &self_param, self.span_map()),
+ );
let self_type = match self_param.ty() {
Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref),
None => {
@@ -342,40 +380,25 @@ impl<'a> Ctx<'a> {
}
};
let type_ref = Interned::new(self_type);
- let ast_id = self.source_ast_id_map.ast_id(&self_param);
- let idx = self.data().params.alloc(Param {
- type_ref: Some(type_ref),
- ast_id: ParamAstId::SelfParam(ast_id),
- });
- self.add_attrs(
- idx.into(),
- RawAttrs::new(self.db.upcast(), &self_param, self.span_map()),
- );
+ params.push(Param { type_ref });
has_self_param = true;
}
for param in param_list.params() {
- let ast_id = self.source_ast_id_map.ast_id(&param);
- let idx = match param.dotdotdot_token() {
- Some(_) => self
- .data()
- .params
- .alloc(Param { type_ref: None, ast_id: ParamAstId::Param(ast_id) }),
+ push_attr(params.len(), RawAttrs::new(self.db.upcast(), &param, self.span_map()));
+ let param = match param.dotdotdot_token() {
+ Some(_) => {
+ has_var_args = true;
+ Param { type_ref: Interned::new(TypeRef::Error) }
+ }
None => {
let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty());
let ty = Interned::new(type_ref);
- self.data()
- .params
- .alloc(Param { type_ref: Some(ty), ast_id: ParamAstId::Param(ast_id) })
+ Param { type_ref: ty }
}
};
- self.add_attrs(
- idx.into(),
- RawAttrs::new(self.db.upcast(), &param, self.span_map()),
- );
+ params.push(param);
}
}
- let end_param = self.next_param_idx();
- let params = IdxRange::new(start_param..end_param);
let ret_type = match func.ret_type() {
Some(rt) => match rt.ty() {
@@ -417,19 +440,25 @@ impl<'a> Ctx<'a> {
if func.unsafe_token().is_some() {
flags |= FnFlags::HAS_UNSAFE_KW;
}
+ if has_var_args {
+ flags |= FnFlags::IS_VARARGS;
+ }
let res = Function {
name,
visibility,
explicit_generic_params: self.lower_generic_params(HasImplicitSelf::No, func),
abi,
- params,
+ params: params.into_boxed_slice(),
ret_type: Interned::new(ret_type),
ast_id,
flags,
};
let id = id(self.data().functions.alloc(res));
+ for (idx, attr) in attrs {
+ self.add_attrs(AttrOwner::Param(id, Idx::from_raw(RawIdx::from_u32(idx as u32))), attr);
+ }
self.write_generic_params_attributes(id.into());
Some(id)
}
@@ -725,21 +754,11 @@ impl<'a> Ctx<'a> {
}
}
- fn next_field_idx(&self) -> Idx<Field> {
- Idx::from_raw(RawIdx::from(
- self.tree.data.as_ref().map_or(0, |data| data.fields.len() as u32),
- ))
- }
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 next_param_idx(&self) -> Idx<Param> {
- Idx::from_raw(RawIdx::from(
- self.tree.data.as_ref().map_or(0, |data| data.params.len() as u32),
- ))
- }
}
fn desugar_future_path(orig: TypeRef) -> Path {
diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs
index 6283ae23b5..5eeb8607b9 100644
--- a/crates/hir-def/src/item_tree/pretty.rs
+++ b/crates/hir-def/src/item_tree/pretty.rs
@@ -2,16 +2,17 @@
use std::fmt::{self, Write};
+use la_arena::{Idx, RawIdx};
use span::ErasedFileAstId;
use crate::{
generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget},
item_tree::{
- AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldAstId, Fields,
- FileItemTreeId, FnFlags, Function, GenericModItem, GenericParams, Impl, Interned, ItemTree,
- Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, Param, ParamAstId, Path, RawAttrs,
- RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound, TypeRef, Union,
- Use, UseTree, UseTreeKind, Variant,
+ AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldParent,
+ FieldsShape, FileItemTreeId, FnFlags, Function, GenericModItem, GenericParams, Impl,
+ Interned, ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, Param, Path,
+ RawAttrs, RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound,
+ TypeRef, Union, Use, UseTree, UseTreeKind, Variant,
},
pretty::{print_path, print_type_bounds, print_type_ref},
visibility::RawVisibility,
@@ -118,19 +119,17 @@ impl Printer<'_> {
};
}
- fn print_fields(&mut self, fields: &Fields) {
- match fields {
- Fields::Record(fields) => {
+ fn print_fields(&mut self, parent: FieldParent, kind: FieldsShape, fields: &[Field]) {
+ match kind {
+ FieldsShape::Record => {
self.whitespace();
w!(self, "{{");
self.indented(|this| {
- for field in fields.clone() {
- let Field { visibility, name, type_ref, ast_id } = &this.tree[field];
- this.print_ast_id(match ast_id {
- FieldAstId::Record(it) => it.erase(),
- FieldAstId::Tuple(it) => it.erase(),
- });
- this.print_attrs_of(field, "\n");
+ for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() {
+ this.print_attrs_of(
+ AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
+ "\n",
+ );
this.print_visibility(*visibility);
w!(this, "{}: ", name.display(self.db.upcast()));
this.print_type_ref(type_ref);
@@ -139,16 +138,14 @@ impl Printer<'_> {
});
w!(self, "}}");
}
- Fields::Tuple(fields) => {
+ FieldsShape::Tuple => {
w!(self, "(");
self.indented(|this| {
- for field in fields.clone() {
- let Field { visibility, name, type_ref, ast_id } = &this.tree[field];
- this.print_ast_id(match ast_id {
- FieldAstId::Record(it) => it.erase(),
- FieldAstId::Tuple(it) => it.erase(),
- });
- this.print_attrs_of(field, "\n");
+ for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() {
+ this.print_attrs_of(
+ AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
+ "\n",
+ );
this.print_visibility(*visibility);
w!(this, "{}: ", name.display(self.db.upcast()));
this.print_type_ref(type_ref);
@@ -157,24 +154,30 @@ impl Printer<'_> {
});
w!(self, ")");
}
- Fields::Unit => {}
+ FieldsShape::Unit => {}
}
}
- fn print_fields_and_where_clause(&mut self, fields: &Fields, params: &GenericParams) {
- match fields {
- Fields::Record(_) => {
+ fn print_fields_and_where_clause(
+ &mut self,
+ parent: FieldParent,
+ kind: FieldsShape,
+ fields: &[Field],
+ params: &GenericParams,
+ ) {
+ match kind {
+ FieldsShape::Record => {
if self.print_where_clause(params) {
wln!(self);
}
- self.print_fields(fields);
+ self.print_fields(parent, kind, fields);
}
- Fields::Unit => {
+ FieldsShape::Unit => {
self.print_where_clause(params);
- self.print_fields(fields);
+ self.print_fields(parent, kind, fields);
}
- Fields::Tuple(_) => {
- self.print_fields(fields);
+ FieldsShape::Tuple => {
+ self.print_fields(parent, kind, fields);
self.print_where_clause(params);
}
}
@@ -280,25 +283,20 @@ impl Printer<'_> {
w!(self, "(");
if !params.is_empty() {
self.indented(|this| {
- for param in params.clone() {
- this.print_attrs_of(param, "\n");
- let Param { type_ref, ast_id } = &this.tree[param];
- this.print_ast_id(match ast_id {
- ParamAstId::Param(it) => it.erase(),
- ParamAstId::SelfParam(it) => it.erase(),
- });
- match type_ref {
- Some(ty) => {
- if flags.contains(FnFlags::HAS_SELF_PARAM) {
- w!(this, "self: ");
- }
- this.print_type_ref(ty);
- wln!(this, ",");
- }
- None => {
- wln!(this, "...");
- }
- };
+ for (idx, Param { type_ref }) in params.iter().enumerate() {
+ this.print_attrs_of(
+ AttrOwner::Param(it, Idx::from_raw(RawIdx::from(idx as u32))),
+ "\n",
+ );
+ if idx == 0 && flags.contains(FnFlags::HAS_SELF_PARAM) {
+ w!(this, "self: ");
+ }
+ if idx != params.len() {
+ this.print_type_ref(type_ref);
+ } else {
+ wln!(this, "...");
+ }
+ wln!(this, ",");
}
});
}
@@ -312,13 +310,19 @@ impl Printer<'_> {
}
}
ModItem::Struct(it) => {
- let Struct { visibility, name, fields, generic_params, ast_id } = &self.tree[it];
+ let Struct { visibility, name, fields, shape: kind, generic_params, ast_id } =
+ &self.tree[it];
self.print_ast_id(ast_id.erase());
self.print_visibility(*visibility);
w!(self, "struct {}", name.display(self.db.upcast()));
self.print_generic_params(generic_params, it.into());
- self.print_fields_and_where_clause(fields, generic_params);
- if matches!(fields, Fields::Record(_)) {
+ self.print_fields_and_where_clause(
+ FieldParent::Struct(it),
+ *kind,
+ fields,
+ generic_params,
+ );
+ if matches!(kind, FieldsShape::Record) {
wln!(self);
} else {
wln!(self, ";");
@@ -330,12 +334,13 @@ impl Printer<'_> {
self.print_visibility(*visibility);
w!(self, "union {}", name.display(self.db.upcast()));
self.print_generic_params(generic_params, it.into());
- self.print_fields_and_where_clause(fields, generic_params);
- if matches!(fields, Fields::Record(_)) {
- wln!(self);
- } else {
- wln!(self, ";");
- }
+ self.print_fields_and_where_clause(
+ FieldParent::Union(it),
+ FieldsShape::Record,
+ fields,
+ generic_params,
+ );
+ wln!(self);
}
ModItem::Enum(it) => {
let Enum { name, visibility, variants, generic_params, ast_id } = &self.tree[it];
@@ -346,11 +351,11 @@ impl Printer<'_> {
self.print_where_clause_and_opening_brace(generic_params);
self.indented(|this| {
for variant in FileItemTreeId::range_iter(variants.clone()) {
- let Variant { name, fields, ast_id } = &this.tree[variant];
+ 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.upcast()));
- this.print_fields(fields);
+ this.print_fields(FieldParent::Variant(variant), *kind, fields);
wln!(this, ",");
}
});
diff --git a/crates/hir-def/src/item_tree/tests.rs b/crates/hir-def/src/item_tree/tests.rs
index 79bab11998..c6930401a6 100644
--- a/crates/hir-def/src/item_tree/tests.rs
+++ b/crates/hir-def/src/item_tree/tests.rs
@@ -129,40 +129,34 @@ enum E {
#[derive(Debug)]
// AstId: 2
pub(self) struct Struct {
- // AstId: 6
#[doc = " fld docs"]
pub(self) fld: (),
}
// AstId: 3
pub(self) struct Tuple(
- // AstId: 7
#[attr]
pub(self) 0: u8,
);
// AstId: 4
pub(self) union Ize {
- // AstId: 8
pub(self) a: (),
- // AstId: 9
pub(self) b: (),
}
// AstId: 5
pub(self) enum E {
- // AstId: 10
+ // AstId: 6
#[doc = " comment on Unit"]
Unit,
- // AstId: 11
+ // AstId: 7
#[doc = " comment on Tuple"]
Tuple(
- // AstId: 13
pub(self) 0: u8,
),
- // AstId: 12
+ // AstId: 8
Struct {
- // AstId: 14
#[doc = " comment on a: u8"]
pub(self) a: u8,
},
@@ -201,9 +195,7 @@ trait Tr: SuperTrait + 'lifetime {
// AstId: 3
pub(self) fn f(
#[attr]
- // AstId: 5
u8,
- // AstId: 6
(),
) -> () { ... }
@@ -213,12 +205,11 @@ trait Tr: SuperTrait + 'lifetime {
Self: SuperTrait,
Self: 'lifetime
{
- // AstId: 8
+ // AstId: 6
pub(self) type Assoc: AssocBound = Default;
- // AstId: 9
+ // AstId: 7
pub(self) fn method(
- // AstId: 10
self: &Self,
) -> ();
}
@@ -300,17 +291,11 @@ struct S {
expect![[r#"
// AstId: 1
pub(self) struct S {
- // AstId: 2
pub(self) a: self::Ty,
- // AstId: 3
pub(self) b: super::SuperTy,
- // AstId: 4
pub(self) c: super::super::SuperSuperTy,
- // AstId: 5
pub(self) d: ::abs::Path,
- // AstId: 6
pub(self) e: crate::Crate,
- // AstId: 7
pub(self) f: plain::path::Ty,
}
"#]],
@@ -331,13 +316,9 @@ struct S {
expect![[r#"
// AstId: 1
pub(self) struct S {
- // AstId: 2
pub(self) a: Mixed::<'a, T, Item = (), OtherItem = u8>,
- // AstId: 3
pub(self) b: Qualified::<Self=Fully>::Syntax,
- // AstId: 4
pub(self) c: <TypeAnchored>::Path::<'a>,
- // AstId: 5
pub(self) d: dyn for<'a> Trait::<'a>,
}
"#]],
@@ -371,15 +352,12 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
T: 'a,
T: 'b
{
- // AstId: 8
pub(self) field: &'a &'b T,
}
// AstId: 2
pub(self) struct Tuple<T, U>(
- // AstId: 9
pub(self) 0: T,
- // AstId: 10
pub(self) 1: U,
)
where
@@ -393,9 +371,8 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
T: 'a,
T: 'b
{
- // AstId: 12
+ // AstId: 9
pub(self) fn f<G>(
- // AstId: 13
impl Copy,
) -> impl Copy
where
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 58aca96429..c51eea22dc 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -23,7 +23,7 @@ use itertools::{izip, Itertools};
use la_arena::Idx;
use limit::Limit;
use rustc_hash::{FxHashMap, FxHashSet};
-use span::{Edition, EditionedFileId, ErasedFileAstId, FileAstId, SyntaxContextId};
+use span::{Edition, EditionedFileId, FileAstId, SyntaxContextId};
use syntax::ast;
use triomphe::Arc;
@@ -32,8 +32,8 @@ use crate::{
db::DefDatabase,
item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
item_tree::{
- self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
- Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
+ self, AttrOwner, ExternCrate, FieldsShape, FileItemTreeId, ImportKind, ItemTree,
+ ItemTreeId, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
},
macro_call_as_call_id, macro_call_as_call_id_with_eager,
nameres::{
@@ -1580,10 +1580,7 @@ impl ModCollector<'_, '_> {
let attrs = self.item_tree.attrs(db, krate, item.into());
if let Some(cfg) = attrs.cfg() {
if !self.is_cfg_enabled(&cfg) {
- self.emit_unconfigured_diagnostic(
- InFile::new(self.file_id(), item.ast_id(self.item_tree).erase()),
- &cfg,
- );
+ self.emit_unconfigured_diagnostic(self.tree_id, item.into(), &cfg);
return;
}
}
@@ -1699,7 +1696,7 @@ impl ModCollector<'_, '_> {
.into(),
&it.name,
vis,
- !matches!(it.fields, Fields::Record(_)),
+ !matches!(it.shape, FieldsShape::Record),
);
}
ModItem::Union(id) => {
@@ -1737,10 +1734,8 @@ impl ModCollector<'_, '_> {
match is_enabled {
Err(cfg) => {
self.emit_unconfigured_diagnostic(
- InFile::new(
- self.file_id(),
- self.item_tree[variant.index()].ast_id.erase(),
- ),
+ self.tree_id,
+ variant.into(),
&cfg,
);
None
@@ -1956,7 +1951,8 @@ impl ModCollector<'_, '_> {
match is_enabled {
Err(cfg) => {
self.emit_unconfigured_diagnostic(
- ast_id.map(|it| it.erase()),
+ self.tree_id,
+ AttrOwner::TopLevel,
&cfg,
);
}
@@ -2402,10 +2398,11 @@ impl ModCollector<'_, '_> {
self.def_collector.cfg_options.check(cfg) != Some(false)
}
- fn emit_unconfigured_diagnostic(&mut self, ast_id: InFile<ErasedFileAstId>, cfg: &CfgExpr) {
+ fn emit_unconfigured_diagnostic(&mut self, tree_id: TreeId, item: AttrOwner, cfg: &CfgExpr) {
self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
self.module_id,
- ast_id,
+ tree_id,
+ item,
cfg.clone(),
self.def_collector.cfg_options.clone(),
));
diff --git a/crates/hir-def/src/nameres/diagnostics.rs b/crates/hir-def/src/nameres/diagnostics.rs
index 4ab53d20b5..e1bd6966f3 100644
--- a/crates/hir-def/src/nameres/diagnostics.rs
+++ b/crates/hir-def/src/nameres/diagnostics.rs
@@ -4,12 +4,12 @@ use std::ops::Not;
use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
-use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind};
+use hir_expand::{attrs::AttrId, MacroCallKind};
use la_arena::Idx;
use syntax::ast;
use crate::{
- item_tree::{self, ItemTreeId},
+ item_tree::{self, AttrOwner, ItemTreeId, TreeId},
nameres::LocalModuleId,
path::ModPath,
AstId,
@@ -29,7 +29,8 @@ pub enum DefDiagnosticKind {
index: Idx<ast::UseTree>,
},
UnconfiguredCode {
- ast: ErasedAstId,
+ tree: TreeId,
+ item: AttrOwner,
cfg: CfgExpr,
opts: CfgOptions,
},
@@ -116,11 +117,15 @@ impl DefDiagnostic {
pub fn unconfigured_code(
container: LocalModuleId,
- ast: ErasedAstId,
+ tree: TreeId,
+ item: AttrOwner,
cfg: CfgExpr,
opts: CfgOptions,
) -> Self {
- Self { in_module: container, kind: DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } }
+ Self {
+ in_module: container,
+ kind: DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts },
+ }
}
pub fn unresolved_proc_macro(
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index e797d19223..75cab137f7 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/crates/hir-def/src/nameres/path_resolution.rs
@@ -17,7 +17,7 @@ use triomphe::Arc;
use crate::{
db::DefDatabase,
item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
- item_tree::Fields,
+ item_tree::FieldsShape,
nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs},
path::{ModPath, PathKind},
per_ns::PerNs,
@@ -381,11 +381,11 @@ impl DefMap {
.iter()
.find_map(|&variant| {
let variant_data = &tree[variant.lookup(db).id.value];
- (variant_data.name == *segment).then(|| match variant_data.fields {
- Fields::Record(_) => {
+ (variant_data.name == *segment).then(|| match variant_data.shape {
+ FieldsShape::Record => {
PerNs::types(variant.into(), Visibility::Public, None)
}
- Fields::Tuple(_) | Fields::Unit => PerNs::both(
+ FieldsShape::Tuple | FieldsShape::Unit => PerNs::both(
variant.into(),
variant.into(),
Visibility::Public,
diff --git a/crates/hir-def/src/src.rs b/crates/hir-def/src/src.rs
index a0d2079e0d..6db20870cf 100644
--- a/crates/hir-def/src/src.rs
+++ b/crates/hir-def/src/src.rs
@@ -6,9 +6,12 @@ use la_arena::ArenaMap;
use syntax::{ast, AstNode, AstPtr};
use crate::{
- data::adt::lower_struct, db::DefDatabase, item_tree::ItemTreeNode, trace::Trace, GenericDefId,
- ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, UseId,
- VariantId,
+ data::adt::lower_struct,
+ db::DefDatabase,
+ item_tree::{FieldParent, ItemTreeNode},
+ trace::Trace,
+ GenericDefId, ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup,
+ UseId, VariantId,
};
pub trait HasSource {
@@ -124,13 +127,13 @@ impl HasChildSource<LocalFieldId> for VariantId {
fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<LocalFieldId, Self::Value>> {
let item_tree;
- let (src, fields, container) = match *self {
+ let (src, parent, container) = match *self {
VariantId::EnumVariantId(it) => {
let lookup = it.lookup(db);
item_tree = lookup.id.item_tree(db);
(
lookup.source(db).map(|it| it.kind()),
- &item_tree[lookup.id.value].fields,
+ FieldParent::Variant(lookup.id.value),
lookup.parent.lookup(db).container,
)
}
@@ -139,7 +142,7 @@ impl HasChildSource<LocalFieldId> for VariantId {
item_tree = lookup.id.item_tree(db);
(
lookup.source(db).map(|it| it.kind()),
- &item_tree[lookup.id.value].fields,
+ FieldParent::Struct(lookup.id.value),
lookup.container,
)
}
@@ -148,13 +151,13 @@ impl HasChildSource<LocalFieldId> for VariantId {
item_tree = lookup.id.item_tree(db);
(
lookup.source(db).map(|it| it.kind()),
- &item_tree[lookup.id.value].fields,
+ FieldParent::Union(lookup.id.value),
lookup.container,
)
}
};
let mut trace = Trace::new_for_map();
- lower_struct(db, &mut trace, &src, container.krate, &item_tree, fields);
+ lower_struct(db, &mut trace, &src, container.krate, &item_tree, parent);
src.with_value(trace.into_map())
}
}
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 82f4ad01e0..284291bb9a 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -812,7 +812,9 @@ impl<'a> InferenceContext<'a> {
None => self.err_ty(),
};
- param_tys.push(va_list_ty)
+ if let Some(ty) = param_tys.last_mut() {
+ *ty = va_list_ty;
+ }
}
let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.new_type_var()));
if let Some(self_param) = self.body.self_param {
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index f80ccf84a2..a40022c43a 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -99,7 +99,13 @@ impl HirDisplay for Function {
}
// FIXME: Use resolved `param.ty` once we no longer discard lifetimes
- for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)).skip(skip_self) {
+ for (type_ref, param) in data
+ .params
+ .iter()
+ .zip(self.assoc_fn_params(db))
+ .take(data.params.len() - data.is_varargs() as usize)
+ .skip(skip_self)
+ {
let local = param.as_local(db).map(|it| it.name(db));
if !first {
f.write_str(", ")?;
@@ -114,7 +120,10 @@ impl HirDisplay for Function {
}
if data.is_varargs() {
- f.write_str(", ...")?;
+ if !first {
+ f.write_str(", ")?;
+ }
+ f.write_str("...")?;
}
f.write_char(')')?;
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index dd9f1e8803..70f4a632fb 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -44,7 +44,7 @@ use hir_def::{
data::adt::VariantData,
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat},
- item_tree::ItemTreeNode,
+ item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
lang_item::LangItemTarget,
layout::{self, ReprOptions, TargetDataLayout},
nameres::{self, diagnostics::DefDiagnostic},
@@ -81,7 +81,7 @@ use rustc_hash::FxHashSet;
use span::{Edition, EditionedFileId, FileId, MacroCallId};
use stdx::{impl_from, never};
use syntax::{
- ast::{self, HasAttrs as _, HasName},
+ ast::{self, HasAttrs as _, HasGenericParams, HasName},
format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr, T,
};
use triomphe::Arc;
@@ -906,12 +906,90 @@ fn emit_def_diagnostic_(
);
}
- DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
- let item = ast.to_ptr(db.upcast());
- acc.push(
- InactiveCode { node: ast.with_value(item), cfg: cfg.clone(), opts: opts.clone() }
+ DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts } => {
+ let item_tree = tree.item_tree(db.upcast());
+ let ast_id_map = db.ast_id_map(tree.file_id());
+ // FIXME: This parses... We could probably store relative ranges for the children things
+ // here in the item tree?
+ (|| {
+ let process_field_list =
+ |field_list: Option<_>, idx: ItemTreeFieldId| match field_list? {
+ ast::FieldList::RecordFieldList(it) => Some(SyntaxNodePtr::new(
+ it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(),
+ )),
+ ast::FieldList::TupleFieldList(it) => Some(SyntaxNodePtr::new(
+ it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(),
+ )),
+ };
+ let ptr = match *item {
+ AttrOwner::ModItem(it) => {
+ ast_id_map.get(it.ast_id(&item_tree)).syntax_node_ptr()
+ }
+ AttrOwner::TopLevel => ast_id_map.root(),
+ AttrOwner::Variant(it) => {
+ ast_id_map.get(item_tree[it].ast_id).syntax_node_ptr()
+ }
+ AttrOwner::Field(FieldParent::Variant(parent), idx) => process_field_list(
+ ast_id_map
+ .get(item_tree[parent].ast_id)
+ .to_node(&db.parse_or_expand(tree.file_id()))
+ .field_list(),
+ idx,
+ )?,
+ AttrOwner::Field(FieldParent::Struct(parent), idx) => process_field_list(
+ ast_id_map
+ .get(item_tree[parent.index()].ast_id)
+ .to_node(&db.parse_or_expand(tree.file_id()))
+ .field_list(),
+ idx,
+ )?,
+ AttrOwner::Field(FieldParent::Union(parent), idx) => SyntaxNodePtr::new(
+ ast_id_map
+ .get(item_tree[parent.index()].ast_id)
+ .to_node(&db.parse_or_expand(tree.file_id()))
+ .record_field_list()?
+ .fields()
+ .nth(idx.into_raw().into_u32() as usize)?
+ .syntax(),
+ ),
+ AttrOwner::Param(parent, idx) => SyntaxNodePtr::new(
+ ast_id_map
+ .get(item_tree[parent.index()].ast_id)
+ .to_node(&db.parse_or_expand(tree.file_id()))
+ .param_list()?
+ .params()
+ .nth(idx.into_raw().into_u32() as usize)?
+ .syntax(),
+ ),
+ AttrOwner::TypeOrConstParamData(parent, idx) => SyntaxNodePtr::new(
+ ast_id_map
+ .get(parent.ast_id(&item_tree))
+ .to_node(&db.parse_or_expand(tree.file_id()))
+ .generic_param_list()?
+ .type_or_const_params()
+ .nth(idx.into_raw().into_u32() as usize)?
+ .syntax(),
+ ),
+ AttrOwner::LifetimeParamData(parent, idx) => SyntaxNodePtr::new(
+ ast_id_map
+ .get(parent.ast_id(&item_tree))
+ .to_node(&db.parse_or_expand(tree.file_id()))
+ .generic_param_list()?
+ .lifetime_params()
+ .nth(idx.into_raw().into_u32() as usize)?
+ .syntax(),
+ ),
+ };
+ acc.push(
+ InactiveCode {
+ node: InFile::new(tree.file_id(), ptr),
+ cfg: cfg.clone(),
+ opts: opts.clone(),
+ }
.into(),
- );
+ );
+ Some(())
+ })();
}
DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => {
let (node, precise_location, macro_name, kind) = precise_macro_call_location(ast, db);
diff --git a/crates/span/src/ast_id.rs b/crates/span/src/ast_id.rs
index 332745aae6..b61baa2244 100644
--- a/crates/span/src/ast_id.rs
+++ b/crates/span/src/ast_id.rs
@@ -80,13 +80,11 @@ macro_rules! register_ast_id_node {
}
register_ast_id_node! {
impl AstIdNode for
- Item,
+ Item, AnyHasGenericParams,
Adt,
Enum,
Variant,
Struct,
- RecordField,
- TupleField,
Union,
AssocItem,
Const,
@@ -104,7 +102,7 @@ register_ast_id_node! {
Trait,
TraitAlias,
Use,
- BlockExpr, ConstArg, Param, SelfParam
+ BlockExpr, ConstArg
}
/// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.