mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
Remove Params and Fields from AstIdMap
This commit is contained in:
parent
200a01adc4
commit
9cbafa2d49
16 changed files with 494 additions and 449 deletions
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
}),
|
||||
)
|
||||
|
|
|
@ -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(|¶m| 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(),
|
||||
));
|
||||
|
|
|
@ -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)
|
||||
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::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(
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
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 => Fields::Unit,
|
||||
ast::StructKind::Unit => (Box::default(), FieldsShape::Unit, Vec::default()),
|
||||
}
|
||||
}
|
||||
|
||||
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 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(¶m);
|
||||
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(), ¶m, 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(), ¶m, 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 {
|
||||
|
|
|
@ -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, ",");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
));
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(')')?;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue