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::{
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;

View file

@ -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)
}),
)

View file

@ -7,6 +7,7 @@ use hir_expand::{
name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
};
use intern::{sym, Interned, Symbol};
use la_arena::{Idx, RawIdx};
use smallvec::SmallVec;
use syntax::{ast, Parse};
use triomphe::Arc;
@ -58,32 +59,15 @@ impl FunctionData {
let crate_graph = db.crate_graph();
let cfg_options = &crate_graph[krate].cfg_options;
let enabled_params = func
.params
.clone()
.filter(|&param| item_tree.attrs(db, krate, param.into()).is_cfg_enabled(cfg_options));
// If last cfg-enabled param is a `...` param, it's a varargs function.
let is_varargs = enabled_params
.clone()
.next_back()
.map_or(false, |param| item_tree[param].type_ref.is_none());
let attr_owner = |idx| {
item_tree::AttrOwner::Param(loc.id.value, Idx::from_raw(RawIdx::from(idx as u32)))
};
let mut flags = func.flags;
if is_varargs {
flags |= FnFlags::IS_VARARGS;
}
if flags.contains(FnFlags::HAS_SELF_PARAM) {
// If there's a self param in the syntax, but it is cfg'd out, remove the flag.
let is_cfgd_out = match func.params.clone().next() {
Some(param) => {
!item_tree.attrs(db, krate, param.into()).is_cfg_enabled(cfg_options)
}
None => {
stdx::never!("fn HAS_SELF_PARAM but no parameters allocated");
true
}
};
let is_cfgd_out =
!item_tree.attrs(db, krate, attr_owner(0usize)).is_cfg_enabled(cfg_options);
if is_cfgd_out {
cov_mark::hit!(cfgd_out_self_param);
flags.remove(FnFlags::HAS_SELF_PARAM);
@ -101,9 +85,14 @@ impl FunctionData {
Arc::new(FunctionData {
name: func.name.clone(),
params: enabled_params
.clone()
.filter_map(|id| item_tree[id].type_ref.clone())
params: func
.params
.iter()
.enumerate()
.filter(|&(idx, _)| {
item_tree.attrs(db, krate, attr_owner(idx)).is_cfg_enabled(cfg_options)
})
.map(|(_, param)| param.type_ref.clone())
.collect(),
ret_type: func.ret_type.clone(),
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
@ -629,7 +618,8 @@ impl<'a> AssocItemCollector<'a> {
if !attrs.is_cfg_enabled(self.expander.cfg_options()) {
self.diagnostics.push(DefDiagnostic::unconfigured_code(
self.module_id.local_id,
InFile::new(self.expander.current_file_id(), item.ast_id(item_tree).erase()),
tree_id,
ModItem::from(item).into(),
attrs.cfg().unwrap(),
self.expander.cfg_options().clone(),
));

View file

@ -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(

View file

@ -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,
}

View file

@ -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(&param);
let idx = match param.dotdotdot_token() {
Some(_) => self
.data()
.params
.alloc(Param { type_ref: None, ast_id: ParamAstId::Param(ast_id) }),
push_attr(params.len(), RawAttrs::new(self.db.upcast(), &param, self.span_map()));
let param = match param.dotdotdot_token() {
Some(_) => {
has_var_args = true;
Param { type_ref: Interned::new(TypeRef::Error) }
}
None => {
let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty());
let ty = Interned::new(type_ref);
self.data()
.params
.alloc(Param { type_ref: Some(ty), ast_id: ParamAstId::Param(ast_id) })
Param { type_ref: ty }
}
};
self.add_attrs(
idx.into(),
RawAttrs::new(self.db.upcast(), &param, self.span_map()),
);
params.push(param);
}
}
let end_param = self.next_param_idx();
let params = IdxRange::new(start_param..end_param);
let ret_type = match func.ret_type() {
Some(rt) => match rt.ty() {
@ -417,19 +440,25 @@ impl<'a> Ctx<'a> {
if func.unsafe_token().is_some() {
flags |= FnFlags::HAS_UNSAFE_KW;
}
if has_var_args {
flags |= FnFlags::IS_VARARGS;
}
let res = Function {
name,
visibility,
explicit_generic_params: self.lower_generic_params(HasImplicitSelf::No, func),
abi,
params,
params: params.into_boxed_slice(),
ret_type: Interned::new(ret_type),
ast_id,
flags,
};
let id = id(self.data().functions.alloc(res));
for (idx, attr) in attrs {
self.add_attrs(AttrOwner::Param(id, Idx::from_raw(RawIdx::from_u32(idx as u32))), attr);
}
self.write_generic_params_attributes(id.into());
Some(id)
}
@ -725,21 +754,11 @@ impl<'a> Ctx<'a> {
}
}
fn next_field_idx(&self) -> Idx<Field> {
Idx::from_raw(RawIdx::from(
self.tree.data.as_ref().map_or(0, |data| data.fields.len() as u32),
))
}
fn next_variant_idx(&self) -> Idx<Variant> {
Idx::from_raw(RawIdx::from(
self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32),
))
}
fn next_param_idx(&self) -> Idx<Param> {
Idx::from_raw(RawIdx::from(
self.tree.data.as_ref().map_or(0, |data| data.params.len() as u32),
))
}
}
fn desugar_future_path(orig: TypeRef) -> Path {

View file

@ -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, ",");
}
});

View file

@ -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

View file

@ -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(),
));

View file

@ -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(

View file

@ -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,

View file

@ -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())
}
}

View file

@ -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 {

View file

@ -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(')')?;

View file

@ -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);

View file

@ -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.