Remove Params and Fields from AstIdMap

This commit is contained in:
Lukas Wirth 2024-07-25 10:18:06 +02:00
parent 200a01adc4
commit 9cbafa2d49
16 changed files with 494 additions and 449 deletions

View file

@ -20,7 +20,7 @@ use triomphe::Arc;
use crate::{ use crate::{
db::DefDatabase, db::DefDatabase,
item_tree::{AttrOwner, Fields, ItemTreeNode}, item_tree::{AttrOwner, FieldParent, ItemTreeNode},
lang_item::LangItem, lang_item::LangItem,
nameres::{ModuleOrigin, ModuleSource}, nameres::{ModuleOrigin, ModuleSource},
src::{HasChildSource, HasSource}, src::{HasChildSource, HasSource},
@ -76,40 +76,36 @@ impl Attrs {
let mut res = ArenaMap::default(); let mut res = ArenaMap::default();
let crate_graph = db.crate_graph(); 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) => { VariantId::EnumVariantId(it) => {
let loc = it.lookup(db); let loc = it.lookup(db);
let krate = loc.parent.lookup(db).container.krate; 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]; let variant = &item_tree[loc.id.value];
(variant.fields.clone(), item_tree, krate) (FieldParent::Variant(loc.id.value), &variant.fields, krate)
} }
VariantId::StructId(it) => { VariantId::StructId(it) => {
let loc = it.lookup(db); let loc = it.lookup(db);
let krate = loc.container.krate; 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]; let struct_ = &item_tree[loc.id.value];
(struct_.fields.clone(), item_tree, krate) (FieldParent::Struct(loc.id.value), &struct_.fields, krate)
} }
VariantId::UnionId(it) => { VariantId::UnionId(it) => {
let loc = it.lookup(db); let loc = it.lookup(db);
let krate = loc.container.krate; 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]; 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 cfg_options = &crate_graph[krate].cfg_options;
let mut idx = 0; let mut idx = 0;
for field in fields { for (id, _field) in fields.iter().enumerate() {
let attrs = item_tree.attrs(db, krate, field.into()); let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, id));
if attrs.is_cfg_enabled(cfg_options) { if attrs.is_cfg_enabled(cfg_options) {
res.insert(Idx::from_raw(RawIdx::from(idx)), attrs); res.insert(Idx::from_raw(RawIdx::from(idx)), attrs);
idx += 1; idx += 1;

View file

@ -11,7 +11,7 @@ use std::ops::{Deref, Index};
use base_db::CrateId; use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions}; use cfg::{CfgExpr, CfgOptions};
use hir_expand::{name::Name, InFile}; use hir_expand::{name::Name, InFile};
use la_arena::{Arena, ArenaMap}; use la_arena::{Arena, ArenaMap, Idx, RawIdx};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use smallvec::SmallVec; use smallvec::SmallVec;
use span::MacroFileId; use span::MacroFileId;
@ -24,6 +24,7 @@ use crate::{
hir::{ hir::{
dummy_expr_id, Binding, BindingId, Expr, ExprId, Label, LabelId, Pat, PatId, RecordFieldPat, dummy_expr_id, Binding, BindingId, Expr, ExprId, Label, LabelId, Pat, PatId, RecordFieldPat,
}, },
item_tree::AttrOwner,
nameres::DefMap, nameres::DefMap,
path::{ModPath, Path}, path::{ModPath, Path},
src::HasSource, src::HasSource,
@ -136,16 +137,23 @@ impl Body {
let data = db.function_data(f); let data = db.function_data(f);
let f = f.lookup(db); let f = f.lookup(db);
let src = f.source(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 item_tree = f.id.item_tree(db);
let func = &item_tree[f.id.value]; let func = &item_tree[f.id.value];
let krate = f.container.module(db).krate; let krate = f.container.module(db).krate;
let crate_graph = db.crate_graph(); let crate_graph = db.crate_graph();
( (
param_list, param_list,
func.params.clone().map(move |param| { (0..func.params.len()).map(move |idx| {
item_tree 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) .is_cfg_enabled(&crate_graph[krate].cfg_options)
}), }),
) )

View file

@ -7,6 +7,7 @@ use hir_expand::{
name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind, name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
}; };
use intern::{sym, Interned, Symbol}; use intern::{sym, Interned, Symbol};
use la_arena::{Idx, RawIdx};
use smallvec::SmallVec; use smallvec::SmallVec;
use syntax::{ast, Parse}; use syntax::{ast, Parse};
use triomphe::Arc; use triomphe::Arc;
@ -58,32 +59,15 @@ impl FunctionData {
let crate_graph = db.crate_graph(); let crate_graph = db.crate_graph();
let cfg_options = &crate_graph[krate].cfg_options; let cfg_options = &crate_graph[krate].cfg_options;
let enabled_params = func let attr_owner = |idx| {
.params item_tree::AttrOwner::Param(loc.id.value, Idx::from_raw(RawIdx::from(idx as u32)))
.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 mut flags = func.flags; let mut flags = func.flags;
if is_varargs {
flags |= FnFlags::IS_VARARGS;
}
if flags.contains(FnFlags::HAS_SELF_PARAM) { 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. // 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() { let is_cfgd_out =
Some(param) => { !item_tree.attrs(db, krate, attr_owner(0usize)).is_cfg_enabled(cfg_options);
!item_tree.attrs(db, krate, param.into()).is_cfg_enabled(cfg_options)
}
None => {
stdx::never!("fn HAS_SELF_PARAM but no parameters allocated");
true
}
};
if is_cfgd_out { if is_cfgd_out {
cov_mark::hit!(cfgd_out_self_param); cov_mark::hit!(cfgd_out_self_param);
flags.remove(FnFlags::HAS_SELF_PARAM); flags.remove(FnFlags::HAS_SELF_PARAM);
@ -101,9 +85,14 @@ impl FunctionData {
Arc::new(FunctionData { Arc::new(FunctionData {
name: func.name.clone(), name: func.name.clone(),
params: enabled_params params: func
.clone() .params
.filter_map(|id| item_tree[id].type_ref.clone()) .iter()
.enumerate()
.filter(|&(idx, _)| {
item_tree.attrs(db, krate, attr_owner(idx)).is_cfg_enabled(cfg_options)
})
.map(|(_, param)| param.type_ref.clone())
.collect(), .collect(),
ret_type: func.ret_type.clone(), ret_type: func.ret_type.clone(),
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), 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()) { if !attrs.is_cfg_enabled(self.expander.cfg_options()) {
self.diagnostics.push(DefDiagnostic::unconfigured_code( self.diagnostics.push(DefDiagnostic::unconfigured_code(
self.module_id.local_id, 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(), attrs.cfg().unwrap(),
self.expander.cfg_options().clone(), self.expander.cfg_options().clone(),
)); ));

View file

@ -7,7 +7,7 @@ use either::Either;
use hir_expand::{ use hir_expand::{
name::{AsName, Name}, name::{AsName, Name},
HirFileId, InFile, InFile,
}; };
use intern::{sym, Interned}; use intern::{sym, Interned};
use la_arena::Arena; use la_arena::Arena;
@ -18,7 +18,9 @@ use triomphe::Arc;
use crate::{ use crate::{
builtin_type::{BuiltinInt, BuiltinUint}, builtin_type::{BuiltinInt, BuiltinUint},
db::DefDatabase, db::DefDatabase,
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId}, item_tree::{
AttrOwner, Field, FieldParent, FieldsShape, ItemTree, ModItem, RawVisibilityId, TreeId,
},
lang_item::LangItem, lang_item::LangItem,
lower::LowerCtx, lower::LowerCtx,
nameres::diagnostics::{DefDiagnostic, DefDiagnostics}, nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
@ -211,20 +213,25 @@ impl StructData {
} }
let strukt = &item_tree[loc.id.value]; let strukt = &item_tree[loc.id.value];
let (variant_data, diagnostics) = lower_fields( let (data, diagnostics) = lower_fields(
db, db,
krate, krate,
loc.id.file_id(),
loc.container.local_id, loc.container.local_id,
loc.id.tree_id(),
&item_tree, &item_tree,
&db.crate_graph()[krate].cfg_options, &db.crate_graph()[krate].cfg_options,
FieldParent::Struct(loc.id.value),
&strukt.fields, &strukt.fields,
None, None,
); );
( (
Arc::new(StructData { Arc::new(StructData {
name: strukt.name.clone(), 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, repr,
visibility: item_tree[strukt.visibility].clone(), visibility: item_tree[strukt.visibility].clone(),
flags, flags,
@ -256,20 +263,21 @@ impl StructData {
} }
let union = &item_tree[loc.id.value]; let union = &item_tree[loc.id.value];
let (variant_data, diagnostics) = lower_fields( let (data, diagnostics) = lower_fields(
db, db,
krate, krate,
loc.id.file_id(),
loc.container.local_id, loc.container.local_id,
loc.id.tree_id(),
&item_tree, &item_tree,
&db.crate_graph()[krate].cfg_options, &db.crate_graph()[krate].cfg_options,
FieldParent::Union(loc.id.value),
&union.fields, &union.fields,
None, None,
); );
( (
Arc::new(StructData { Arc::new(StructData {
name: union.name.clone(), name: union.name.clone(),
variant_data: Arc::new(variant_data), variant_data: Arc::new(VariantData::Record(data)),
repr, repr,
visibility: item_tree[union.visibility].clone(), visibility: item_tree[union.visibility].clone(),
flags, flags,
@ -336,13 +344,14 @@ impl EnumVariantData {
let item_tree = loc.id.item_tree(db); let item_tree = loc.id.item_tree(db);
let variant = &item_tree[loc.id.value]; let variant = &item_tree[loc.id.value];
let (var_data, diagnostics) = lower_fields( let (data, diagnostics) = lower_fields(
db, db,
krate, krate,
loc.id.file_id(),
container.local_id, container.local_id,
loc.id.tree_id(),
&item_tree, &item_tree,
&db.crate_graph()[krate].cfg_options, &db.crate_graph()[krate].cfg_options,
FieldParent::Variant(loc.id.value),
&variant.fields, &variant.fields,
Some(item_tree[loc.parent.lookup(db).id.value].visibility), Some(item_tree[loc.parent.lookup(db).id.value].visibility),
); );
@ -350,7 +359,11 @@ impl EnumVariantData {
( (
Arc::new(EnumVariantData { Arc::new(EnumVariantData {
name: variant.name.clone(), 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), DefDiagnostics::new(diagnostics),
) )
@ -396,21 +409,23 @@ pub enum StructKind {
Unit, Unit,
} }
// FIXME This is only used for mapping back source now?
pub(crate) fn lower_struct( pub(crate) fn lower_struct(
db: &dyn DefDatabase, db: &dyn DefDatabase,
trace: &mut Trace<FieldData, Either<ast::TupleField, ast::RecordField>>, trace: &mut Trace<FieldData, Either<ast::TupleField, ast::RecordField>>,
ast: &InFile<ast::StructKind>, ast: &InFile<ast::StructKind>,
krate: CrateId, krate: CrateId,
item_tree: &ItemTree, item_tree: &ItemTree,
fields: &Fields, parent: FieldParent,
) -> StructKind { ) -> StructKind {
let ctx = LowerCtx::new(db, ast.file_id); let ctx = LowerCtx::new(db, ast.file_id);
match (&ast.value, fields) { match &ast.value {
(ast::StructKind::Tuple(fl), Fields::Tuple(fields)) => { ast::StructKind::Tuple(fl) => {
let cfg_options = &db.crate_graph()[krate].cfg_options; let cfg_options = &db.crate_graph()[krate].cfg_options;
for ((i, fd), item_tree_id) in fl.fields().enumerate().zip(fields.clone()) { for (i, fd) in fl.fields().enumerate() {
if !item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options) { let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, i));
if !attrs.is_cfg_enabled(cfg_options) {
continue; continue;
} }
@ -427,10 +442,11 @@ pub(crate) fn lower_struct(
} }
StructKind::Tuple StructKind::Tuple
} }
(ast::StructKind::Record(fl), Fields::Record(fields)) => { ast::StructKind::Record(fl) => {
let cfg_options = &db.crate_graph()[krate].cfg_options; let cfg_options = &db.crate_graph()[krate].cfg_options;
for (fd, item_tree_id) in fl.fields().zip(fields.clone()) { for (i, fd) in fl.fields().enumerate() {
if !item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options) { let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, i));
if !attrs.is_cfg_enabled(cfg_options) {
continue; continue;
} }
@ -454,65 +470,32 @@ pub(crate) fn lower_struct(
fn lower_fields( fn lower_fields(
db: &dyn DefDatabase, db: &dyn DefDatabase,
krate: CrateId, krate: CrateId,
current_file_id: HirFileId,
container: LocalModuleId, container: LocalModuleId,
tree_id: TreeId,
item_tree: &ItemTree, item_tree: &ItemTree,
cfg_options: &CfgOptions, cfg_options: &CfgOptions,
fields: &Fields, parent: FieldParent,
fields: &[Field],
override_visibility: Option<RawVisibilityId>, override_visibility: Option<RawVisibilityId>,
) -> (VariantData, Vec<DefDiagnostic>) { ) -> (Arena<FieldData>, Vec<DefDiagnostic>) {
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
match fields { let mut arena = Arena::new();
Fields::Record(flds) => { for (idx, field) in fields.iter().enumerate() {
let mut arena = Arena::new(); let attr_owner = AttrOwner::make_field_indexed(parent, idx);
for field_id in flds.clone() { let attrs = item_tree.attrs(db, krate, attr_owner);
let attrs = item_tree.attrs(db, krate, field_id.into()); if attrs.is_cfg_enabled(cfg_options) {
let field = &item_tree[field_id]; arena.alloc(lower_field(item_tree, field, override_visibility));
if attrs.is_cfg_enabled(cfg_options) { } else {
arena.alloc(lower_field(item_tree, field, override_visibility)); diagnostics.push(DefDiagnostic::unconfigured_code(
} else { container,
diagnostics.push(DefDiagnostic::unconfigured_code( tree_id,
container, attr_owner,
InFile::new( attrs.cfg().unwrap(),
current_file_id, cfg_options.clone(),
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)
}
Fields::Unit => (VariantData::Unit, diagnostics),
} }
(arena, diagnostics)
} }
fn lower_field( fn lower_field(

View file

@ -47,7 +47,7 @@ use base_db::CrateId;
use either::Either; use either::Either;
use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile}; use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
use intern::{Interned, Symbol}; use intern::{Interned, Symbol};
use la_arena::{Arena, Idx, IdxRange, RawIdx}; use la_arena::{Arena, Idx, RawIdx};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use smallvec::SmallVec; use smallvec::SmallVec;
@ -218,9 +218,7 @@ impl ItemTree {
extern_crates, extern_crates,
extern_blocks, extern_blocks,
functions, functions,
params,
structs, structs,
fields,
unions, unions,
enums, enums,
variants, variants,
@ -241,9 +239,7 @@ impl ItemTree {
extern_crates.shrink_to_fit(); extern_crates.shrink_to_fit();
extern_blocks.shrink_to_fit(); extern_blocks.shrink_to_fit();
functions.shrink_to_fit(); functions.shrink_to_fit();
params.shrink_to_fit();
structs.shrink_to_fit(); structs.shrink_to_fit();
fields.shrink_to_fit();
unions.shrink_to_fit(); unions.shrink_to_fit();
enums.shrink_to_fit(); enums.shrink_to_fit();
variants.shrink_to_fit(); variants.shrink_to_fit();
@ -295,9 +291,7 @@ struct ItemTreeData {
extern_crates: Arena<ExternCrate>, extern_crates: Arena<ExternCrate>,
extern_blocks: Arena<ExternBlock>, extern_blocks: Arena<ExternBlock>,
functions: Arena<Function>, functions: Arena<Function>,
params: Arena<Param>,
structs: Arena<Struct>, structs: Arena<Struct>,
fields: Arena<Field>,
unions: Arena<Union>, unions: Arena<Union>,
enums: Arena<Enum>, enums: Arena<Enum>,
variants: Arena<Variant>, variants: Arena<Variant>,
@ -315,7 +309,7 @@ struct ItemTreeData {
vis: ItemVisibilities, vis: ItemVisibilities,
} }
#[derive(Debug, Eq, PartialEq, Hash)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum AttrOwner { pub enum AttrOwner {
/// Attributes on an item. /// Attributes on an item.
ModItem(ModItem), ModItem(ModItem),
@ -323,12 +317,28 @@ pub enum AttrOwner {
TopLevel, TopLevel,
Variant(FileItemTreeId<Variant>), Variant(FileItemTreeId<Variant>),
Field(Idx<Field>), Field(FieldParent, ItemTreeFieldId),
Param(Idx<Param>), Param(FileItemTreeId<Function>, ItemTreeParamId),
TypeOrConstParamData(GenericModItem, LocalTypeOrConstParamId), TypeOrConstParamData(GenericModItem, LocalTypeOrConstParamId),
LifetimeParamData(GenericModItem, LocalLifetimeParamId), 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 { macro_rules! from_attrs {
( $( $var:ident($t:ty) ),+ $(,)? ) => { ( $( $var:ident($t:ty) ),+ $(,)? ) => {
$( $(
@ -341,12 +351,7 @@ macro_rules! from_attrs {
}; };
} }
from_attrs!( from_attrs!(ModItem(ModItem), Variant(FileItemTreeId<Variant>));
ModItem(ModItem),
Variant(FileItemTreeId<Variant>),
Field(Idx<Field>),
Param(Idx<Param>),
);
/// Trait implemented by all nodes in the item tree. /// Trait implemented by all nodes in the item tree.
pub trait ItemTreeNode: Clone { pub trait ItemTreeNode: Clone {
@ -365,7 +370,7 @@ pub trait GenericsItemTreeNode: ItemTreeNode {
pub struct FileItemTreeId<N>(Idx<N>); pub struct FileItemTreeId<N>(Idx<N>);
impl<N> FileItemTreeId<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()) (range.start.index().into_raw().into_u32()..range.end.index().into_raw().into_u32())
.map(RawIdx::from_u32) .map(RawIdx::from_u32)
.map(Idx::from_raw) .map(Idx::from_raw)
@ -417,18 +422,18 @@ impl TreeId {
Self { file, block } 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 { match self.block {
Some(block) => db.block_item_tree(block), Some(block) => db.block_item_tree(block),
None => db.file_item_tree(self.file), None => db.file_item_tree(self.file),
} }
} }
pub(crate) fn file_id(self) -> HirFileId { pub fn file_id(self) -> HirFileId {
self.file self.file
} }
pub(crate) fn is_block(self) -> bool { pub fn is_block(self) -> bool {
self.block.is_some() 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 { impl From<GenericModItem> for ModItem {
fn from(id: GenericModItem) -> ModItem { fn from(id: GenericModItem) -> ModItem {
match id { match id {
@ -596,22 +622,6 @@ mod_items! {
Macro2 in macro_defs -> ast::MacroDef, 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 { impl Index<RawVisibilityId> for ItemTree {
type Output = RawVisibility; type Output = RawVisibility;
fn index(&self, index: RawVisibilityId) -> &Self::Output { fn index(&self, index: RawVisibilityId) -> &Self::Output {
@ -723,7 +733,7 @@ pub struct Function {
pub visibility: RawVisibilityId, pub visibility: RawVisibilityId,
pub explicit_generic_params: Interned<GenericParams>, pub explicit_generic_params: Interned<GenericParams>,
pub abi: Option<Symbol>, pub abi: Option<Symbol>,
pub params: IdxRange<Param>, pub params: Box<[Param]>,
pub ret_type: Interned<TypeRef>, pub ret_type: Interned<TypeRef>,
pub ast_id: FileAstId<ast::Fn>, pub ast_id: FileAstId<ast::Fn>,
pub(crate) flags: FnFlags, pub(crate) flags: FnFlags,
@ -731,15 +741,7 @@ pub struct Function {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct Param { pub struct Param {
/// This is [`None`] for varargs pub type_ref: Interned<TypeRef>,
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>),
} }
bitflags::bitflags! { bitflags::bitflags! {
@ -760,7 +762,8 @@ pub struct Struct {
pub name: Name, pub name: Name,
pub visibility: RawVisibilityId, pub visibility: RawVisibilityId,
pub generic_params: Interned<GenericParams>, pub generic_params: Interned<GenericParams>,
pub fields: Fields, pub fields: Box<[Field]>,
pub shape: FieldsShape,
pub ast_id: FileAstId<ast::Struct>, pub ast_id: FileAstId<ast::Struct>,
} }
@ -769,7 +772,7 @@ pub struct Union {
pub name: Name, pub name: Name,
pub visibility: RawVisibilityId, pub visibility: RawVisibilityId,
pub generic_params: Interned<GenericParams>, pub generic_params: Interned<GenericParams>,
pub fields: Fields, pub fields: Box<[Field]>,
pub ast_id: FileAstId<ast::Union>, pub ast_id: FileAstId<ast::Union>,
} }
@ -782,6 +785,29 @@ pub struct Enum {
pub ast_id: FileAstId<ast::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)] #[derive(Debug, Clone, Eq, PartialEq)]
pub struct Const { pub struct Const {
/// `None` for `const _: () = ();` /// `None` for `const _: () = ();`
@ -1039,28 +1065,6 @@ impl ModItem {
&ModItem::Function(func) => Some(AssocItem::Function(func)), &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)] #[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,
}

View file

@ -17,12 +17,12 @@ use crate::{
db::DefDatabase, db::DefDatabase,
generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance}, generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance},
item_tree::{ item_tree::{
AssocItem, AttrOwner, Const, Either, Enum, ExternBlock, ExternCrate, Field, FieldAstId, AssocItem, AttrOwner, Const, Either, Enum, ExternBlock, ExternCrate, Field, FieldParent,
Fields, FileItemTreeId, FnFlags, Function, GenericArgs, GenericModItem, Idx, IdxRange, FieldsShape, FileItemTreeId, FnFlags, Function, GenericArgs, GenericModItem, Idx, Impl,
Impl, ImportAlias, Interned, ItemTree, ItemTreeData, ItemTreeNode, Macro2, MacroCall, ImportAlias, Interned, ItemTree, ItemTreeData, Macro2, MacroCall, MacroRules, Mod, ModItem,
MacroRules, Mod, ModItem, ModKind, ModPath, Mutability, Name, Param, ParamAstId, Path, ModKind, ModPath, Mutability, Name, Param, Path, Range, RawAttrs, RawIdx, RawVisibilityId,
Range, RawAttrs, RawIdx, RawVisibilityId, Static, Struct, StructKind, Trait, TraitAlias, Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
TypeAlias, Union, Use, UseTree, UseTreeKind, Variant, Variant,
}, },
path::AssociatedTypeBinding, path::AssociatedTypeBinding,
type_ref::{LifetimeRef, TraitBoundModifier, TraitRef, TypeBound, TypeRef}, type_ref::{LifetimeRef, TraitBoundModifier, TraitRef, TypeBound, TypeRef},
@ -30,7 +30,7 @@ use crate::{
LocalLifetimeParamId, LocalTypeOrConstParamId, LocalLifetimeParamId, LocalTypeOrConstParamId,
}; };
fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> { fn id<N>(index: Idx<N>) -> FileItemTreeId<N> {
FileItemTreeId(index) FileItemTreeId(index)
} }
@ -193,82 +193,98 @@ impl<'a> Ctx<'a> {
let visibility = self.lower_visibility(strukt); let visibility = self.lower_visibility(strukt);
let name = strukt.name()?.as_name(); let name = strukt.name()?.as_name();
let ast_id = self.source_ast_id_map.ast_id(strukt); 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 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)); 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()); self.write_generic_params_attributes(id.into());
Some(id) 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 { match strukt_kind {
ast::StructKind::Record(it) => { ast::StructKind::Record(it) => {
let range = self.lower_record_fields(it); let mut fields = vec![];
Fields::Record(range) 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) => { ast::StructKind::Tuple(it) => {
let range = self.lower_tuple_fields(it); let mut fields = vec![];
Fields::Tuple(range) 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 => Fields::Unit, ast::StructKind::Unit => (Box::default(), FieldsShape::Unit, Vec::default()),
} }
} }
fn lower_record_fields(&mut self, fields: &ast::RecordFieldList) -> IdxRange<Field> { fn lower_record_field(&mut self, field: &ast::RecordField) -> Field {
let start = self.next_field_idx(); let name = match field.name() {
for field in fields.fields() { Some(name) => name.as_name(),
if let Some(data) = self.lower_record_field(&field) { None => Name::missing(),
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)
}
fn lower_record_field(&mut self, field: &ast::RecordField) -> Option<Field> {
let name = field.name()?.as_name();
let visibility = self.lower_visibility(field); let visibility = self.lower_visibility(field);
let type_ref = self.lower_type_ref_opt(field.ty()); 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> { Field { name, type_ref, visibility }
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)
} }
fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleField) -> Field { fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleField) -> Field {
let name = Name::new_tuple_field(idx); let name = Name::new_tuple_field(idx);
let visibility = self.lower_visibility(field); let visibility = self.lower_visibility(field);
let type_ref = self.lower_type_ref_opt(field.ty()); 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 }
Field { name, type_ref, visibility, ast_id }
} }
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> { fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
let visibility = self.lower_visibility(union); let visibility = self.lower_visibility(union);
let name = union.name()?.as_name(); let name = union.name()?.as_name();
let ast_id = self.source_ast_id_map.ast_id(union); 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)), 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 generic_params = self.lower_generic_params(HasImplicitSelf::No, union);
let res = Union { name, visibility, generic_params, fields, ast_id }; let res = Union { name, visibility, generic_params, fields, ast_id };
let id = id(self.data().unions.alloc(res)); 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()); self.write_generic_params_attributes(id.into());
Some(id) Some(id)
} }
@ -293,24 +309,35 @@ impl<'a> Ctx<'a> {
fn lower_variants(&mut self, variants: &ast::VariantList) -> Range<FileItemTreeId<Variant>> { fn lower_variants(&mut self, variants: &ast::VariantList) -> Range<FileItemTreeId<Variant>> {
let start = self.next_variant_idx(); let start = self.next_variant_idx();
for variant in variants.variants() { for variant in variants.variants() {
if let Some(data) = self.lower_variant(&variant) { let idx = self.lower_variant(&variant);
let idx = self.data().variants.alloc(data); self.add_attrs(
self.add_attrs( id(idx).into(),
id(idx).into(), RawAttrs::new(self.db.upcast(), &variant, self.span_map()),
RawAttrs::new(self.db.upcast(), &variant, self.span_map()), );
);
}
} }
let end = self.next_variant_idx(); let end = self.next_variant_idx();
FileItemTreeId(start)..FileItemTreeId(end) FileItemTreeId(start)..FileItemTreeId(end)
} }
fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> { fn lower_variant(&mut self, variant: &ast::Variant) -> Idx<Variant> {
let name = variant.name()?.as_name(); let name = match variant.name() {
let fields = self.lower_fields(&variant.kind()); 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 ast_id = self.source_ast_id_map.ast_id(variant);
let res = Variant { name, fields, ast_id }; let res = Variant { name, fields, shape: kind, ast_id };
Some(res) 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>> { 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 name = func.name()?.as_name();
let mut has_self_param = false; 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(param_list) = func.param_list() {
if let Some(self_param) = param_list.self_param() { 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() { let self_type = match self_param.ty() {
Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref),
None => { None => {
@ -342,40 +380,25 @@ impl<'a> Ctx<'a> {
} }
}; };
let type_ref = Interned::new(self_type); let type_ref = Interned::new(self_type);
let ast_id = self.source_ast_id_map.ast_id(&self_param); params.push(Param { type_ref });
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()),
);
has_self_param = true; has_self_param = true;
} }
for param in param_list.params() { for param in param_list.params() {
let ast_id = self.source_ast_id_map.ast_id(&param); push_attr(params.len(), RawAttrs::new(self.db.upcast(), &param, self.span_map()));
let idx = match param.dotdotdot_token() { let param = match param.dotdotdot_token() {
Some(_) => self Some(_) => {
.data() has_var_args = true;
.params Param { type_ref: Interned::new(TypeRef::Error) }
.alloc(Param { type_ref: None, ast_id: ParamAstId::Param(ast_id) }), }
None => { None => {
let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty());
let ty = Interned::new(type_ref); let ty = Interned::new(type_ref);
self.data() Param { type_ref: ty }
.params
.alloc(Param { type_ref: Some(ty), ast_id: ParamAstId::Param(ast_id) })
} }
}; };
self.add_attrs( params.push(param);
idx.into(),
RawAttrs::new(self.db.upcast(), &param, self.span_map()),
);
} }
} }
let end_param = self.next_param_idx();
let params = IdxRange::new(start_param..end_param);
let ret_type = match func.ret_type() { let ret_type = match func.ret_type() {
Some(rt) => match rt.ty() { Some(rt) => match rt.ty() {
@ -417,19 +440,25 @@ impl<'a> Ctx<'a> {
if func.unsafe_token().is_some() { if func.unsafe_token().is_some() {
flags |= FnFlags::HAS_UNSAFE_KW; flags |= FnFlags::HAS_UNSAFE_KW;
} }
if has_var_args {
flags |= FnFlags::IS_VARARGS;
}
let res = Function { let res = Function {
name, name,
visibility, visibility,
explicit_generic_params: self.lower_generic_params(HasImplicitSelf::No, func), explicit_generic_params: self.lower_generic_params(HasImplicitSelf::No, func),
abi, abi,
params, params: params.into_boxed_slice(),
ret_type: Interned::new(ret_type), ret_type: Interned::new(ret_type),
ast_id, ast_id,
flags, flags,
}; };
let id = id(self.data().functions.alloc(res)); 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()); self.write_generic_params_attributes(id.into());
Some(id) 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> { fn next_variant_idx(&self) -> Idx<Variant> {
Idx::from_raw(RawIdx::from( Idx::from_raw(RawIdx::from(
self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32), 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 { fn desugar_future_path(orig: TypeRef) -> Path {

View file

@ -2,16 +2,17 @@
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use la_arena::{Idx, RawIdx};
use span::ErasedFileAstId; use span::ErasedFileAstId;
use crate::{ use crate::{
generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget}, generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget},
item_tree::{ item_tree::{
AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldAstId, Fields, AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldParent,
FileItemTreeId, FnFlags, Function, GenericModItem, GenericParams, Impl, Interned, ItemTree, FieldsShape, FileItemTreeId, FnFlags, Function, GenericModItem, GenericParams, Impl,
Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, Param, ParamAstId, Path, RawAttrs, Interned, ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, Param, Path,
RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound, TypeRef, Union, RawAttrs, RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound,
Use, UseTree, UseTreeKind, Variant, TypeRef, Union, Use, UseTree, UseTreeKind, Variant,
}, },
pretty::{print_path, print_type_bounds, print_type_ref}, pretty::{print_path, print_type_bounds, print_type_ref},
visibility::RawVisibility, visibility::RawVisibility,
@ -118,19 +119,17 @@ impl Printer<'_> {
}; };
} }
fn print_fields(&mut self, fields: &Fields) { fn print_fields(&mut self, parent: FieldParent, kind: FieldsShape, fields: &[Field]) {
match fields { match kind {
Fields::Record(fields) => { FieldsShape::Record => {
self.whitespace(); self.whitespace();
w!(self, "{{"); w!(self, "{{");
self.indented(|this| { self.indented(|this| {
for field in fields.clone() { for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() {
let Field { visibility, name, type_ref, ast_id } = &this.tree[field]; this.print_attrs_of(
this.print_ast_id(match ast_id { AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
FieldAstId::Record(it) => it.erase(), "\n",
FieldAstId::Tuple(it) => it.erase(), );
});
this.print_attrs_of(field, "\n");
this.print_visibility(*visibility); this.print_visibility(*visibility);
w!(this, "{}: ", name.display(self.db.upcast())); w!(this, "{}: ", name.display(self.db.upcast()));
this.print_type_ref(type_ref); this.print_type_ref(type_ref);
@ -139,16 +138,14 @@ impl Printer<'_> {
}); });
w!(self, "}}"); w!(self, "}}");
} }
Fields::Tuple(fields) => { FieldsShape::Tuple => {
w!(self, "("); w!(self, "(");
self.indented(|this| { self.indented(|this| {
for field in fields.clone() { for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() {
let Field { visibility, name, type_ref, ast_id } = &this.tree[field]; this.print_attrs_of(
this.print_ast_id(match ast_id { AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
FieldAstId::Record(it) => it.erase(), "\n",
FieldAstId::Tuple(it) => it.erase(), );
});
this.print_attrs_of(field, "\n");
this.print_visibility(*visibility); this.print_visibility(*visibility);
w!(this, "{}: ", name.display(self.db.upcast())); w!(this, "{}: ", name.display(self.db.upcast()));
this.print_type_ref(type_ref); this.print_type_ref(type_ref);
@ -157,24 +154,30 @@ impl Printer<'_> {
}); });
w!(self, ")"); w!(self, ")");
} }
Fields::Unit => {} FieldsShape::Unit => {}
} }
} }
fn print_fields_and_where_clause(&mut self, fields: &Fields, params: &GenericParams) { fn print_fields_and_where_clause(
match fields { &mut self,
Fields::Record(_) => { parent: FieldParent,
kind: FieldsShape,
fields: &[Field],
params: &GenericParams,
) {
match kind {
FieldsShape::Record => {
if self.print_where_clause(params) { if self.print_where_clause(params) {
wln!(self); wln!(self);
} }
self.print_fields(fields); self.print_fields(parent, kind, fields);
} }
Fields::Unit => { FieldsShape::Unit => {
self.print_where_clause(params); self.print_where_clause(params);
self.print_fields(fields); self.print_fields(parent, kind, fields);
} }
Fields::Tuple(_) => { FieldsShape::Tuple => {
self.print_fields(fields); self.print_fields(parent, kind, fields);
self.print_where_clause(params); self.print_where_clause(params);
} }
} }
@ -280,25 +283,20 @@ impl Printer<'_> {
w!(self, "("); w!(self, "(");
if !params.is_empty() { if !params.is_empty() {
self.indented(|this| { self.indented(|this| {
for param in params.clone() { for (idx, Param { type_ref }) in params.iter().enumerate() {
this.print_attrs_of(param, "\n"); this.print_attrs_of(
let Param { type_ref, ast_id } = &this.tree[param]; AttrOwner::Param(it, Idx::from_raw(RawIdx::from(idx as u32))),
this.print_ast_id(match ast_id { "\n",
ParamAstId::Param(it) => it.erase(), );
ParamAstId::SelfParam(it) => it.erase(), if idx == 0 && flags.contains(FnFlags::HAS_SELF_PARAM) {
}); w!(this, "self: ");
match type_ref { }
Some(ty) => { if idx != params.len() {
if flags.contains(FnFlags::HAS_SELF_PARAM) { this.print_type_ref(type_ref);
w!(this, "self: "); } else {
} wln!(this, "...");
this.print_type_ref(ty); }
wln!(this, ","); wln!(this, ",");
}
None => {
wln!(this, "...");
}
};
} }
}); });
} }
@ -312,13 +310,19 @@ impl Printer<'_> {
} }
} }
ModItem::Struct(it) => { 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_ast_id(ast_id.erase());
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "struct {}", name.display(self.db.upcast())); w!(self, "struct {}", name.display(self.db.upcast()));
self.print_generic_params(generic_params, it.into()); self.print_generic_params(generic_params, it.into());
self.print_fields_and_where_clause(fields, generic_params); self.print_fields_and_where_clause(
if matches!(fields, Fields::Record(_)) { FieldParent::Struct(it),
*kind,
fields,
generic_params,
);
if matches!(kind, FieldsShape::Record) {
wln!(self); wln!(self);
} else { } else {
wln!(self, ";"); wln!(self, ";");
@ -330,12 +334,13 @@ impl Printer<'_> {
self.print_visibility(*visibility); self.print_visibility(*visibility);
w!(self, "union {}", name.display(self.db.upcast())); w!(self, "union {}", name.display(self.db.upcast()));
self.print_generic_params(generic_params, it.into()); self.print_generic_params(generic_params, it.into());
self.print_fields_and_where_clause(fields, generic_params); self.print_fields_and_where_clause(
if matches!(fields, Fields::Record(_)) { FieldParent::Union(it),
wln!(self); FieldsShape::Record,
} else { fields,
wln!(self, ";"); generic_params,
} );
wln!(self);
} }
ModItem::Enum(it) => { ModItem::Enum(it) => {
let Enum { name, visibility, variants, generic_params, ast_id } = &self.tree[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.print_where_clause_and_opening_brace(generic_params);
self.indented(|this| { self.indented(|this| {
for variant in FileItemTreeId::range_iter(variants.clone()) { 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_ast_id(ast_id.erase());
this.print_attrs_of(variant, "\n"); this.print_attrs_of(variant, "\n");
w!(this, "{}", name.display(self.db.upcast())); w!(this, "{}", name.display(self.db.upcast()));
this.print_fields(fields); this.print_fields(FieldParent::Variant(variant), *kind, fields);
wln!(this, ","); wln!(this, ",");
} }
}); });

View file

@ -129,40 +129,34 @@ enum E {
#[derive(Debug)] #[derive(Debug)]
// AstId: 2 // AstId: 2
pub(self) struct Struct { pub(self) struct Struct {
// AstId: 6
#[doc = " fld docs"] #[doc = " fld docs"]
pub(self) fld: (), pub(self) fld: (),
} }
// AstId: 3 // AstId: 3
pub(self) struct Tuple( pub(self) struct Tuple(
// AstId: 7
#[attr] #[attr]
pub(self) 0: u8, pub(self) 0: u8,
); );
// AstId: 4 // AstId: 4
pub(self) union Ize { pub(self) union Ize {
// AstId: 8
pub(self) a: (), pub(self) a: (),
// AstId: 9
pub(self) b: (), pub(self) b: (),
} }
// AstId: 5 // AstId: 5
pub(self) enum E { pub(self) enum E {
// AstId: 10 // AstId: 6
#[doc = " comment on Unit"] #[doc = " comment on Unit"]
Unit, Unit,
// AstId: 11 // AstId: 7
#[doc = " comment on Tuple"] #[doc = " comment on Tuple"]
Tuple( Tuple(
// AstId: 13
pub(self) 0: u8, pub(self) 0: u8,
), ),
// AstId: 12 // AstId: 8
Struct { Struct {
// AstId: 14
#[doc = " comment on a: u8"] #[doc = " comment on a: u8"]
pub(self) a: u8, pub(self) a: u8,
}, },
@ -201,9 +195,7 @@ trait Tr: SuperTrait + 'lifetime {
// AstId: 3 // AstId: 3
pub(self) fn f( pub(self) fn f(
#[attr] #[attr]
// AstId: 5
u8, u8,
// AstId: 6
(), (),
) -> () { ... } ) -> () { ... }
@ -213,12 +205,11 @@ trait Tr: SuperTrait + 'lifetime {
Self: SuperTrait, Self: SuperTrait,
Self: 'lifetime Self: 'lifetime
{ {
// AstId: 8 // AstId: 6
pub(self) type Assoc: AssocBound = Default; pub(self) type Assoc: AssocBound = Default;
// AstId: 9 // AstId: 7
pub(self) fn method( pub(self) fn method(
// AstId: 10
self: &Self, self: &Self,
) -> (); ) -> ();
} }
@ -300,17 +291,11 @@ struct S {
expect![[r#" expect![[r#"
// AstId: 1 // AstId: 1
pub(self) struct S { pub(self) struct S {
// AstId: 2
pub(self) a: self::Ty, pub(self) a: self::Ty,
// AstId: 3
pub(self) b: super::SuperTy, pub(self) b: super::SuperTy,
// AstId: 4
pub(self) c: super::super::SuperSuperTy, pub(self) c: super::super::SuperSuperTy,
// AstId: 5
pub(self) d: ::abs::Path, pub(self) d: ::abs::Path,
// AstId: 6
pub(self) e: crate::Crate, pub(self) e: crate::Crate,
// AstId: 7
pub(self) f: plain::path::Ty, pub(self) f: plain::path::Ty,
} }
"#]], "#]],
@ -331,13 +316,9 @@ struct S {
expect![[r#" expect![[r#"
// AstId: 1 // AstId: 1
pub(self) struct S { pub(self) struct S {
// AstId: 2
pub(self) a: Mixed::<'a, T, Item = (), OtherItem = u8>, pub(self) a: Mixed::<'a, T, Item = (), OtherItem = u8>,
// AstId: 3
pub(self) b: Qualified::<Self=Fully>::Syntax, pub(self) b: Qualified::<Self=Fully>::Syntax,
// AstId: 4
pub(self) c: <TypeAnchored>::Path::<'a>, pub(self) c: <TypeAnchored>::Path::<'a>,
// AstId: 5
pub(self) d: dyn for<'a> Trait::<'a>, 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: 'a,
T: 'b T: 'b
{ {
// AstId: 8
pub(self) field: &'a &'b T, pub(self) field: &'a &'b T,
} }
// AstId: 2 // AstId: 2
pub(self) struct Tuple<T, U>( pub(self) struct Tuple<T, U>(
// AstId: 9
pub(self) 0: T, pub(self) 0: T,
// AstId: 10
pub(self) 1: U, pub(self) 1: U,
) )
where where
@ -393,9 +371,8 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
T: 'a, T: 'a,
T: 'b T: 'b
{ {
// AstId: 12 // AstId: 9
pub(self) fn f<G>( pub(self) fn f<G>(
// AstId: 13
impl Copy, impl Copy,
) -> impl Copy ) -> impl Copy
where where

View file

@ -23,7 +23,7 @@ use itertools::{izip, Itertools};
use la_arena::Idx; use la_arena::Idx;
use limit::Limit; use limit::Limit;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use span::{Edition, EditionedFileId, ErasedFileAstId, FileAstId, SyntaxContextId}; use span::{Edition, EditionedFileId, FileAstId, SyntaxContextId};
use syntax::ast; use syntax::ast;
use triomphe::Arc; use triomphe::Arc;
@ -32,8 +32,8 @@ use crate::{
db::DefDatabase, db::DefDatabase,
item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports}, item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
item_tree::{ item_tree::{
self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, self, AttrOwner, ExternCrate, FieldsShape, FileItemTreeId, ImportKind, ItemTree,
Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, ItemTreeId, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
}, },
macro_call_as_call_id, macro_call_as_call_id_with_eager, macro_call_as_call_id, macro_call_as_call_id_with_eager,
nameres::{ nameres::{
@ -1580,10 +1580,7 @@ impl ModCollector<'_, '_> {
let attrs = self.item_tree.attrs(db, krate, item.into()); let attrs = self.item_tree.attrs(db, krate, item.into());
if let Some(cfg) = attrs.cfg() { if let Some(cfg) = attrs.cfg() {
if !self.is_cfg_enabled(&cfg) { if !self.is_cfg_enabled(&cfg) {
self.emit_unconfigured_diagnostic( self.emit_unconfigured_diagnostic(self.tree_id, item.into(), &cfg);
InFile::new(self.file_id(), item.ast_id(self.item_tree).erase()),
&cfg,
);
return; return;
} }
} }
@ -1699,7 +1696,7 @@ impl ModCollector<'_, '_> {
.into(), .into(),
&it.name, &it.name,
vis, vis,
!matches!(it.fields, Fields::Record(_)), !matches!(it.shape, FieldsShape::Record),
); );
} }
ModItem::Union(id) => { ModItem::Union(id) => {
@ -1737,10 +1734,8 @@ impl ModCollector<'_, '_> {
match is_enabled { match is_enabled {
Err(cfg) => { Err(cfg) => {
self.emit_unconfigured_diagnostic( self.emit_unconfigured_diagnostic(
InFile::new( self.tree_id,
self.file_id(), variant.into(),
self.item_tree[variant.index()].ast_id.erase(),
),
&cfg, &cfg,
); );
None None
@ -1956,7 +1951,8 @@ impl ModCollector<'_, '_> {
match is_enabled { match is_enabled {
Err(cfg) => { Err(cfg) => {
self.emit_unconfigured_diagnostic( self.emit_unconfigured_diagnostic(
ast_id.map(|it| it.erase()), self.tree_id,
AttrOwner::TopLevel,
&cfg, &cfg,
); );
} }
@ -2402,10 +2398,11 @@ impl ModCollector<'_, '_> {
self.def_collector.cfg_options.check(cfg) != Some(false) 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.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
self.module_id, self.module_id,
ast_id, tree_id,
item,
cfg.clone(), cfg.clone(),
self.def_collector.cfg_options.clone(), self.def_collector.cfg_options.clone(),
)); ));

View file

@ -4,12 +4,12 @@ use std::ops::Not;
use base_db::CrateId; use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions}; use cfg::{CfgExpr, CfgOptions};
use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind}; use hir_expand::{attrs::AttrId, MacroCallKind};
use la_arena::Idx; use la_arena::Idx;
use syntax::ast; use syntax::ast;
use crate::{ use crate::{
item_tree::{self, ItemTreeId}, item_tree::{self, AttrOwner, ItemTreeId, TreeId},
nameres::LocalModuleId, nameres::LocalModuleId,
path::ModPath, path::ModPath,
AstId, AstId,
@ -29,7 +29,8 @@ pub enum DefDiagnosticKind {
index: Idx<ast::UseTree>, index: Idx<ast::UseTree>,
}, },
UnconfiguredCode { UnconfiguredCode {
ast: ErasedAstId, tree: TreeId,
item: AttrOwner,
cfg: CfgExpr, cfg: CfgExpr,
opts: CfgOptions, opts: CfgOptions,
}, },
@ -116,11 +117,15 @@ impl DefDiagnostic {
pub fn unconfigured_code( pub fn unconfigured_code(
container: LocalModuleId, container: LocalModuleId,
ast: ErasedAstId, tree: TreeId,
item: AttrOwner,
cfg: CfgExpr, cfg: CfgExpr,
opts: CfgOptions, opts: CfgOptions,
) -> Self { ) -> 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( pub fn unresolved_proc_macro(

View file

@ -17,7 +17,7 @@ use triomphe::Arc;
use crate::{ use crate::{
db::DefDatabase, db::DefDatabase,
item_scope::{ImportOrExternCrate, BUILTIN_SCOPE}, item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
item_tree::Fields, item_tree::FieldsShape,
nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs}, nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs},
path::{ModPath, PathKind}, path::{ModPath, PathKind},
per_ns::PerNs, per_ns::PerNs,
@ -381,11 +381,11 @@ impl DefMap {
.iter() .iter()
.find_map(|&variant| { .find_map(|&variant| {
let variant_data = &tree[variant.lookup(db).id.value]; let variant_data = &tree[variant.lookup(db).id.value];
(variant_data.name == *segment).then(|| match variant_data.fields { (variant_data.name == *segment).then(|| match variant_data.shape {
Fields::Record(_) => { FieldsShape::Record => {
PerNs::types(variant.into(), Visibility::Public, None) PerNs::types(variant.into(), Visibility::Public, None)
} }
Fields::Tuple(_) | Fields::Unit => PerNs::both( FieldsShape::Tuple | FieldsShape::Unit => PerNs::both(
variant.into(), variant.into(),
variant.into(), variant.into(),
Visibility::Public, Visibility::Public,

View file

@ -6,9 +6,12 @@ use la_arena::ArenaMap;
use syntax::{ast, AstNode, AstPtr}; use syntax::{ast, AstNode, AstPtr};
use crate::{ use crate::{
data::adt::lower_struct, db::DefDatabase, item_tree::ItemTreeNode, trace::Trace, GenericDefId, data::adt::lower_struct,
ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, UseId, db::DefDatabase,
VariantId, item_tree::{FieldParent, ItemTreeNode},
trace::Trace,
GenericDefId, ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup,
UseId, VariantId,
}; };
pub trait HasSource { pub trait HasSource {
@ -124,13 +127,13 @@ impl HasChildSource<LocalFieldId> for VariantId {
fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<LocalFieldId, Self::Value>> { fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<LocalFieldId, Self::Value>> {
let item_tree; let item_tree;
let (src, fields, container) = match *self { let (src, parent, container) = match *self {
VariantId::EnumVariantId(it) => { VariantId::EnumVariantId(it) => {
let lookup = it.lookup(db); let lookup = it.lookup(db);
item_tree = lookup.id.item_tree(db); item_tree = lookup.id.item_tree(db);
( (
lookup.source(db).map(|it| it.kind()), lookup.source(db).map(|it| it.kind()),
&item_tree[lookup.id.value].fields, FieldParent::Variant(lookup.id.value),
lookup.parent.lookup(db).container, lookup.parent.lookup(db).container,
) )
} }
@ -139,7 +142,7 @@ impl HasChildSource<LocalFieldId> for VariantId {
item_tree = lookup.id.item_tree(db); item_tree = lookup.id.item_tree(db);
( (
lookup.source(db).map(|it| it.kind()), lookup.source(db).map(|it| it.kind()),
&item_tree[lookup.id.value].fields, FieldParent::Struct(lookup.id.value),
lookup.container, lookup.container,
) )
} }
@ -148,13 +151,13 @@ impl HasChildSource<LocalFieldId> for VariantId {
item_tree = lookup.id.item_tree(db); item_tree = lookup.id.item_tree(db);
( (
lookup.source(db).map(|it| it.kind()), lookup.source(db).map(|it| it.kind()),
&item_tree[lookup.id.value].fields, FieldParent::Union(lookup.id.value),
lookup.container, lookup.container,
) )
} }
}; };
let mut trace = Trace::new_for_map(); 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()) src.with_value(trace.into_map())
} }
} }

View file

@ -812,7 +812,9 @@ impl<'a> InferenceContext<'a> {
None => self.err_ty(), 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())); 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 { if let Some(self_param) = self.body.self_param {

View file

@ -99,7 +99,13 @@ impl HirDisplay for Function {
} }
// FIXME: Use resolved `param.ty` once we no longer discard lifetimes // 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)); let local = param.as_local(db).map(|it| it.name(db));
if !first { if !first {
f.write_str(", ")?; f.write_str(", ")?;
@ -114,7 +120,10 @@ impl HirDisplay for Function {
} }
if data.is_varargs() { if data.is_varargs() {
f.write_str(", ...")?; if !first {
f.write_str(", ")?;
}
f.write_str("...")?;
} }
f.write_char(')')?; f.write_char(')')?;

View file

@ -44,7 +44,7 @@ use hir_def::{
data::adt::VariantData, data::adt::VariantData,
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat}, hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat},
item_tree::ItemTreeNode, item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
lang_item::LangItemTarget, lang_item::LangItemTarget,
layout::{self, ReprOptions, TargetDataLayout}, layout::{self, ReprOptions, TargetDataLayout},
nameres::{self, diagnostics::DefDiagnostic}, nameres::{self, diagnostics::DefDiagnostic},
@ -81,7 +81,7 @@ use rustc_hash::FxHashSet;
use span::{Edition, EditionedFileId, FileId, MacroCallId}; use span::{Edition, EditionedFileId, FileId, MacroCallId};
use stdx::{impl_from, never}; use stdx::{impl_from, never};
use syntax::{ use syntax::{
ast::{self, HasAttrs as _, HasName}, ast::{self, HasAttrs as _, HasGenericParams, HasName},
format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr, T, format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr, T,
}; };
use triomphe::Arc; use triomphe::Arc;
@ -906,12 +906,90 @@ fn emit_def_diagnostic_(
); );
} }
DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => { DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts } => {
let item = ast.to_ptr(db.upcast()); let item_tree = tree.item_tree(db.upcast());
acc.push( let ast_id_map = db.ast_id_map(tree.file_id());
InactiveCode { node: ast.with_value(item), cfg: cfg.clone(), opts: opts.clone() } // 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(), .into(),
); );
Some(())
})();
} }
DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => { DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => {
let (node, precise_location, macro_name, kind) = precise_macro_call_location(ast, db); let (node, precise_location, macro_name, kind) = precise_macro_call_location(ast, db);

View file

@ -80,13 +80,11 @@ macro_rules! register_ast_id_node {
} }
register_ast_id_node! { register_ast_id_node! {
impl AstIdNode for impl AstIdNode for
Item, Item, AnyHasGenericParams,
Adt, Adt,
Enum, Enum,
Variant, Variant,
Struct, Struct,
RecordField,
TupleField,
Union, Union,
AssocItem, AssocItem,
Const, Const,
@ -104,7 +102,7 @@ register_ast_id_node! {
Trait, Trait,
TraitAlias, TraitAlias,
Use, Use,
BlockExpr, ConstArg, Param, SelfParam BlockExpr, ConstArg
} }
/// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back. /// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.