diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index b0f16ad6f4..ba88495e14 100644 --- a/crates/hir-def/src/attr.rs +++ b/crates/hir-def/src/attr.rs @@ -20,7 +20,7 @@ use triomphe::Arc; use crate::{ db::DefDatabase, - item_tree::{AttrOwner, Fields, ItemTreeNode}, + item_tree::{AttrOwner, FieldParent, ItemTreeNode}, lang_item::LangItem, nameres::{ModuleOrigin, ModuleSource}, src::{HasChildSource, HasSource}, @@ -76,40 +76,36 @@ impl Attrs { let mut res = ArenaMap::default(); let crate_graph = db.crate_graph(); - let (fields, item_tree, krate) = match v { + let item_tree; + let (parent, fields, krate) = match v { VariantId::EnumVariantId(it) => { let loc = it.lookup(db); let krate = loc.parent.lookup(db).container.krate; - let item_tree = loc.id.item_tree(db); + item_tree = loc.id.item_tree(db); let variant = &item_tree[loc.id.value]; - (variant.fields.clone(), item_tree, krate) + (FieldParent::Variant(loc.id.value), &variant.fields, krate) } VariantId::StructId(it) => { let loc = it.lookup(db); let krate = loc.container.krate; - let item_tree = loc.id.item_tree(db); + item_tree = loc.id.item_tree(db); let struct_ = &item_tree[loc.id.value]; - (struct_.fields.clone(), item_tree, krate) + (FieldParent::Struct(loc.id.value), &struct_.fields, krate) } VariantId::UnionId(it) => { let loc = it.lookup(db); let krate = loc.container.krate; - let item_tree = loc.id.item_tree(db); + item_tree = loc.id.item_tree(db); let union_ = &item_tree[loc.id.value]; - (union_.fields.clone(), item_tree, krate) + (FieldParent::Union(loc.id.value), &union_.fields, krate) } }; - let fields = match fields { - Fields::Record(fields) | Fields::Tuple(fields) => fields, - Fields::Unit => return Arc::new(res), - }; - let cfg_options = &crate_graph[krate].cfg_options; let mut idx = 0; - for field in fields { - let attrs = item_tree.attrs(db, krate, field.into()); + for (id, _field) in fields.iter().enumerate() { + let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, id)); if attrs.is_cfg_enabled(cfg_options) { res.insert(Idx::from_raw(RawIdx::from(idx)), attrs); idx += 1; diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index 3486928e41..9e1bff98f8 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -11,7 +11,7 @@ use std::ops::{Deref, Index}; use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; use hir_expand::{name::Name, InFile}; -use la_arena::{Arena, ArenaMap}; +use la_arena::{Arena, ArenaMap, Idx, RawIdx}; use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::MacroFileId; @@ -24,6 +24,7 @@ use crate::{ hir::{ dummy_expr_id, Binding, BindingId, Expr, ExprId, Label, LabelId, Pat, PatId, RecordFieldPat, }, + item_tree::AttrOwner, nameres::DefMap, path::{ModPath, Path}, src::HasSource, @@ -136,16 +137,23 @@ impl Body { let data = db.function_data(f); let f = f.lookup(db); let src = f.source(db); - params = src.value.param_list().map(|param_list| { + params = src.value.param_list().map(move |param_list| { let item_tree = f.id.item_tree(db); let func = &item_tree[f.id.value]; let krate = f.container.module(db).krate; let crate_graph = db.crate_graph(); ( param_list, - func.params.clone().map(move |param| { + (0..func.params.len()).map(move |idx| { item_tree - .attrs(db, krate, param.into()) + .attrs( + db, + krate, + AttrOwner::Param( + f.id.value, + Idx::from_raw(RawIdx::from(idx as u32)), + ), + ) .is_cfg_enabled(&crate_graph[krate].cfg_options) }), ) diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 37506b6cdc..3f862f69f8 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -7,6 +7,7 @@ use hir_expand::{ name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind, }; use intern::{sym, Interned, Symbol}; +use la_arena::{Idx, RawIdx}; use smallvec::SmallVec; use syntax::{ast, Parse}; use triomphe::Arc; @@ -58,37 +59,31 @@ 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); } } + if flags.contains(FnFlags::IS_VARARGS) { + if let Some((_, param)) = func.params.iter().enumerate().rev().find(|&(idx, _)| { + item_tree.attrs(db, krate, attr_owner(idx)).is_cfg_enabled(cfg_options) + }) { + if param.type_ref.is_some() { + flags.remove(FnFlags::IS_VARARGS); + } + } else { + flags.remove(FnFlags::IS_VARARGS); + } + } let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); let legacy_const_generics_indices = attrs @@ -101,9 +96,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) + }) + .filter_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 +629,8 @@ impl<'a> AssocItemCollector<'a> { if !attrs.is_cfg_enabled(self.expander.cfg_options()) { self.diagnostics.push(DefDiagnostic::unconfigured_code( self.module_id.local_id, - InFile::new(self.expander.current_file_id(), item.ast_id(item_tree).erase()), + tree_id, + ModItem::from(item).into(), attrs.cfg().unwrap(), self.expander.cfg_options().clone(), )); diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs index cc6e408b65..827cce706b 100644 --- a/crates/hir-def/src/data/adt.rs +++ b/crates/hir-def/src/data/adt.rs @@ -7,7 +7,7 @@ use either::Either; use hir_expand::{ name::{AsName, Name}, - HirFileId, InFile, + InFile, }; use intern::{sym, Interned}; use la_arena::Arena; @@ -18,7 +18,9 @@ use triomphe::Arc; use crate::{ builtin_type::{BuiltinInt, BuiltinUint}, db::DefDatabase, - item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId}, + item_tree::{ + AttrOwner, Field, FieldParent, FieldsShape, ItemTree, ModItem, RawVisibilityId, TreeId, + }, lang_item::LangItem, lower::LowerCtx, nameres::diagnostics::{DefDiagnostic, DefDiagnostics}, @@ -211,20 +213,25 @@ impl StructData { } let strukt = &item_tree[loc.id.value]; - let (variant_data, diagnostics) = lower_fields( + let (data, diagnostics) = lower_fields( db, krate, - loc.id.file_id(), loc.container.local_id, + loc.id.tree_id(), &item_tree, &db.crate_graph()[krate].cfg_options, + FieldParent::Struct(loc.id.value), &strukt.fields, None, ); ( Arc::new(StructData { name: strukt.name.clone(), - variant_data: Arc::new(variant_data), + variant_data: Arc::new(match strukt.shape { + FieldsShape::Record => VariantData::Record(data), + FieldsShape::Tuple => VariantData::Tuple(data), + FieldsShape::Unit => VariantData::Unit, + }), repr, visibility: item_tree[strukt.visibility].clone(), flags, @@ -256,20 +263,21 @@ impl StructData { } let union = &item_tree[loc.id.value]; - let (variant_data, diagnostics) = lower_fields( + let (data, diagnostics) = lower_fields( db, krate, - loc.id.file_id(), loc.container.local_id, + loc.id.tree_id(), &item_tree, &db.crate_graph()[krate].cfg_options, + FieldParent::Union(loc.id.value), &union.fields, None, ); ( Arc::new(StructData { name: union.name.clone(), - variant_data: Arc::new(variant_data), + variant_data: Arc::new(VariantData::Record(data)), repr, visibility: item_tree[union.visibility].clone(), flags, @@ -336,13 +344,14 @@ impl EnumVariantData { let item_tree = loc.id.item_tree(db); let variant = &item_tree[loc.id.value]; - let (var_data, diagnostics) = lower_fields( + let (data, diagnostics) = lower_fields( db, krate, - loc.id.file_id(), container.local_id, + loc.id.tree_id(), &item_tree, &db.crate_graph()[krate].cfg_options, + FieldParent::Variant(loc.id.value), &variant.fields, Some(item_tree[loc.parent.lookup(db).id.value].visibility), ); @@ -350,7 +359,11 @@ impl EnumVariantData { ( Arc::new(EnumVariantData { name: variant.name.clone(), - variant_data: Arc::new(var_data), + variant_data: Arc::new(match variant.shape { + FieldsShape::Record => VariantData::Record(data), + FieldsShape::Tuple => VariantData::Tuple(data), + FieldsShape::Unit => VariantData::Unit, + }), }), DefDiagnostics::new(diagnostics), ) @@ -396,21 +409,23 @@ pub enum StructKind { Unit, } +// FIXME This is only used for mapping back source now? pub(crate) fn lower_struct( db: &dyn DefDatabase, trace: &mut Trace>, ast: &InFile, 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, -) -> (VariantData, Vec) { +) -> (Arena, Vec) { 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( diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 479beea4a9..28eebb286e 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -47,7 +47,7 @@ use base_db::CrateId; use either::Either; use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile}; use intern::{Interned, Symbol}; -use la_arena::{Arena, Idx, IdxRange, RawIdx}; +use la_arena::{Arena, Idx, RawIdx}; use once_cell::sync::OnceCell; use rustc_hash::FxHashMap; use smallvec::SmallVec; @@ -218,9 +218,7 @@ impl ItemTree { extern_crates, extern_blocks, functions, - params, structs, - fields, unions, enums, variants, @@ -241,9 +239,7 @@ impl ItemTree { extern_crates.shrink_to_fit(); extern_blocks.shrink_to_fit(); functions.shrink_to_fit(); - params.shrink_to_fit(); structs.shrink_to_fit(); - fields.shrink_to_fit(); unions.shrink_to_fit(); enums.shrink_to_fit(); variants.shrink_to_fit(); @@ -295,9 +291,7 @@ struct ItemTreeData { extern_crates: Arena, extern_blocks: Arena, functions: Arena, - params: Arena, structs: Arena, - fields: Arena, unions: Arena, enums: Arena, variants: Arena, @@ -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), - Field(Idx), - Param(Idx), + Field(FieldParent, ItemTreeFieldId), + Param(FileItemTreeId, 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), + Union(FileItemTreeId), + Variant(FileItemTreeId), +} + +pub type ItemTreeParamId = Idx; +pub type ItemTreeFieldId = Idx; + macro_rules! from_attrs { ( $( $var:ident($t:ty) ),+ $(,)? ) => { $( @@ -341,12 +351,7 @@ macro_rules! from_attrs { }; } -from_attrs!( - ModItem(ModItem), - Variant(FileItemTreeId), - Field(Idx), - Param(Idx), -); +from_attrs!(ModItem(ModItem), Variant(FileItemTreeId)); /// Trait implemented by all nodes in the item tree. pub trait ItemTreeNode: Clone { @@ -365,7 +370,7 @@ pub trait GenericsItemTreeNode: ItemTreeNode { pub struct FileItemTreeId(Idx); impl FileItemTreeId { - pub fn range_iter(range: Range) -> impl Iterator { + pub fn range_iter(range: Range) -> impl Iterator + 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 { + pub fn item_tree(&self, db: &dyn DefDatabase) -> Arc { 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 { + match self { + $(ModItem::$typ(it) => tree[it.index()].ast_id().upcast()),+ + } + } + } + + impl GenericModItem { + pub fn ast_id(&self, tree: &ItemTree) -> FileAstId { + match self { + $( + $( + #[cfg_attr(ignore_fragment, $generic_params)] + GenericModItem::$typ(it) => tree[it.index()].ast_id().upcast(), + )? + )+ + } + } + } + impl From 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> 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 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, pub abi: Option, - pub params: IdxRange, + pub params: Box<[Param]>, pub ret_type: Interned, pub ast_id: FileAstId, 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>, - pub ast_id: ParamAstId, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ParamAstId { - Param(FileAstId), - SelfParam(FileAstId), } bitflags::bitflags! { @@ -760,7 +762,8 @@ pub struct Struct { pub name: Name, pub visibility: RawVisibilityId, pub generic_params: Interned, - pub fields: Fields, + pub fields: Box<[Field]>, + pub shape: FieldsShape, pub ast_id: FileAstId, } @@ -769,7 +772,7 @@ pub struct Union { pub name: Name, pub visibility: RawVisibilityId, pub generic_params: Interned, - pub fields: Fields, + pub fields: Box<[Field]>, pub ast_id: FileAstId, } @@ -782,6 +785,29 @@ pub struct Enum { pub ast_id: FileAstId, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Variant { + pub name: Name, + pub fields: Box<[Field]>, + pub shape: FieldsShape, + pub ast_id: FileAstId, +} + +#[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, + 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 { - 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, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum Fields { - Record(IdxRange), - Tuple(IdxRange), - Unit, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum FieldAstId { - Record(FileAstId), - Tuple(FileAstId), -} - -/// A single field of an enum variant or struct -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Field { - pub name: Name, - pub type_ref: Interned, - pub visibility: RawVisibilityId, - pub ast_id: FieldAstId, -} diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index 67092ae0c0..7aac383ab4 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -17,12 +17,12 @@ use crate::{ db::DefDatabase, generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance}, item_tree::{ - AssocItem, AttrOwner, Const, Either, Enum, ExternBlock, ExternCrate, Field, FieldAstId, - Fields, FileItemTreeId, FnFlags, Function, GenericArgs, GenericModItem, Idx, IdxRange, - Impl, ImportAlias, Interned, ItemTree, ItemTreeData, ItemTreeNode, Macro2, MacroCall, - MacroRules, Mod, ModItem, ModKind, ModPath, Mutability, Name, Param, ParamAstId, Path, - Range, RawAttrs, RawIdx, RawVisibilityId, Static, Struct, StructKind, Trait, TraitAlias, - TypeAlias, Union, Use, UseTree, UseTreeKind, Variant, + AssocItem, AttrOwner, Const, Either, Enum, ExternBlock, ExternCrate, Field, FieldParent, + FieldsShape, FileItemTreeId, FnFlags, Function, GenericArgs, GenericModItem, Idx, Impl, + ImportAlias, Interned, ItemTree, ItemTreeData, Macro2, MacroCall, MacroRules, Mod, ModItem, + ModKind, ModPath, Mutability, Name, Param, Path, Range, RawAttrs, RawIdx, RawVisibilityId, + Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, + Variant, }, path::AssociatedTypeBinding, type_ref::{LifetimeRef, TraitBoundModifier, TraitRef, TypeBound, TypeRef}, @@ -30,7 +30,7 @@ use crate::{ LocalLifetimeParamId, LocalTypeOrConstParamId, }; -fn id(index: Idx) -> FileItemTreeId { +fn id(index: Idx) -> FileItemTreeId { 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 { - 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 { - 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 { - 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> { 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> { 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 { - let name = variant.name()?.as_name(); - let fields = self.lower_fields(&variant.kind()); + fn lower_variant(&mut self, variant: &ast::Variant) -> Idx { + 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> { @@ -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: Some(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: None } + } 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: Some(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 { - 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 { 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 { - Idx::from_raw(RawIdx::from( - self.tree.data.as_ref().map_or(0, |data| data.params.len() as u32), - )) - } } fn desugar_future_path(orig: TypeRef) -> Path { diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index 6283ae23b5..740759e6e3 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -2,16 +2,17 @@ use std::fmt::{self, Write}; +use la_arena::{Idx, RawIdx}; use span::ErasedFileAstId; use crate::{ generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget}, item_tree::{ - AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldAstId, Fields, - FileItemTreeId, FnFlags, Function, GenericModItem, GenericParams, Impl, Interned, ItemTree, - Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, Param, ParamAstId, Path, RawAttrs, - RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound, TypeRef, Union, - Use, UseTree, UseTreeKind, Variant, + AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldParent, + FieldsShape, FileItemTreeId, FnFlags, Function, GenericModItem, GenericParams, Impl, + Interned, ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, Param, Path, + RawAttrs, RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound, + TypeRef, Union, Use, UseTree, UseTreeKind, Variant, }, pretty::{print_path, print_type_bounds, print_type_ref}, visibility::RawVisibility, @@ -118,19 +119,17 @@ impl Printer<'_> { }; } - fn print_fields(&mut self, fields: &Fields) { - match fields { - Fields::Record(fields) => { + fn print_fields(&mut self, parent: FieldParent, kind: FieldsShape, fields: &[Field]) { + match kind { + FieldsShape::Record => { self.whitespace(); w!(self, "{{"); self.indented(|this| { - for field in fields.clone() { - let Field { visibility, name, type_ref, ast_id } = &this.tree[field]; - this.print_ast_id(match ast_id { - FieldAstId::Record(it) => it.erase(), - FieldAstId::Tuple(it) => it.erase(), - }); - this.print_attrs_of(field, "\n"); + for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() { + this.print_attrs_of( + AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))), + "\n", + ); this.print_visibility(*visibility); w!(this, "{}: ", name.display(self.db.upcast())); this.print_type_ref(type_ref); @@ -139,16 +138,14 @@ impl Printer<'_> { }); w!(self, "}}"); } - Fields::Tuple(fields) => { + FieldsShape::Tuple => { w!(self, "("); self.indented(|this| { - for field in fields.clone() { - let Field { visibility, name, type_ref, ast_id } = &this.tree[field]; - this.print_ast_id(match ast_id { - FieldAstId::Record(it) => it.erase(), - FieldAstId::Tuple(it) => it.erase(), - }); - this.print_attrs_of(field, "\n"); + for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() { + this.print_attrs_of( + AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))), + "\n", + ); this.print_visibility(*visibility); w!(this, "{}: ", name.display(self.db.upcast())); this.print_type_ref(type_ref); @@ -157,24 +154,30 @@ impl Printer<'_> { }); w!(self, ")"); } - Fields::Unit => {} + FieldsShape::Unit => {} } } - fn print_fields_and_where_clause(&mut self, fields: &Fields, params: &GenericParams) { - match fields { - Fields::Record(_) => { + fn print_fields_and_where_clause( + &mut self, + parent: FieldParent, + kind: FieldsShape, + fields: &[Field], + params: &GenericParams, + ) { + match kind { + FieldsShape::Record => { if self.print_where_clause(params) { wln!(self); } - self.print_fields(fields); + self.print_fields(parent, kind, fields); } - Fields::Unit => { + FieldsShape::Unit => { self.print_where_clause(params); - self.print_fields(fields); + self.print_fields(parent, kind, fields); } - Fields::Tuple(_) => { - self.print_fields(fields); + FieldsShape::Tuple => { + self.print_fields(parent, kind, fields); self.print_where_clause(params); } } @@ -280,25 +283,20 @@ impl Printer<'_> { w!(self, "("); if !params.is_empty() { self.indented(|this| { - for param in params.clone() { - this.print_attrs_of(param, "\n"); - let Param { type_ref, ast_id } = &this.tree[param]; - this.print_ast_id(match ast_id { - ParamAstId::Param(it) => it.erase(), - ParamAstId::SelfParam(it) => it.erase(), - }); - match type_ref { - Some(ty) => { - if flags.contains(FnFlags::HAS_SELF_PARAM) { - w!(this, "self: "); - } - this.print_type_ref(ty); - wln!(this, ","); - } - None => { - wln!(this, "..."); - } - }; + for (idx, Param { type_ref }) in params.iter().enumerate() { + this.print_attrs_of( + AttrOwner::Param(it, Idx::from_raw(RawIdx::from(idx as u32))), + "\n", + ); + if idx == 0 && flags.contains(FnFlags::HAS_SELF_PARAM) { + w!(this, "self: "); + } + if let Some(type_ref) = type_ref { + this.print_type_ref(type_ref); + } else { + wln!(this, "..."); + } + wln!(this, ","); } }); } @@ -312,13 +310,19 @@ impl Printer<'_> { } } ModItem::Struct(it) => { - let Struct { visibility, name, fields, generic_params, ast_id } = &self.tree[it]; + let Struct { visibility, name, fields, shape: kind, generic_params, ast_id } = + &self.tree[it]; self.print_ast_id(ast_id.erase()); self.print_visibility(*visibility); w!(self, "struct {}", name.display(self.db.upcast())); self.print_generic_params(generic_params, it.into()); - self.print_fields_and_where_clause(fields, generic_params); - if matches!(fields, Fields::Record(_)) { + self.print_fields_and_where_clause( + FieldParent::Struct(it), + *kind, + fields, + generic_params, + ); + if matches!(kind, FieldsShape::Record) { wln!(self); } else { wln!(self, ";"); @@ -330,12 +334,13 @@ impl Printer<'_> { self.print_visibility(*visibility); w!(self, "union {}", name.display(self.db.upcast())); self.print_generic_params(generic_params, it.into()); - self.print_fields_and_where_clause(fields, generic_params); - if matches!(fields, Fields::Record(_)) { - wln!(self); - } else { - wln!(self, ";"); - } + self.print_fields_and_where_clause( + FieldParent::Union(it), + FieldsShape::Record, + fields, + generic_params, + ); + wln!(self); } ModItem::Enum(it) => { let Enum { name, visibility, variants, generic_params, ast_id } = &self.tree[it]; @@ -346,11 +351,11 @@ impl Printer<'_> { self.print_where_clause_and_opening_brace(generic_params); self.indented(|this| { for variant in FileItemTreeId::range_iter(variants.clone()) { - let Variant { name, fields, ast_id } = &this.tree[variant]; + let Variant { name, fields, shape: kind, ast_id } = &this.tree[variant]; this.print_ast_id(ast_id.erase()); this.print_attrs_of(variant, "\n"); w!(this, "{}", name.display(self.db.upcast())); - this.print_fields(fields); + this.print_fields(FieldParent::Variant(variant), *kind, fields); wln!(this, ","); } }); diff --git a/crates/hir-def/src/item_tree/tests.rs b/crates/hir-def/src/item_tree/tests.rs index 79bab11998..c6930401a6 100644 --- a/crates/hir-def/src/item_tree/tests.rs +++ b/crates/hir-def/src/item_tree/tests.rs @@ -129,40 +129,34 @@ enum E { #[derive(Debug)] // AstId: 2 pub(self) struct Struct { - // AstId: 6 #[doc = " fld docs"] pub(self) fld: (), } // AstId: 3 pub(self) struct Tuple( - // AstId: 7 #[attr] pub(self) 0: u8, ); // AstId: 4 pub(self) union Ize { - // AstId: 8 pub(self) a: (), - // AstId: 9 pub(self) b: (), } // AstId: 5 pub(self) enum E { - // AstId: 10 + // AstId: 6 #[doc = " comment on Unit"] Unit, - // AstId: 11 + // AstId: 7 #[doc = " comment on Tuple"] Tuple( - // AstId: 13 pub(self) 0: u8, ), - // AstId: 12 + // AstId: 8 Struct { - // AstId: 14 #[doc = " comment on a: u8"] pub(self) a: u8, }, @@ -201,9 +195,7 @@ trait Tr: SuperTrait + 'lifetime { // AstId: 3 pub(self) fn f( #[attr] - // AstId: 5 u8, - // AstId: 6 (), ) -> () { ... } @@ -213,12 +205,11 @@ trait Tr: SuperTrait + 'lifetime { Self: SuperTrait, Self: 'lifetime { - // AstId: 8 + // AstId: 6 pub(self) type Assoc: AssocBound = Default; - // AstId: 9 + // AstId: 7 pub(self) fn method( - // AstId: 10 self: &Self, ) -> (); } @@ -300,17 +291,11 @@ struct S { expect![[r#" // AstId: 1 pub(self) struct S { - // AstId: 2 pub(self) a: self::Ty, - // AstId: 3 pub(self) b: super::SuperTy, - // AstId: 4 pub(self) c: super::super::SuperSuperTy, - // AstId: 5 pub(self) d: ::abs::Path, - // AstId: 6 pub(self) e: crate::Crate, - // AstId: 7 pub(self) f: plain::path::Ty, } "#]], @@ -331,13 +316,9 @@ struct S { expect![[r#" // AstId: 1 pub(self) struct S { - // AstId: 2 pub(self) a: Mixed::<'a, T, Item = (), OtherItem = u8>, - // AstId: 3 pub(self) b: Qualified::::Syntax, - // AstId: 4 pub(self) c: ::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( - // 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( - // AstId: 13 impl Copy, ) -> impl Copy where diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 58aca96429..c51eea22dc 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -23,7 +23,7 @@ use itertools::{izip, Itertools}; use la_arena::Idx; use limit::Limit; use rustc_hash::{FxHashMap, FxHashSet}; -use span::{Edition, EditionedFileId, ErasedFileAstId, FileAstId, SyntaxContextId}; +use span::{Edition, EditionedFileId, FileAstId, SyntaxContextId}; use syntax::ast; use triomphe::Arc; @@ -32,8 +32,8 @@ use crate::{ db::DefDatabase, item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports}, item_tree::{ - self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, - Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, + self, AttrOwner, ExternCrate, FieldsShape, FileItemTreeId, ImportKind, ItemTree, + ItemTreeId, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, }, macro_call_as_call_id, macro_call_as_call_id_with_eager, nameres::{ @@ -1580,10 +1580,7 @@ impl ModCollector<'_, '_> { let attrs = self.item_tree.attrs(db, krate, item.into()); if let Some(cfg) = attrs.cfg() { if !self.is_cfg_enabled(&cfg) { - self.emit_unconfigured_diagnostic( - InFile::new(self.file_id(), item.ast_id(self.item_tree).erase()), - &cfg, - ); + self.emit_unconfigured_diagnostic(self.tree_id, item.into(), &cfg); return; } } @@ -1699,7 +1696,7 @@ impl ModCollector<'_, '_> { .into(), &it.name, vis, - !matches!(it.fields, Fields::Record(_)), + !matches!(it.shape, FieldsShape::Record), ); } ModItem::Union(id) => { @@ -1737,10 +1734,8 @@ impl ModCollector<'_, '_> { match is_enabled { Err(cfg) => { self.emit_unconfigured_diagnostic( - InFile::new( - self.file_id(), - self.item_tree[variant.index()].ast_id.erase(), - ), + self.tree_id, + variant.into(), &cfg, ); None @@ -1956,7 +1951,8 @@ impl ModCollector<'_, '_> { match is_enabled { Err(cfg) => { self.emit_unconfigured_diagnostic( - ast_id.map(|it| it.erase()), + self.tree_id, + AttrOwner::TopLevel, &cfg, ); } @@ -2402,10 +2398,11 @@ impl ModCollector<'_, '_> { self.def_collector.cfg_options.check(cfg) != Some(false) } - fn emit_unconfigured_diagnostic(&mut self, ast_id: InFile, cfg: &CfgExpr) { + fn emit_unconfigured_diagnostic(&mut self, tree_id: TreeId, item: AttrOwner, cfg: &CfgExpr) { self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code( self.module_id, - ast_id, + tree_id, + item, cfg.clone(), self.def_collector.cfg_options.clone(), )); diff --git a/crates/hir-def/src/nameres/diagnostics.rs b/crates/hir-def/src/nameres/diagnostics.rs index 4ab53d20b5..e1bd6966f3 100644 --- a/crates/hir-def/src/nameres/diagnostics.rs +++ b/crates/hir-def/src/nameres/diagnostics.rs @@ -4,12 +4,12 @@ use std::ops::Not; use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; -use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind}; +use hir_expand::{attrs::AttrId, MacroCallKind}; use la_arena::Idx; use syntax::ast; use crate::{ - item_tree::{self, ItemTreeId}, + item_tree::{self, AttrOwner, ItemTreeId, TreeId}, nameres::LocalModuleId, path::ModPath, AstId, @@ -29,7 +29,8 @@ pub enum DefDiagnosticKind { index: Idx, }, UnconfiguredCode { - ast: ErasedAstId, + tree: TreeId, + item: AttrOwner, cfg: CfgExpr, opts: CfgOptions, }, @@ -116,11 +117,15 @@ impl DefDiagnostic { pub fn unconfigured_code( container: LocalModuleId, - ast: ErasedAstId, + tree: TreeId, + item: AttrOwner, cfg: CfgExpr, opts: CfgOptions, ) -> Self { - Self { in_module: container, kind: DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } } + Self { + in_module: container, + kind: DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts }, + } } pub fn unresolved_proc_macro( diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index e797d19223..75cab137f7 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -17,7 +17,7 @@ use triomphe::Arc; use crate::{ db::DefDatabase, item_scope::{ImportOrExternCrate, BUILTIN_SCOPE}, - item_tree::Fields, + item_tree::FieldsShape, nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs}, path::{ModPath, PathKind}, per_ns::PerNs, @@ -381,11 +381,11 @@ impl DefMap { .iter() .find_map(|&variant| { let variant_data = &tree[variant.lookup(db).id.value]; - (variant_data.name == *segment).then(|| match variant_data.fields { - Fields::Record(_) => { + (variant_data.name == *segment).then(|| match variant_data.shape { + FieldsShape::Record => { PerNs::types(variant.into(), Visibility::Public, None) } - Fields::Tuple(_) | Fields::Unit => PerNs::both( + FieldsShape::Tuple | FieldsShape::Unit => PerNs::both( variant.into(), variant.into(), Visibility::Public, diff --git a/crates/hir-def/src/src.rs b/crates/hir-def/src/src.rs index a0d2079e0d..6db20870cf 100644 --- a/crates/hir-def/src/src.rs +++ b/crates/hir-def/src/src.rs @@ -6,9 +6,12 @@ use la_arena::ArenaMap; use syntax::{ast, AstNode, AstPtr}; use crate::{ - data::adt::lower_struct, db::DefDatabase, item_tree::ItemTreeNode, trace::Trace, GenericDefId, - ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, UseId, - VariantId, + data::adt::lower_struct, + db::DefDatabase, + item_tree::{FieldParent, ItemTreeNode}, + trace::Trace, + GenericDefId, ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, + UseId, VariantId, }; pub trait HasSource { @@ -124,13 +127,13 @@ impl HasChildSource for VariantId { fn child_source(&self, db: &dyn DefDatabase) -> InFile> { 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 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 for VariantId { item_tree = lookup.id.item_tree(db); ( lookup.source(db).map(|it| it.kind()), - &item_tree[lookup.id.value].fields, + FieldParent::Union(lookup.id.value), lookup.container, ) } }; let mut trace = Trace::new_for_map(); - lower_struct(db, &mut trace, &src, container.krate, &item_tree, fields); + lower_struct(db, &mut trace, &src, container.krate, &item_tree, parent); src.with_value(trace.into_map()) } } diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 82f4ad01e0..804bc53905 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -812,7 +812,7 @@ impl<'a> InferenceContext<'a> { None => self.err_ty(), }; - param_tys.push(va_list_ty) + param_tys.push(va_list_ty); } let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.new_type_var())); if let Some(self_param) = self.body.self_param { diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs index 1c1f7055ef..57866acc06 100644 --- a/crates/hir-ty/src/tests/patterns.rs +++ b/crates/hir-ty/src/tests/patterns.rs @@ -1126,6 +1126,23 @@ fn var_args() { pub struct VaListImpl<'f>; fn my_fn(foo: ...) {} //^^^ VaListImpl<'?> +fn my_fn2(bar: u32, foo: ...) {} + //^^^ VaListImpl<'?> +"#, + ); +} + +#[test] +fn var_args_cond() { + check_types( + r#" +#[lang = "va_list"] +pub struct VaListImpl<'f>; +fn my_fn(bar: u32, #[cfg(FALSE)] foo: ..., #[cfg(not(FALSE))] foo: u32) { + foo; + //^^^ u32 + +} "#, ); } diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index f80ccf84a2..7def828e95 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -114,7 +114,10 @@ impl HirDisplay for Function { } if data.is_varargs() { - f.write_str(", ...")?; + if !first { + f.write_str(", ")?; + } + f.write_str("...")?; } f.write_char(')')?; diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index dd9f1e8803..70f4a632fb 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -44,7 +44,7 @@ use hir_def::{ data::adt::VariantData, generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance}, hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat}, - item_tree::ItemTreeNode, + item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode}, lang_item::LangItemTarget, layout::{self, ReprOptions, TargetDataLayout}, nameres::{self, diagnostics::DefDiagnostic}, @@ -81,7 +81,7 @@ use rustc_hash::FxHashSet; use span::{Edition, EditionedFileId, FileId, MacroCallId}; use stdx::{impl_from, never}; use syntax::{ - ast::{self, HasAttrs as _, HasName}, + ast::{self, HasAttrs as _, HasGenericParams, HasName}, format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr, T, }; use triomphe::Arc; @@ -906,12 +906,90 @@ fn emit_def_diagnostic_( ); } - DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => { - let item = ast.to_ptr(db.upcast()); - acc.push( - InactiveCode { node: ast.with_value(item), cfg: cfg.clone(), opts: opts.clone() } + DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts } => { + let item_tree = tree.item_tree(db.upcast()); + let ast_id_map = db.ast_id_map(tree.file_id()); + // FIXME: This parses... We could probably store relative ranges for the children things + // here in the item tree? + (|| { + let process_field_list = + |field_list: Option<_>, idx: ItemTreeFieldId| match field_list? { + ast::FieldList::RecordFieldList(it) => Some(SyntaxNodePtr::new( + it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(), + )), + ast::FieldList::TupleFieldList(it) => Some(SyntaxNodePtr::new( + it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(), + )), + }; + let ptr = match *item { + AttrOwner::ModItem(it) => { + ast_id_map.get(it.ast_id(&item_tree)).syntax_node_ptr() + } + AttrOwner::TopLevel => ast_id_map.root(), + AttrOwner::Variant(it) => { + ast_id_map.get(item_tree[it].ast_id).syntax_node_ptr() + } + AttrOwner::Field(FieldParent::Variant(parent), idx) => process_field_list( + ast_id_map + .get(item_tree[parent].ast_id) + .to_node(&db.parse_or_expand(tree.file_id())) + .field_list(), + idx, + )?, + AttrOwner::Field(FieldParent::Struct(parent), idx) => process_field_list( + ast_id_map + .get(item_tree[parent.index()].ast_id) + .to_node(&db.parse_or_expand(tree.file_id())) + .field_list(), + idx, + )?, + AttrOwner::Field(FieldParent::Union(parent), idx) => SyntaxNodePtr::new( + ast_id_map + .get(item_tree[parent.index()].ast_id) + .to_node(&db.parse_or_expand(tree.file_id())) + .record_field_list()? + .fields() + .nth(idx.into_raw().into_u32() as usize)? + .syntax(), + ), + AttrOwner::Param(parent, idx) => SyntaxNodePtr::new( + ast_id_map + .get(item_tree[parent.index()].ast_id) + .to_node(&db.parse_or_expand(tree.file_id())) + .param_list()? + .params() + .nth(idx.into_raw().into_u32() as usize)? + .syntax(), + ), + AttrOwner::TypeOrConstParamData(parent, idx) => SyntaxNodePtr::new( + ast_id_map + .get(parent.ast_id(&item_tree)) + .to_node(&db.parse_or_expand(tree.file_id())) + .generic_param_list()? + .type_or_const_params() + .nth(idx.into_raw().into_u32() as usize)? + .syntax(), + ), + AttrOwner::LifetimeParamData(parent, idx) => SyntaxNodePtr::new( + ast_id_map + .get(parent.ast_id(&item_tree)) + .to_node(&db.parse_or_expand(tree.file_id())) + .generic_param_list()? + .lifetime_params() + .nth(idx.into_raw().into_u32() as usize)? + .syntax(), + ), + }; + acc.push( + InactiveCode { + node: InFile::new(tree.file_id(), ptr), + cfg: cfg.clone(), + opts: opts.clone(), + } .into(), - ); + ); + Some(()) + })(); } DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => { let (node, precise_location, macro_name, kind) = precise_macro_call_location(ast, db); diff --git a/crates/intern/src/symbol/symbols.rs b/crates/intern/src/symbol/symbols.rs index d810fac36a..2feca32ff8 100644 --- a/crates/intern/src/symbol/symbols.rs +++ b/crates/intern/src/symbol/symbols.rs @@ -56,6 +56,7 @@ macro_rules! define_symbols { define_symbols! { @WITH_NAME: + dotdotdot = "...", INTEGER_0 = "0", INTEGER_1 = "1", INTEGER_2 = "2", diff --git a/crates/span/src/ast_id.rs b/crates/span/src/ast_id.rs index 332745aae6..b61baa2244 100644 --- a/crates/span/src/ast_id.rs +++ b/crates/span/src/ast_id.rs @@ -80,13 +80,11 @@ macro_rules! register_ast_id_node { } register_ast_id_node! { impl AstIdNode for - Item, + Item, AnyHasGenericParams, Adt, Enum, Variant, Struct, - RecordField, - TupleField, Union, AssocItem, Const, @@ -104,7 +102,7 @@ register_ast_id_node! { Trait, TraitAlias, Use, - BlockExpr, ConstArg, Param, SelfParam + BlockExpr, ConstArg } /// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back. diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs index ceecffba5d..b8c5c22983 100644 --- a/crates/syntax/src/ast/generated/nodes.rs +++ b/crates/syntax/src/ast/generated/nodes.rs @@ -5106,6 +5106,14 @@ impl AstNode for AnyHasArgList { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl From for AnyHasArgList { + #[inline] + fn from(node: CallExpr) -> AnyHasArgList { AnyHasArgList { syntax: node.syntax } } +} +impl From for AnyHasArgList { + #[inline] + fn from(node: MethodCallExpr) -> AnyHasArgList { AnyHasArgList { syntax: node.syntax } } +} impl AnyHasAttrs { #[inline] pub fn new(node: T) -> AnyHasAttrs { @@ -5198,6 +5206,294 @@ impl AstNode for AnyHasAttrs { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl From for AnyHasAttrs { + #[inline] + fn from(node: ArrayExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: AsmExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: AssocItemList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: AwaitExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: BecomeExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: BinExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: BlockExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: BreakExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: CallExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: CastExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: ClosureExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: Const) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: ConstParam) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: ContinueExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: Enum) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: ExternBlock) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: ExternCrate) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: ExternItemList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: FieldExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: Fn) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: ForExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: FormatArgsExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: IdentPat) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: IfExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: Impl) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: IndexExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: ItemList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: LetExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: LetStmt) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: LifetimeParam) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: Literal) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: LoopExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: MacroCall) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: MacroDef) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: MacroRules) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: MatchArm) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: MatchArmList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: MatchExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: MethodCallExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: Module) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: OffsetOfExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: Param) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: ParenExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: PathExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: PrefixExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: RangeExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: RecordExprField) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: RecordExprFieldList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: RecordField) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: RecordPatField) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: RefExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: RestPat) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: ReturnExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: SelfParam) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: SourceFile) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: Static) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: StmtList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: Struct) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: Trait) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: TraitAlias) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: TryExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: TupleExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: TupleField) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: TypeAlias) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: TypeParam) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: UnderscoreExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: Union) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: Use) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: Variant) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: WhileExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: YeetExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} +impl From for AnyHasAttrs { + #[inline] + fn from(node: YieldExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } } +} impl AnyHasDocComments { #[inline] pub fn new(node: T) -> AnyHasDocComments { @@ -5239,6 +5535,90 @@ impl AstNode for AnyHasDocComments { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl From for AnyHasDocComments { + #[inline] + fn from(node: Const) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: Enum) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: ExternBlock) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: ExternCrate) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: Fn) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: Impl) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: MacroCall) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: MacroDef) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: MacroRules) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: Module) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: RecordField) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: SourceFile) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: Static) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: Struct) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: Trait) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: TraitAlias) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: TupleField) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: TypeAlias) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: Union) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: Use) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} +impl From for AnyHasDocComments { + #[inline] + fn from(node: Variant) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } } +} impl AnyHasGenericArgs { #[inline] pub fn new(node: T) -> AnyHasGenericArgs { @@ -5257,6 +5637,18 @@ impl AstNode for AnyHasGenericArgs { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl From for AnyHasGenericArgs { + #[inline] + fn from(node: AssocTypeArg) -> AnyHasGenericArgs { AnyHasGenericArgs { syntax: node.syntax } } +} +impl From for AnyHasGenericArgs { + #[inline] + fn from(node: MethodCallExpr) -> AnyHasGenericArgs { AnyHasGenericArgs { syntax: node.syntax } } +} +impl From for AnyHasGenericArgs { + #[inline] + fn from(node: PathSegment) -> AnyHasGenericArgs { AnyHasGenericArgs { syntax: node.syntax } } +} impl AnyHasGenericParams { #[inline] pub fn new(node: T) -> AnyHasGenericParams { @@ -5275,6 +5667,38 @@ impl AstNode for AnyHasGenericParams { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl From for AnyHasGenericParams { + #[inline] + fn from(node: Enum) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } } +} +impl From for AnyHasGenericParams { + #[inline] + fn from(node: Fn) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } } +} +impl From for AnyHasGenericParams { + #[inline] + fn from(node: Impl) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } } +} +impl From for AnyHasGenericParams { + #[inline] + fn from(node: Struct) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } } +} +impl From for AnyHasGenericParams { + #[inline] + fn from(node: Trait) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } } +} +impl From for AnyHasGenericParams { + #[inline] + fn from(node: TraitAlias) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } } +} +impl From for AnyHasGenericParams { + #[inline] + fn from(node: TypeAlias) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } } +} +impl From for AnyHasGenericParams { + #[inline] + fn from(node: Union) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } } +} impl AnyHasLoopBody { #[inline] pub fn new(node: T) -> AnyHasLoopBody { @@ -5291,6 +5715,18 @@ impl AstNode for AnyHasLoopBody { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl From for AnyHasLoopBody { + #[inline] + fn from(node: ForExpr) -> AnyHasLoopBody { AnyHasLoopBody { syntax: node.syntax } } +} +impl From for AnyHasLoopBody { + #[inline] + fn from(node: LoopExpr) -> AnyHasLoopBody { AnyHasLoopBody { syntax: node.syntax } } +} +impl From for AnyHasLoopBody { + #[inline] + fn from(node: WhileExpr) -> AnyHasLoopBody { AnyHasLoopBody { syntax: node.syntax } } +} impl AnyHasModuleItem { #[inline] pub fn new(node: T) -> AnyHasModuleItem { @@ -5307,6 +5743,18 @@ impl AstNode for AnyHasModuleItem { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl From for AnyHasModuleItem { + #[inline] + fn from(node: ItemList) -> AnyHasModuleItem { AnyHasModuleItem { syntax: node.syntax } } +} +impl From for AnyHasModuleItem { + #[inline] + fn from(node: MacroItems) -> AnyHasModuleItem { AnyHasModuleItem { syntax: node.syntax } } +} +impl From for AnyHasModuleItem { + #[inline] + fn from(node: SourceFile) -> AnyHasModuleItem { AnyHasModuleItem { syntax: node.syntax } } +} impl AnyHasName { #[inline] pub fn new(node: T) -> AnyHasName { @@ -5347,6 +5795,86 @@ impl AstNode for AnyHasName { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl From for AnyHasName { + #[inline] + fn from(node: Const) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: ConstParam) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: Enum) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: Fn) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: FormatArgsArg) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: IdentPat) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: MacroDef) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: MacroRules) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: Module) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: RecordField) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: Rename) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: SelfParam) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: Static) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: Struct) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: Trait) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: TraitAlias) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: TypeAlias) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: TypeParam) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: Union) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} +impl From for AnyHasName { + #[inline] + fn from(node: Variant) -> AnyHasName { AnyHasName { syntax: node.syntax } } +} impl AnyHasTypeBounds { #[inline] pub fn new(node: T) -> AnyHasTypeBounds { @@ -5368,6 +5896,30 @@ impl AstNode for AnyHasTypeBounds { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl From for AnyHasTypeBounds { + #[inline] + fn from(node: AssocTypeArg) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } } +} +impl From for AnyHasTypeBounds { + #[inline] + fn from(node: LifetimeParam) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } } +} +impl From for AnyHasTypeBounds { + #[inline] + fn from(node: Trait) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } } +} +impl From for AnyHasTypeBounds { + #[inline] + fn from(node: TypeAlias) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } } +} +impl From for AnyHasTypeBounds { + #[inline] + fn from(node: TypeParam) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } } +} +impl From for AnyHasTypeBounds { + #[inline] + fn from(node: WherePred) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } } +} impl AnyHasVisibility { #[inline] pub fn new(node: T) -> AnyHasVisibility { @@ -5406,6 +5958,78 @@ impl AstNode for AnyHasVisibility { #[inline] fn syntax(&self) -> &SyntaxNode { &self.syntax } } +impl From for AnyHasVisibility { + #[inline] + fn from(node: Const) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: Enum) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: ExternCrate) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: Fn) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: Impl) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: MacroDef) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: MacroRules) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: Module) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: RecordField) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: Static) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: Struct) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: Trait) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: TraitAlias) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: TupleField) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: TypeAlias) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: Union) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: Use) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} +impl From for AnyHasVisibility { + #[inline] + fn from(node: Variant) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } } +} impl std::fmt::Display for Adt { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 911e3d823d..9e0eef483b 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -1127,21 +1127,3 @@ impl From for ast::AnyHasAttrs { Self::new(node) } } - -impl From for ast::AnyHasAttrs { - fn from(node: ast::Variant) -> Self { - Self::new(node) - } -} - -impl From for ast::AnyHasAttrs { - fn from(node: ast::RecordField) -> Self { - Self::new(node) - } -} - -impl From for ast::AnyHasAttrs { - fn from(node: ast::TupleField) -> Self { - Self::new(node) - } -} diff --git a/xtask/src/codegen/grammar.rs b/xtask/src/codegen/grammar.rs index 44f12ba4ad..0352539754 100644 --- a/xtask/src/codegen/grammar.rs +++ b/xtask/src/codegen/grammar.rs @@ -261,7 +261,7 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String { .iter() .map(|name| format_ident!("{}", to_upper_snake_case(&name.name.to_string()))) .collect(); - + let nodes = nodes.iter().map(|node| format_ident!("{}", node.name)); ( quote! { #[pretty_doc_comment_placeholder_workaround] @@ -294,6 +294,15 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String { &self.syntax } } + + #( + impl From<#nodes> for #name { + #[inline] + fn from(node: #nodes) -> #name { + #name { syntax: node.syntax } + } + } + )* }, ) })