Repository: rust-lang/rust-analyzer
Pull request #17697 (2024-07-25 10:28:48)

fix: Support new cargo config get env format
Fixes https://github.com/rust-lang/rust-analyzer/issues/17686


Patch:
diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs
index ba88495e14..b0f16ad6f4 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, FieldParent, ItemTreeNode},
+    item_tree::{AttrOwner, Fields, ItemTreeNode},
     lang_item::LangItem,
     nameres::{ModuleOrigin, ModuleSource},
     src::{HasChildSource, HasSource},
@@ -76,36 +76,40 @@ impl Attrs {
         let mut res = ArenaMap::default();
 
         let crate_graph = db.crate_graph();
-        let item_tree;
-        let (parent, fields, krate) = match v {
+        let (fields, item_tree, krate) = match v {
             VariantId::EnumVariantId(it) => {
                 let loc = it.lookup(db);
                 let krate = loc.parent.lookup(db).container.krate;
-                item_tree = loc.id.item_tree(db);
+                let item_tree = loc.id.item_tree(db);
                 let variant = &item_tree[loc.id.value];
-                (FieldParent::Variant(loc.id.value), &variant.fields, krate)
+                (variant.fields.clone(), item_tree, krate)
             }
             VariantId::StructId(it) => {
                 let loc = it.lookup(db);
                 let krate = loc.container.krate;
-                item_tree = loc.id.item_tree(db);
+                let item_tree = loc.id.item_tree(db);
                 let struct_ = &item_tree[loc.id.value];
-                (FieldParent::Struct(loc.id.value), &struct_.fields, krate)
+                (struct_.fields.clone(), item_tree, krate)
             }
             VariantId::UnionId(it) => {
                 let loc = it.lookup(db);
                 let krate = loc.container.krate;
-                item_tree = loc.id.item_tree(db);
+                let item_tree = loc.id.item_tree(db);
                 let union_ = &item_tree[loc.id.value];
-                (FieldParent::Union(loc.id.value), &union_.fields, krate)
+                (union_.fields.clone(), item_tree, 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 (id, _field) in fields.iter().enumerate() {
-            let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, id));
+        for field in fields {
+            let attrs = item_tree.attrs(db, krate, field.into());
             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 9e1bff98f8..3486928e41 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, Idx, RawIdx};
+use la_arena::{Arena, ArenaMap};
 use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
 use span::MacroFileId;
@@ -24,7 +24,6 @@ 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,
@@ -137,23 +136,16 @@ impl Body {
                     let data = db.function_data(f);
                     let f = f.lookup(db);
                     let src = f.source(db);
-                    params = src.value.param_list().map(move |param_list| {
+                    params = src.value.param_list().map(|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,
-                            (0..func.params.len()).map(move |idx| {
+                            func.params.clone().map(move |param| {
                                 item_tree
-                                    .attrs(
-                                        db,
-                                        krate,
-                                        AttrOwner::Param(
-                                            f.id.value,
-                                            Idx::from_raw(RawIdx::from(idx as u32)),
-                                        ),
-                                    )
+                                    .attrs(db, krate, param.into())
                                     .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 3a3b540c13..37506b6cdc 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -7,7 +7,6 @@ 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;
@@ -40,7 +39,7 @@ pub struct FunctionData {
     pub attrs: Attrs,
     pub visibility: RawVisibility,
     pub abi: Option<Symbol>,
-    pub legacy_const_generics_indices: Option<Box<Box<[u32]>>>,
+    pub legacy_const_generics_indices: Box<[u32]>,
     pub rustc_allow_incoherent_impl: bool,
     flags: FnFlags,
 }
@@ -59,31 +58,37 @@ impl FunctionData {
 
         let crate_graph = db.crate_graph();
         let cfg_options = &crate_graph[krate].cfg_options;
-        let attr_owner = |idx| {
-            item_tree::AttrOwner::Param(loc.id.value, Idx::from_raw(RawIdx::from(idx as u32)))
-        };
+        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 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 =
-                !item_tree.attrs(db, krate, attr_owner(0usize)).is_cfg_enabled(cfg_options);
+            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
+                }
+            };
             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
@@ -91,20 +96,14 @@ impl FunctionData {
             .tt_values()
             .next()
             .map(parse_rustc_legacy_const_generics)
-            .filter(|it| !it.is_empty())
-            .map(Box::new);
+            .unwrap_or_default();
         let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists();
 
         Arc::new(FunctionData {
             name: func.name.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())
+            params: enabled_params
+                .clone()
+                .filter_map(|id| item_tree[id].type_ref.clone())
                 .collect(),
             ret_type: func.ret_type.clone(),
             attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
@@ -630,8 +629,7 @@ impl<'a> AssocItemCollector<'a> {
             if !attrs.is_cfg_enabled(self.expander.cfg_options()) {
                 self.diagnostics.push(DefDiagnostic::unconfigured_code(
                     self.module_id.local_id,
-                    tree_id,
-                    ModItem::from(item).into(),
+                    InFile::new(self.expander.current_file_id(), item.ast_id(item_tree).erase()),
                     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 827cce706b..cc6e408b65 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},
-    InFile,
+    HirFileId, InFile,
 };
 use intern::{sym, Interned};
 use la_arena::Arena;
@@ -18,9 +18,7 @@ use triomphe::Arc;
 use crate::{
     builtin_type::{BuiltinInt, BuiltinUint},
     db::DefDatabase,
-    item_tree::{
-        AttrOwner, Field, FieldParent, FieldsShape, ItemTree, ModItem, RawVisibilityId, TreeId,
-    },
+    item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
     lang_item::LangItem,
     lower::LowerCtx,
     nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
@@ -213,25 +211,20 @@ impl StructData {
         }
 
         let strukt = &item_tree[loc.id.value];
-        let (data, diagnostics) = lower_fields(
+        let (variant_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(match strukt.shape {
-                    FieldsShape::Record => VariantData::Record(data),
-                    FieldsShape::Tuple => VariantData::Tuple(data),
-                    FieldsShape::Unit => VariantData::Unit,
-                }),
+                variant_data: Arc::new(variant_data),
                 repr,
                 visibility: item_tree[strukt.visibility].clone(),
                 flags,
@@ -263,21 +256,20 @@ impl StructData {
         }
 
         let union = &item_tree[loc.id.value];
-        let (data, diagnostics) = lower_fields(
+        let (variant_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(VariantData::Record(data)),
+                variant_data: Arc::new(variant_data),
                 repr,
                 visibility: item_tree[union.visibility].clone(),
                 flags,
@@ -344,14 +336,13 @@ impl EnumVariantData {
         let item_tree = loc.id.item_tree(db);
         let variant = &item_tree[loc.id.value];
 
-        let (data, diagnostics) = lower_fields(
+        let (var_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),
         );
@@ -359,11 +350,7 @@ impl EnumVariantData {
         (
             Arc::new(EnumVariantData {
                 name: variant.name.clone(),
-                variant_data: Arc::new(match variant.shape {
-                    FieldsShape::Record => VariantData::Record(data),
-                    FieldsShape::Tuple => VariantData::Tuple(data),
-                    FieldsShape::Unit => VariantData::Unit,
-                }),
+                variant_data: Arc::new(var_data),
             }),
             DefDiagnostics::new(diagnostics),
         )
@@ -409,23 +396,21 @@ 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,
-    parent: FieldParent,
+    fields: &Fields,
 ) -> StructKind {
     let ctx = LowerCtx::new(db, ast.file_id);
 
-    match &ast.value {
-        ast::StructKind::Tuple(fl) => {
+    match (&ast.value, fields) {
+        (ast::StructKind::Tuple(fl), Fields::Tuple(fields)) => {
             let cfg_options = &db.crate_graph()[krate].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) {
+            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) {
                     continue;
                 }
 
@@ -442,11 +427,10 @@ pub(crate) fn lower_struct(
             }
             StructKind::Tuple
         }
-        ast::StructKind::Record(fl) => {
+        (ast::StructKind::Record(fl), Fields::Record(fields)) => {
             let cfg_options = &db.crate_graph()[krate].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) {
+            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) {
                     continue;
                 }
 
@@ -470,32 +454,65 @@ 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,
-    parent: FieldParent,
-    fields: &[Field],
+    fields: &Fields,
     override_visibility: Option<RawVisibilityId>,
-) -> (Arena<FieldData>, Vec<DefDiagnostic>) {
+) -> (VariantData, Vec<DefDiagnostic>) {
     let mut diagnostics = Vec::new();
-    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(),
-            ))
+    match fields {
+        Fields::Record(flds) => {
+            let mut arena = Arena::new();
+            for field_id in flds.clone() {
+                let attrs = item_tree.attrs(db, krate, field_id.into());
+                let field = &item_tree[field_id];
+                if attrs.is_cfg_enabled(cfg_options) {
+                    arena.alloc(lower_field(item_tree, field, override_visibility));
+                } else {
+                    diagnostics.push(DefDiagnostic::unconfigured_code(
+                        container,
+                        InFile::new(
+                            current_file_id,
+                            match field.ast_id {
+                                FieldAstId::Record(it) => it.erase(),
+                                FieldAstId::Tuple(it) => it.erase(),
+                            },
+                        ),
+                        attrs.cfg().unwrap(),
+                        cfg_options.clone(),
+                    ))
+                }
+            }
+            (VariantData::Record(arena), diagnostics)
+        }
+        Fields::Tuple(flds) => {
+            let mut arena = Arena::new();
+            for field_id in flds.clone() {
+                let attrs = item_tree.attrs(db, krate, field_id.into());
+                let field = &item_tree[field_id];
+                if attrs.is_cfg_enabled(cfg_options) {
+                    arena.alloc(lower_field(item_tree, field, override_visibility));
+                } else {
+                    diagnostics.push(DefDiagnostic::unconfigured_code(
+                        container,
+                        InFile::new(
+                            current_file_id,
+                            match field.ast_id {
+                                FieldAstId::Record(it) => it.erase(),
+                                FieldAstId::Tuple(it) => it.erase(),
+                            },
+                        ),
+                        attrs.cfg().unwrap(),
+                        cfg_options.clone(),
+                    ))
+                }
+            }
+            (VariantData::Tuple(arena), diagnostics)
         }
+        Fields::Unit => (VariantData::Unit, diagnostics),
     }
-    (arena, diagnostics)
 }
 
 fn lower_field(
diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs
index 4cca42ed1a..9b05432258 100644
--- a/crates/hir-def/src/hir/type_ref.rs
+++ b/crates/hir-def/src/hir/type_ref.rs
@@ -121,7 +121,7 @@ pub enum TypeRef {
     Slice(Box<TypeRef>),
     /// A fn pointer. Last element of the vector is the return type.
     Fn(
-        Box<[(Option<Name>, TypeRef)]>,
+        Vec<(Option<Name>, TypeRef)>,
         bool,           /*varargs*/
         bool,           /*is_unsafe*/
         Option<Symbol>, /* abi */
@@ -228,7 +228,7 @@ impl TypeRef {
                         })
                         .collect()
                 } else {
-                    Vec::with_capacity(1)
+                    Vec::new()
                 };
                 fn lower_abi(abi: ast::Abi) -> Symbol {
                     match abi.abi_string() {
@@ -240,7 +240,7 @@ impl TypeRef {
 
                 let abi = inner.abi().map(lower_abi);
                 params.push((None, ret_ty));
-                TypeRef::Fn(params.into(), is_varargs, inner.unsafe_token().is_some(), abi)
+                TypeRef::Fn(params, is_varargs, inner.unsafe_token().is_some(), abi)
             }
             // for types are close enough for our purposes to the inner type for now...
             ast::Type::ForType(inner) => TypeRef::from_ast_opt(ctx, inner.ty()),
@@ -396,7 +396,7 @@ impl TypeBound {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum ConstRef {
-    Scalar(Box<LiteralConstRef>),
+    Scalar(LiteralConstRef),
     Path(Name),
     Complex(AstId<ast::ConstArg>),
 }
@@ -408,7 +408,7 @@ impl ConstRef {
                 return Self::from_expr(expr, Some(lower_ctx.ast_id(&arg)));
             }
         }
-        Self::Scalar(Box::new(LiteralConstRef::Unknown))
+        Self::Scalar(LiteralConstRef::Unknown)
     }
 
     pub(crate) fn from_const_param(
@@ -452,10 +452,10 @@ impl ConstRef {
             ast::Expr::PathExpr(p) if is_path_ident(&p) => {
                 match p.path().and_then(|it| it.segment()).and_then(|it| it.name_ref()) {
                     Some(it) => Self::Path(it.as_name()),
-                    None => Self::Scalar(Box::new(LiteralConstRef::Unknown)),
+                    None => Self::Scalar(LiteralConstRef::Unknown),
                 }
             }
-            ast::Expr::Literal(literal) => Self::Scalar(Box::new(match literal.kind() {
+            ast::Expr::Literal(literal) => Self::Scalar(match literal.kind() {
                 ast::LiteralKind::IntNumber(num) => {
                     num.value().map(LiteralConstRef::UInt).unwrap_or(LiteralConstRef::Unknown)
                 }
@@ -464,12 +464,12 @@ impl ConstRef {
                 }
                 ast::LiteralKind::Bool(f) => LiteralConstRef::Bool(f),
                 _ => LiteralConstRef::Unknown,
-            })),
+            }),
             _ => {
                 if let Some(ast_id) = ast_id {
                     Self::Complex(ast_id)
                 } else {
-                    Self::Scalar(Box::new(LiteralConstRef::Unknown))
+                    Self::Scalar(LiteralConstRef::Unknown)
                 }
             }
         }
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 28eebb286e..479beea4a9 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, RawIdx};
+use la_arena::{Arena, Idx, IdxRange, RawIdx};
 use once_cell::sync::OnceCell;
 use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
@@ -218,7 +218,9 @@ impl ItemTree {
                 extern_crates,
                 extern_blocks,
                 functions,
+                params,
                 structs,
+                fields,
                 unions,
                 enums,
                 variants,
@@ -239,7 +241,9 @@ 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();
@@ -291,7 +295,9 @@ 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>,
@@ -309,7 +315,7 @@ struct ItemTreeData {
     vis: ItemVisibilities,
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
+#[derive(Debug, Eq, PartialEq, Hash)]
 pub enum AttrOwner {
     /// Attributes on an item.
     ModItem(ModItem),
@@ -317,28 +323,12 @@ pub enum AttrOwner {
     TopLevel,
 
     Variant(FileItemTreeId<Variant>),
-    Field(FieldParent, ItemTreeFieldId),
-    Param(FileItemTreeId<Function>, ItemTreeParamId),
+    Field(Idx<Field>),
+    Param(Idx<Param>),
     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) ),+ $(,)? ) => {
         $(
@@ -351,7 +341,12 @@ macro_rules! from_attrs {
     };
 }
 
-from_attrs!(ModItem(ModItem), Variant(FileItemTreeId<Variant>));
+from_attrs!(
+    ModItem(ModItem),
+    Variant(FileItemTreeId<Variant>),
+    Field(Idx<Field>),
+    Param(Idx<Param>),
+);
 
 /// Trait implemented by all nodes in the item tree.
 pub trait ItemTreeNode: Clone {
@@ -370,7 +365,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> + Clone {
+    pub fn range_iter(range: Range<Self>) -> impl Iterator<Item = Self> {
         (range.start.index().into_raw().into_u32()..range.end.index().into_raw().into_u32())
             .map(RawIdx::from_u32)
             .map(Idx::from_raw)
@@ -422,18 +417,18 @@ impl TreeId {
         Self { file, block }
     }
 
-    pub fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
+    pub(crate) 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 fn file_id(self) -> HirFileId {
+    pub(crate) fn file_id(self) -> HirFileId {
         self.file
     }
 
-    pub fn is_block(self) -> bool {
+    pub(crate) fn is_block(self) -> bool {
         self.block.is_some()
     }
 }
@@ -510,27 +505,6 @@ 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 {
@@ -622,6 +596,22 @@ 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 {
@@ -733,7 +723,7 @@ pub struct Function {
     pub visibility: RawVisibilityId,
     pub explicit_generic_params: Interned<GenericParams>,
     pub abi: Option<Symbol>,
-    pub params: Box<[Param]>,
+    pub params: IdxRange<Param>,
     pub ret_type: Interned<TypeRef>,
     pub ast_id: FileAstId<ast::Fn>,
     pub(crate) flags: FnFlags,
@@ -741,7 +731,15 @@ 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>),
 }
 
 bitflags::bitflags! {
@@ -762,8 +760,7 @@ pub struct Struct {
     pub name: Name,
     pub visibility: RawVisibilityId,
     pub generic_params: Interned<GenericParams>,
-    pub fields: Box<[Field]>,
-    pub shape: FieldsShape,
+    pub fields: Fields,
     pub ast_id: FileAstId<ast::Struct>,
 }
 
@@ -772,7 +769,7 @@ pub struct Union {
     pub name: Name,
     pub visibility: RawVisibilityId,
     pub generic_params: Interned<GenericParams>,
-    pub fields: Box<[Field]>,
+    pub fields: Fields,
     pub ast_id: FileAstId<ast::Union>,
 }
 
@@ -785,29 +782,6 @@ 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 _: () = ();`
@@ -1065,6 +1039,28 @@ 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)]
@@ -1103,3 +1099,32 @@ impl AssocItem {
         }
     }
 }
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Variant {
+    pub name: Name,
+    pub fields: Fields,
+    pub ast_id: FileAstId<ast::Variant>,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum Fields {
+    Record(IdxRange<Field>),
+    Tuple(IdxRange<Field>),
+    Unit,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum FieldAstId {
+    Record(FileAstId<ast::RecordField>),
+    Tuple(FileAstId<ast::TupleField>),
+}
+
+/// A single field of an enum variant or struct
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Field {
+    pub name: Name,
+    pub type_ref: Interned<TypeRef>,
+    pub visibility: RawVisibilityId,
+    pub ast_id: FieldAstId,
+}
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index 7aac383ab4..67092ae0c0 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, 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,
+        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,
     },
     path::AssociatedTypeBinding,
     type_ref::{LifetimeRef, TraitBoundModifier, TraitRef, TypeBound, TypeRef},
@@ -30,7 +30,7 @@ use crate::{
     LocalLifetimeParamId, LocalTypeOrConstParamId,
 };
 
-fn id<N>(index: Idx<N>) -> FileItemTreeId<N> {
+fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> {
     FileItemTreeId(index)
 }
 
@@ -193,98 +193,82 @@ 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, kind, attrs) = self.lower_fields(&strukt.kind());
+        let fields = self.lower_fields(&strukt.kind());
         let generic_params = self.lower_generic_params(HasImplicitSelf::No, strukt);
-        let res = Struct { name, visibility, generic_params, fields, shape: kind, ast_id };
+        let res = Struct { name, visibility, generic_params, fields, 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,
-    ) -> (Box<[Field]>, FieldsShape, Vec<(usize, RawAttrs)>) {
+    fn lower_fields(&mut self, strukt_kind: &ast::StructKind) -> Fields {
         match strukt_kind {
             ast::StructKind::Record(it) => {
-                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)
+                let range = self.lower_record_fields(it);
+                Fields::Record(range)
             }
             ast::StructKind::Tuple(it) => {
-                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)
+                let range = self.lower_tuple_fields(it);
+                Fields::Tuple(range)
             }
-            ast::StructKind::Unit => (Box::default(), FieldsShape::Unit, Vec::default()),
+            ast::StructKind::Unit => Fields::Unit,
         }
     }
 
-    fn lower_record_field(&mut self, field: &ast::RecordField) -> Field {
-        let name = match field.name() {
-            Some(name) => name.as_name(),
-            None => Name::missing(),
-        };
+    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();
         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)
+    }
 
-        Field { name, type_ref, visibility }
+    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)
     }
 
     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());
-        Field { name, type_ref, visibility }
+        let ast_id = FieldAstId::Tuple(self.source_ast_id_map.ast_id(field));
+        Field { name, type_ref, visibility, ast_id }
     }
 
     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, _, attrs) = match union.record_field_list() {
+        let fields = match union.record_field_list() {
             Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)),
-            None => (Box::default(), FieldsShape::Record, Vec::default()),
+            None => Fields::Record(IdxRange::new(self.next_field_idx()..self.next_field_idx())),
         };
         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)
     }
@@ -309,35 +293,24 @@ 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() {
-            let idx = self.lower_variant(&variant);
-            self.add_attrs(
-                id(idx).into(),
-                RawAttrs::new(self.db.upcast(), &variant, self.span_map()),
-            );
+            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 end = self.next_variant_idx();
         FileItemTreeId(start)..FileItemTreeId(end)
     }
 
-    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());
+    fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> {
+        let name = variant.name()?.as_name();
+        let fields = self.lower_fields(&variant.kind());
         let ast_id = self.source_ast_id_map.ast_id(variant);
-        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
+        let res = Variant { name, fields, ast_id };
+        Some(res)
     }
 
     fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>> {
@@ -345,20 +318,9 @@ impl<'a> Ctx<'a> {
         let name = func.name()?.as_name();
 
         let mut has_self_param = false;
-        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))
-            }
-        };
+        let start_param = self.next_param_idx();
         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 => {
@@ -380,25 +342,40 @@ impl<'a> Ctx<'a> {
                     }
                 };
                 let type_ref = Interned::new(self_type);
-                params.push(Param { type_ref: Some(type_ref) });
+                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()),
+                );
                 has_self_param = true;
             }
             for param in param_list.params() {
-                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: None }
-                    }
+                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) }),
                     None => {
                         let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty());
                         let ty = Interned::new(type_ref);
-                        Param { type_ref: Some(ty) }
+                        self.data()
+                            .params
+                            .alloc(Param { type_ref: Some(ty), ast_id: ParamAstId::Param(ast_id) })
                     }
                 };
-                params.push(param);
+                self.add_attrs(
+                    idx.into(),
+                    RawAttrs::new(self.db.upcast(), &param, self.span_map()),
+                );
             }
         }
+        let end_param = self.next_param_idx();
+        let params = IdxRange::new(start_param..end_param);
 
         let ret_type = match func.ret_type() {
             Some(rt) => match rt.ty() {
@@ -440,25 +417,19 @@ 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.into_boxed_slice(),
+            params,
             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)
     }
@@ -754,11 +725,21 @@ impl<'a> Ctx<'a> {
         }
     }
 
+    fn next_field_idx(&self) -> Idx<Field> {
+        Idx::from_raw(RawIdx::from(
+            self.tree.data.as_ref().map_or(0, |data| data.fields.len() as u32),
+        ))
+    }
     fn next_variant_idx(&self) -> Idx<Variant> {
         Idx::from_raw(RawIdx::from(
             self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32),
         ))
     }
+    fn next_param_idx(&self) -> Idx<Param> {
+        Idx::from_raw(RawIdx::from(
+            self.tree.data.as_ref().map_or(0, |data| data.params.len() as u32),
+        ))
+    }
 }
 
 fn desugar_future_path(orig: TypeRef) -> Path {
diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs
index 740759e6e3..6283ae23b5 100644
--- a/crates/hir-def/src/item_tree/pretty.rs
+++ b/crates/hir-def/src/item_tree/pretty.rs
@@ -2,17 +2,16 @@
 
 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, 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,
+        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,
     },
     pretty::{print_path, print_type_bounds, print_type_ref},
     visibility::RawVisibility,
@@ -119,17 +118,19 @@ impl Printer<'_> {
         };
     }
 
-    fn print_fields(&mut self, parent: FieldParent, kind: FieldsShape, fields: &[Field]) {
-        match kind {
-            FieldsShape::Record => {
+    fn print_fields(&mut self, fields: &Fields) {
+        match fields {
+            Fields::Record(fields) => {
                 self.whitespace();
                 w!(self, "{{");
                 self.indented(|this| {
-                    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",
-                        );
+                    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");
                         this.print_visibility(*visibility);
                         w!(this, "{}: ", name.display(self.db.upcast()));
                         this.print_type_ref(type_ref);
@@ -138,14 +139,16 @@ impl Printer<'_> {
                 });
                 w!(self, "}}");
             }
-            FieldsShape::Tuple => {
+            Fields::Tuple(fields) => {
                 w!(self, "(");
                 self.indented(|this| {
-                    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",
-                        );
+                    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");
                         this.print_visibility(*visibility);
                         w!(this, "{}: ", name.display(self.db.upcast()));
                         this.print_type_ref(type_ref);
@@ -154,30 +157,24 @@ impl Printer<'_> {
                 });
                 w!(self, ")");
             }
-            FieldsShape::Unit => {}
+            Fields::Unit => {}
         }
     }
 
-    fn print_fields_and_where_clause(
-        &mut self,
-        parent: FieldParent,
-        kind: FieldsShape,
-        fields: &[Field],
-        params: &GenericParams,
-    ) {
-        match kind {
-            FieldsShape::Record => {
+    fn print_fields_and_where_clause(&mut self, fields: &Fields, params: &GenericParams) {
+        match fields {
+            Fields::Record(_) => {
                 if self.print_where_clause(params) {
                     wln!(self);
                 }
-                self.print_fields(parent, kind, fields);
+                self.print_fields(fields);
             }
-            FieldsShape::Unit => {
+            Fields::Unit => {
                 self.print_where_clause(params);
-                self.print_fields(parent, kind, fields);
+                self.print_fields(fields);
             }
-            FieldsShape::Tuple => {
-                self.print_fields(parent, kind, fields);
+            Fields::Tuple(_) => {
+                self.print_fields(fields);
                 self.print_where_clause(params);
             }
         }
@@ -283,20 +280,25 @@ impl Printer<'_> {
                 w!(self, "(");
                 if !params.is_empty() {
                     self.indented(|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, ",");
+                        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, "...");
+                                }
+                            };
                         }
                     });
                 }
@@ -310,19 +312,13 @@ impl Printer<'_> {
                 }
             }
             ModItem::Struct(it) => {
-                let Struct { visibility, name, fields, shape: kind, generic_params, ast_id } =
-                    &self.tree[it];
+                let Struct { visibility, name, fields, 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(
-                    FieldParent::Struct(it),
-                    *kind,
-                    fields,
-                    generic_params,
-                );
-                if matches!(kind, FieldsShape::Record) {
+                self.print_fields_and_where_clause(fields, generic_params);
+                if matches!(fields, Fields::Record(_)) {
                     wln!(self);
                 } else {
                     wln!(self, ";");
@@ -334,13 +330,12 @@ 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(
-                    FieldParent::Union(it),
-                    FieldsShape::Record,
-                    fields,
-                    generic_params,
-                );
-                wln!(self);
+                self.print_fields_and_where_clause(fields, generic_params);
+                if matches!(fields, Fields::Record(_)) {
+                    wln!(self);
+                } else {
+                    wln!(self, ";");
+                }
             }
             ModItem::Enum(it) => {
                 let Enum { name, visibility, variants, generic_params, ast_id } = &self.tree[it];
@@ -351,11 +346,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, shape: kind, ast_id } = &this.tree[variant];
+                        let Variant { name, fields, 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(FieldParent::Variant(variant), *kind, fields);
+                        this.print_fields(fields);
                         wln!(this, ",");
                     }
                 });
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index c51eea22dc..58aca96429 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, FileAstId, SyntaxContextId};
+use span::{Edition, EditionedFileId, ErasedFileAstId, 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, AttrOwner, ExternCrate, FieldsShape, FileItemTreeId, ImportKind, ItemTree,
-        ItemTreeId, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
+        self, ExternCrate, Fields, 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,7 +1580,10 @@ 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(self.tree_id, item.into(), &cfg);
+                    self.emit_unconfigured_diagnostic(
+                        InFile::new(self.file_id(), item.ast_id(self.item_tree).erase()),
+                        &cfg,
+                    );
                     return;
                 }
             }
@@ -1696,7 +1699,7 @@ impl ModCollector<'_, '_> {
                             .into(),
                         &it.name,
                         vis,
-                        !matches!(it.shape, FieldsShape::Record),
+                        !matches!(it.fields, Fields::Record(_)),
                     );
                 }
                 ModItem::Union(id) => {
@@ -1734,8 +1737,10 @@ impl ModCollector<'_, '_> {
                             match is_enabled {
                                 Err(cfg) => {
                                     self.emit_unconfigured_diagnostic(
-                                        self.tree_id,
-                                        variant.into(),
+                                        InFile::new(
+                                            self.file_id(),
+                                            self.item_tree[variant.index()].ast_id.erase(),
+                                        ),
                                         &cfg,
                                     );
                                     None
@@ -1951,8 +1956,7 @@ impl ModCollector<'_, '_> {
                         match is_enabled {
                             Err(cfg) => {
                                 self.emit_unconfigured_diagnostic(
-                                    self.tree_id,
-                                    AttrOwner::TopLevel,
+                                    ast_id.map(|it| it.erase()),
                                     &cfg,
                                 );
                             }
@@ -2398,11 +2402,10 @@ impl ModCollector<'_, '_> {
         self.def_collector.cfg_options.check(cfg) != Some(false)
     }
 
-    fn emit_unconfigured_diagnostic(&mut self, tree_id: TreeId, item: AttrOwner, cfg: &CfgExpr) {
+    fn emit_unconfigured_diagnostic(&mut self, ast_id: InFile<ErasedFileAstId>, cfg: &CfgExpr) {
         self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
             self.module_id,
-            tree_id,
-            item,
+            ast_id,
             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 e1bd6966f3..4ab53d20b5 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, MacroCallKind};
+use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind};
 use la_arena::Idx;
 use syntax::ast;
 
 use crate::{
-    item_tree::{self, AttrOwner, ItemTreeId, TreeId},
+    item_tree::{self, ItemTreeId},
     nameres::LocalModuleId,
     path::ModPath,
     AstId,
@@ -29,8 +29,7 @@ pub enum DefDiagnosticKind {
         index: Idx<ast::UseTree>,
     },
     UnconfiguredCode {
-        tree: TreeId,
-        item: AttrOwner,
+        ast: ErasedAstId,
         cfg: CfgExpr,
         opts: CfgOptions,
     },
@@ -117,15 +116,11 @@ impl DefDiagnostic {
 
     pub fn unconfigured_code(
         container: LocalModuleId,
-        tree: TreeId,
-        item: AttrOwner,
+        ast: ErasedAstId,
         cfg: CfgExpr,
         opts: CfgOptions,
     ) -> Self {
-        Self {
-            in_module: container,
-            kind: DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts },
-        }
+        Self { in_module: container, kind: DefDiagnosticKind::UnconfiguredCode { ast, 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 75cab137f7..e797d19223 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::FieldsShape,
+    item_tree::Fields,
     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.shape {
-                            FieldsShape::Record => {
+                        (variant_data.name == *segment).then(|| match variant_data.fields {
+                            Fields::Record(_) => {
                                 PerNs::types(variant.into(), Visibility::Public, None)
                             }
-                            FieldsShape::Tuple | FieldsShape::Unit => PerNs::both(
+                            Fields::Tuple(_) | Fields::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 6db20870cf..a0d2079e0d 100644
--- a/crates/hir-def/src/src.rs
+++ b/crates/hir-def/src/src.rs
@@ -6,12 +6,9 @@ use la_arena::ArenaMap;
 use syntax::{ast, AstNode, AstPtr};
 
 use crate::{
-    data::adt::lower_struct,
-    db::DefDatabase,
-    item_tree::{FieldParent, ItemTreeNode},
-    trace::Trace,
-    GenericDefId, ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup,
-    UseId, VariantId,
+    data::adt::lower_struct, db::DefDatabase, item_tree::ItemTreeNode, trace::Trace, GenericDefId,
+    ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, UseId,
+    VariantId,
 };
 
 pub trait HasSource {
@@ -127,13 +124,13 @@ impl HasChildSource<LocalFieldId> for VariantId {
 
     fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<LocalFieldId, Self::Value>> {
         let item_tree;
-        let (src, parent, container) = match *self {
+        let (src, fields, 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()),
-                    FieldParent::Variant(lookup.id.value),
+                    &item_tree[lookup.id.value].fields,
                     lookup.parent.lookup(db).container,
                 )
             }
@@ -142,7 +139,7 @@ impl HasChildSource<LocalFieldId> for VariantId {
                 item_tree = lookup.id.item_tree(db);
                 (
                     lookup.source(db).map(|it| it.kind()),
-                    FieldParent::Struct(lookup.id.value),
+                    &item_tree[lookup.id.value].fields,
                     lookup.container,
                 )
             }
@@ -151,13 +148,13 @@ impl HasChildSource<LocalFieldId> for VariantId {
                 item_tree = lookup.id.item_tree(db);
                 (
                     lookup.source(db).map(|it| it.kind()),
-                    FieldParent::Union(lookup.id.value),
+                    &item_tree[lookup.id.value].fields,
                     lookup.container,
                 )
             }
         };
         let mut trace = Trace::new_for_map();
-        lower_struct(db, &mut trace, &src, container.krate, &item_tree, parent);
+        lower_struct(db, &mut trace, &src, container.krate, &item_tree, fields);
         src.with_value(trace.into_map())
     }
 }
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 804bc53905..82f4ad01e0 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/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 24479a027f..87233fa011 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -1950,25 +1950,25 @@ impl InferenceContext<'_> {
         };
 
         let data = self.db.function_data(func);
-        let Some(legacy_const_generics_indices) = &data.legacy_const_generics_indices else {
+        if data.legacy_const_generics_indices.is_empty() {
             return Default::default();
-        };
+        }
 
         // only use legacy const generics if the param count matches with them
-        if data.params.len() + legacy_const_generics_indices.len() != args.len() {
+        if data.params.len() + data.legacy_const_generics_indices.len() != args.len() {
             if args.len() <= data.params.len() {
                 return Default::default();
             } else {
                 // there are more parameters than there should be without legacy
                 // const params; use them
-                let mut indices = legacy_const_generics_indices.as_ref().clone();
+                let mut indices = data.legacy_const_generics_indices.clone();
                 indices.sort();
                 return indices;
             }
         }
 
         // check legacy const parameters
-        for (subst_idx, arg_idx) in legacy_const_generics_indices.iter().copied().enumerate() {
+        for (subst_idx, arg_idx) in data.legacy_const_generics_indices.iter().copied().enumerate() {
             let arg = match subst.at(Interner, subst_idx).constant(Interner) {
                 Some(c) => c,
                 None => continue, // not a const parameter?
@@ -1981,7 +1981,7 @@ impl InferenceContext<'_> {
             self.infer_expr(args[arg_idx as usize], &expected);
             // FIXME: evaluate and unify with the const
         }
-        let mut indices = legacy_const_generics_indices.as_ref().clone();
+        let mut indices = data.legacy_const_generics_indices.clone();
         indices.sort();
         indices
     }
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 7def828e95..f80ccf84a2 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -114,10 +114,7 @@ impl HirDisplay for Function {
         }
 
         if data.is_varargs() {
-            if !first {
-                f.write_str(", ")?;
-            }
-            f.write_str("...")?;
+            f.write_str(", ...")?;
         }
 
         f.write_char(')')?;
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 70f4a632fb..dd9f1e8803 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::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
+    item_tree::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 _, HasGenericParams, HasName},
+    ast::{self, HasAttrs as _, HasName},
     format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr, T,
 };
 use triomphe::Arc;
@@ -906,90 +906,12 @@ fn emit_def_diagnostic_(
             );
         }
 
-        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(),
-                    }
+        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() }
                     .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 2feca32ff8..d810fac36a 100644
--- a/crates/intern/src/symbol/symbols.rs
+++ b/crates/intern/src/symbol/symbols.rs
@@ -56,7 +56,6 @@ macro_rules! define_symbols {
 define_symbols! {
     @WITH_NAME:
 
-    dotdotdot = "...",
     INTEGER_0 = "0",
     INTEGER_1 = "1",
     INTEGER_2 = "2",
diff --git a/crates/project-model/src/env.rs b/crates/project-model/src/env.rs
index 88fb10a68c..3df46e1e37 100644
--- a/crates/project-model/src/env.rs
+++ b/crates/project-model/src/env.rs
@@ -75,14 +75,26 @@ pub(crate) fn cargo_config_env(
     }
     // if successful we receive `env.key.value = "value" per entry
     tracing::debug!("Discovering cargo config env by {:?}", cargo_config);
-    utf8_stdout(cargo_config).map(parse_output_cargo_config_env).unwrap_or_default()
+    utf8_stdout(cargo_config)
+        .map(parse_output_cargo_config_env)
+        .inspect(|env| {
+            tracing::debug!("Discovered cargo config env: {:?}", env);
+        })
+        .inspect_err(|err| {
+            tracing::error!("Failed to discover cargo config env: {:?}", err);
+        })
+        .unwrap_or_default()
 }
 
 fn parse_output_cargo_config_env(stdout: String) -> FxHashMap<String, String> {
     stdout
         .lines()
         .filter_map(|l| l.strip_prefix("env."))
-        .filter_map(|l| l.split_once(".value = "))
+        .filter_map(|l| {
+            l.split_once(" = ")
+                // cargo used to report it with this, keep it for a couple releases around
+                .or_else(|| l.split_once(".value = "))
+        })
         .map(|(key, value)| (key.to_owned(), value.trim_matches('"').to_owned()))
         .collect()
 }
diff --git a/crates/span/src/ast_id.rs b/crates/span/src/ast_id.rs
index b61baa2244..332745aae6 100644
--- a/crates/span/src/ast_id.rs
+++ b/crates/span/src/ast_id.rs
@@ -80,11 +80,13 @@ macro_rules! register_ast_id_node {
 }
 register_ast_id_node! {
     impl AstIdNode for
-    Item, AnyHasGenericParams,
+    Item,
         Adt,
             Enum,
                 Variant,
             Struct,
+                RecordField,
+                TupleField,
             Union,
         AssocItem,
             Const,
@@ -102,7 +104,7 @@ register_ast_id_node! {
         Trait,
         TraitAlias,
         Use,
-    BlockExpr, ConstArg
+    BlockExpr, ConstArg, Param, SelfParam
 }
 
 /// 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 b8c5c22983..ceecffba5d 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -5106,14 +5106,6 @@ impl AstNode for AnyHasArgList {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl From<CallExpr> for AnyHasArgList {
-    #[inline]
-    fn from(node: CallExpr) -> AnyHasArgList { AnyHasArgList { syntax: node.syntax } }
-}
-impl From<MethodCallExpr> for AnyHasArgList {
-    #[inline]
-    fn from(node: MethodCallExpr) -> AnyHasArgList { AnyHasArgList { syntax: node.syntax } }
-}
 impl AnyHasAttrs {
     #[inline]
     pub fn new<T: ast::HasAttrs>(node: T) -> AnyHasAttrs {
@@ -5206,294 +5198,6 @@ impl AstNode for AnyHasAttrs {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl From<ArrayExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: ArrayExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<AsmExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: AsmExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<AssocItemList> for AnyHasAttrs {
-    #[inline]
-    fn from(node: AssocItemList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<AwaitExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: AwaitExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<BecomeExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: BecomeExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<BinExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: BinExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<BlockExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: BlockExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<BreakExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: BreakExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<CallExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: CallExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<CastExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: CastExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<ClosureExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: ClosureExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<Const> for AnyHasAttrs {
-    #[inline]
-    fn from(node: Const) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<ConstParam> for AnyHasAttrs {
-    #[inline]
-    fn from(node: ConstParam) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<ContinueExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: ContinueExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<Enum> for AnyHasAttrs {
-    #[inline]
-    fn from(node: Enum) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<ExternBlock> for AnyHasAttrs {
-    #[inline]
-    fn from(node: ExternBlock) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<ExternCrate> for AnyHasAttrs {
-    #[inline]
-    fn from(node: ExternCrate) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<ExternItemList> for AnyHasAttrs {
-    #[inline]
-    fn from(node: ExternItemList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<FieldExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: FieldExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<Fn> for AnyHasAttrs {
-    #[inline]
-    fn from(node: Fn) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<ForExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: ForExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<FormatArgsExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: FormatArgsExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<IdentPat> for AnyHasAttrs {
-    #[inline]
-    fn from(node: IdentPat) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<IfExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: IfExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<Impl> for AnyHasAttrs {
-    #[inline]
-    fn from(node: Impl) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<IndexExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: IndexExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<ItemList> for AnyHasAttrs {
-    #[inline]
-    fn from(node: ItemList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<LetExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: LetExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<LetStmt> for AnyHasAttrs {
-    #[inline]
-    fn from(node: LetStmt) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<LifetimeParam> for AnyHasAttrs {
-    #[inline]
-    fn from(node: LifetimeParam) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<Literal> for AnyHasAttrs {
-    #[inline]
-    fn from(node: Literal) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<LoopExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: LoopExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<MacroCall> for AnyHasAttrs {
-    #[inline]
-    fn from(node: MacroCall) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<MacroDef> for AnyHasAttrs {
-    #[inline]
-    fn from(node: MacroDef) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<MacroRules> for AnyHasAttrs {
-    #[inline]
-    fn from(node: MacroRules) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<MatchArm> for AnyHasAttrs {
-    #[inline]
-    fn from(node: MatchArm) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<MatchArmList> for AnyHasAttrs {
-    #[inline]
-    fn from(node: MatchArmList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<MatchExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: MatchExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<MethodCallExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: MethodCallExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<Module> for AnyHasAttrs {
-    #[inline]
-    fn from(node: Module) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<OffsetOfExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: OffsetOfExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<Param> for AnyHasAttrs {
-    #[inline]
-    fn from(node: Param) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<ParenExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: ParenExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<PathExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: PathExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<PrefixExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: PrefixExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<RangeExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: RangeExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<RecordExprField> for AnyHasAttrs {
-    #[inline]
-    fn from(node: RecordExprField) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<RecordExprFieldList> for AnyHasAttrs {
-    #[inline]
-    fn from(node: RecordExprFieldList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<RecordField> for AnyHasAttrs {
-    #[inline]
-    fn from(node: RecordField) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<RecordPatField> for AnyHasAttrs {
-    #[inline]
-    fn from(node: RecordPatField) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<RefExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: RefExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<RestPat> for AnyHasAttrs {
-    #[inline]
-    fn from(node: RestPat) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<ReturnExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: ReturnExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<SelfParam> for AnyHasAttrs {
-    #[inline]
-    fn from(node: SelfParam) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<SourceFile> for AnyHasAttrs {
-    #[inline]
-    fn from(node: SourceFile) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<Static> for AnyHasAttrs {
-    #[inline]
-    fn from(node: Static) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<StmtList> for AnyHasAttrs {
-    #[inline]
-    fn from(node: StmtList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<Struct> for AnyHasAttrs {
-    #[inline]
-    fn from(node: Struct) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<Trait> for AnyHasAttrs {
-    #[inline]
-    fn from(node: Trait) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<TraitAlias> for AnyHasAttrs {
-    #[inline]
-    fn from(node: TraitAlias) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<TryExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: TryExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<TupleExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: TupleExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<TupleField> for AnyHasAttrs {
-    #[inline]
-    fn from(node: TupleField) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<TypeAlias> for AnyHasAttrs {
-    #[inline]
-    fn from(node: TypeAlias) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<TypeParam> for AnyHasAttrs {
-    #[inline]
-    fn from(node: TypeParam) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<UnderscoreExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: UnderscoreExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<Union> for AnyHasAttrs {
-    #[inline]
-    fn from(node: Union) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<Use> for AnyHasAttrs {
-    #[inline]
-    fn from(node: Use) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<Variant> for AnyHasAttrs {
-    #[inline]
-    fn from(node: Variant) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<WhileExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: WhileExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<YeetExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: YeetExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
-impl From<YieldExpr> for AnyHasAttrs {
-    #[inline]
-    fn from(node: YieldExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
-}
 impl AnyHasDocComments {
     #[inline]
     pub fn new<T: ast::HasDocComments>(node: T) -> AnyHasDocComments {
@@ -5535,90 +5239,6 @@ impl AstNode for AnyHasDocComments {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl From<Const> for AnyHasDocComments {
-    #[inline]
-    fn from(node: Const) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<Enum> for AnyHasDocComments {
-    #[inline]
-    fn from(node: Enum) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<ExternBlock> for AnyHasDocComments {
-    #[inline]
-    fn from(node: ExternBlock) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<ExternCrate> for AnyHasDocComments {
-    #[inline]
-    fn from(node: ExternCrate) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<Fn> for AnyHasDocComments {
-    #[inline]
-    fn from(node: Fn) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<Impl> for AnyHasDocComments {
-    #[inline]
-    fn from(node: Impl) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<MacroCall> for AnyHasDocComments {
-    #[inline]
-    fn from(node: MacroCall) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<MacroDef> for AnyHasDocComments {
-    #[inline]
-    fn from(node: MacroDef) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<MacroRules> for AnyHasDocComments {
-    #[inline]
-    fn from(node: MacroRules) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<Module> for AnyHasDocComments {
-    #[inline]
-    fn from(node: Module) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<RecordField> for AnyHasDocComments {
-    #[inline]
-    fn from(node: RecordField) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<SourceFile> for AnyHasDocComments {
-    #[inline]
-    fn from(node: SourceFile) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<Static> for AnyHasDocComments {
-    #[inline]
-    fn from(node: Static) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<Struct> for AnyHasDocComments {
-    #[inline]
-    fn from(node: Struct) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<Trait> for AnyHasDocComments {
-    #[inline]
-    fn from(node: Trait) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<TraitAlias> for AnyHasDocComments {
-    #[inline]
-    fn from(node: TraitAlias) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<TupleField> for AnyHasDocComments {
-    #[inline]
-    fn from(node: TupleField) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<TypeAlias> for AnyHasDocComments {
-    #[inline]
-    fn from(node: TypeAlias) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<Union> for AnyHasDocComments {
-    #[inline]
-    fn from(node: Union) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<Use> for AnyHasDocComments {
-    #[inline]
-    fn from(node: Use) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
-impl From<Variant> for AnyHasDocComments {
-    #[inline]
-    fn from(node: Variant) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
-}
 impl AnyHasGenericArgs {
     #[inline]
     pub fn new<T: ast::HasGenericArgs>(node: T) -> AnyHasGenericArgs {
@@ -5637,18 +5257,6 @@ impl AstNode for AnyHasGenericArgs {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl From<AssocTypeArg> for AnyHasGenericArgs {
-    #[inline]
-    fn from(node: AssocTypeArg) -> AnyHasGenericArgs { AnyHasGenericArgs { syntax: node.syntax } }
-}
-impl From<MethodCallExpr> for AnyHasGenericArgs {
-    #[inline]
-    fn from(node: MethodCallExpr) -> AnyHasGenericArgs { AnyHasGenericArgs { syntax: node.syntax } }
-}
-impl From<PathSegment> for AnyHasGenericArgs {
-    #[inline]
-    fn from(node: PathSegment) -> AnyHasGenericArgs { AnyHasGenericArgs { syntax: node.syntax } }
-}
 impl AnyHasGenericParams {
     #[inline]
     pub fn new<T: ast::HasGenericParams>(node: T) -> AnyHasGenericParams {
@@ -5667,38 +5275,6 @@ impl AstNode for AnyHasGenericParams {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl From<Enum> for AnyHasGenericParams {
-    #[inline]
-    fn from(node: Enum) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
-}
-impl From<Fn> for AnyHasGenericParams {
-    #[inline]
-    fn from(node: Fn) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
-}
-impl From<Impl> for AnyHasGenericParams {
-    #[inline]
-    fn from(node: Impl) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
-}
-impl From<Struct> for AnyHasGenericParams {
-    #[inline]
-    fn from(node: Struct) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
-}
-impl From<Trait> for AnyHasGenericParams {
-    #[inline]
-    fn from(node: Trait) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
-}
-impl From<TraitAlias> for AnyHasGenericParams {
-    #[inline]
-    fn from(node: TraitAlias) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
-}
-impl From<TypeAlias> for AnyHasGenericParams {
-    #[inline]
-    fn from(node: TypeAlias) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
-}
-impl From<Union> for AnyHasGenericParams {
-    #[inline]
-    fn from(node: Union) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
-}
 impl AnyHasLoopBody {
     #[inline]
     pub fn new<T: ast::HasLoopBody>(node: T) -> AnyHasLoopBody {
@@ -5715,18 +5291,6 @@ impl AstNode for AnyHasLoopBody {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl From<ForExpr> for AnyHasLoopBody {
-    #[inline]
-    fn from(node: ForExpr) -> AnyHasLoopBody { AnyHasLoopBody { syntax: node.syntax } }
-}
-impl From<LoopExpr> for AnyHasLoopBody {
-    #[inline]
-    fn from(node: LoopExpr) -> AnyHasLoopBody { AnyHasLoopBody { syntax: node.syntax } }
-}
-impl From<WhileExpr> for AnyHasLoopBody {
-    #[inline]
-    fn from(node: WhileExpr) -> AnyHasLoopBody { AnyHasLoopBody { syntax: node.syntax } }
-}
 impl AnyHasModuleItem {
     #[inline]
     pub fn new<T: ast::HasModuleItem>(node: T) -> AnyHasModuleItem {
@@ -5743,18 +5307,6 @@ impl AstNode for AnyHasModuleItem {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl From<ItemList> for AnyHasModuleItem {
-    #[inline]
-    fn from(node: ItemList) -> AnyHasModuleItem { AnyHasModuleItem { syntax: node.syntax } }
-}
-impl From<MacroItems> for AnyHasModuleItem {
-    #[inline]
-    fn from(node: MacroItems) -> AnyHasModuleItem { AnyHasModuleItem { syntax: node.syntax } }
-}
-impl From<SourceFile> for AnyHasModuleItem {
-    #[inline]
-    fn from(node: SourceFile) -> AnyHasModuleItem { AnyHasModuleItem { syntax: node.syntax } }
-}
 impl AnyHasName {
     #[inline]
     pub fn new<T: ast::HasName>(node: T) -> AnyHasName {
@@ -5795,86 +5347,6 @@ impl AstNode for AnyHasName {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl From<Const> for AnyHasName {
-    #[inline]
-    fn from(node: Const) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<ConstParam> for AnyHasName {
-    #[inline]
-    fn from(node: ConstParam) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<Enum> for AnyHasName {
-    #[inline]
-    fn from(node: Enum) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<Fn> for AnyHasName {
-    #[inline]
-    fn from(node: Fn) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<FormatArgsArg> for AnyHasName {
-    #[inline]
-    fn from(node: FormatArgsArg) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<IdentPat> for AnyHasName {
-    #[inline]
-    fn from(node: IdentPat) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<MacroDef> for AnyHasName {
-    #[inline]
-    fn from(node: MacroDef) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<MacroRules> for AnyHasName {
-    #[inline]
-    fn from(node: MacroRules) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<Module> for AnyHasName {
-    #[inline]
-    fn from(node: Module) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<RecordField> for AnyHasName {
-    #[inline]
-    fn from(node: RecordField) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<Rename> for AnyHasName {
-    #[inline]
-    fn from(node: Rename) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<SelfParam> for AnyHasName {
-    #[inline]
-    fn from(node: SelfParam) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<Static> for AnyHasName {
-    #[inline]
-    fn from(node: Static) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<Struct> for AnyHasName {
-    #[inline]
-    fn from(node: Struct) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<Trait> for AnyHasName {
-    #[inline]
-    fn from(node: Trait) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<TraitAlias> for AnyHasName {
-    #[inline]
-    fn from(node: TraitAlias) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<TypeAlias> for AnyHasName {
-    #[inline]
-    fn from(node: TypeAlias) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<TypeParam> for AnyHasName {
-    #[inline]
-    fn from(node: TypeParam) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<Union> for AnyHasName {
-    #[inline]
-    fn from(node: Union) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
-impl From<Variant> for AnyHasName {
-    #[inline]
-    fn from(node: Variant) -> AnyHasName { AnyHasName { syntax: node.syntax } }
-}
 impl AnyHasTypeBounds {
     #[inline]
     pub fn new<T: ast::HasTypeBounds>(node: T) -> AnyHasTypeBounds {
@@ -5896,30 +5368,6 @@ impl AstNode for AnyHasTypeBounds {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl From<AssocTypeArg> for AnyHasTypeBounds {
-    #[inline]
-    fn from(node: AssocTypeArg) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } }
-}
-impl From<LifetimeParam> for AnyHasTypeBounds {
-    #[inline]
-    fn from(node: LifetimeParam) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } }
-}
-impl From<Trait> for AnyHasTypeBounds {
-    #[inline]
-    fn from(node: Trait) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } }
-}
-impl From<TypeAlias> for AnyHasTypeBounds {
-    #[inline]
-    fn from(node: TypeAlias) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } }
-}
-impl From<TypeParam> for AnyHasTypeBounds {
-    #[inline]
-    fn from(node: TypeParam) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } }
-}
-impl From<WherePred> for AnyHasTypeBounds {
-    #[inline]
-    fn from(node: WherePred) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } }
-}
 impl AnyHasVisibility {
     #[inline]
     pub fn new<T: ast::HasVisibility>(node: T) -> AnyHasVisibility {
@@ -5958,78 +5406,6 @@ impl AstNode for AnyHasVisibility {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl From<Const> for AnyHasVisibility {
-    #[inline]
-    fn from(node: Const) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<Enum> for AnyHasVisibility {
-    #[inline]
-    fn from(node: Enum) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<ExternCrate> for AnyHasVisibility {
-    #[inline]
-    fn from(node: ExternCrate) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<Fn> for AnyHasVisibility {
-    #[inline]
-    fn from(node: Fn) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<Impl> for AnyHasVisibility {
-    #[inline]
-    fn from(node: Impl) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<MacroDef> for AnyHasVisibility {
-    #[inline]
-    fn from(node: MacroDef) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<MacroRules> for AnyHasVisibility {
-    #[inline]
-    fn from(node: MacroRules) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<Module> for AnyHasVisibility {
-    #[inline]
-    fn from(node: Module) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<RecordField> for AnyHasVisibility {
-    #[inline]
-    fn from(node: RecordField) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<Static> for AnyHasVisibility {
-    #[inline]
-    fn from(node: Static) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<Struct> for AnyHasVisibility {
-    #[inline]
-    fn from(node: Struct) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<Trait> for AnyHasVisibility {
-    #[inline]
-    fn from(node: Trait) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<TraitAlias> for AnyHasVisibility {
-    #[inline]
-    fn from(node: TraitAlias) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<TupleField> for AnyHasVisibility {
-    #[inline]
-    fn from(node: TupleField) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<TypeAlias> for AnyHasVisibility {
-    #[inline]
-    fn from(node: TypeAlias) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<Union> for AnyHasVisibility {
-    #[inline]
-    fn from(node: Union) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<Use> for AnyHasVisibility {
-    #[inline]
-    fn from(node: Use) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
-}
-impl From<Variant> 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 9e0eef483b..911e3d823d 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -1127,3 +1127,21 @@ impl From<ast::AssocItem> for ast::AnyHasAttrs {
         Self::new(node)
     }
 }
+
+impl From<ast::Variant> for ast::AnyHasAttrs {
+    fn from(node: ast::Variant) -> Self {
+        Self::new(node)
+    }
+}
+
+impl From<ast::RecordField> for ast::AnyHasAttrs {
+    fn from(node: ast::RecordField) -> Self {
+        Self::new(node)
+    }
+}
+
+impl From<ast::TupleField> 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 0352539754..44f12ba4ad 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,15 +294,6 @@ 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 }
-                            }
-                        }
-                    )*
                 },
             )
         })


Test patch:
diff --git a/crates/hir-def/src/item_tree/tests.rs b/crates/hir-def/src/item_tree/tests.rs
index c6930401a6..79bab11998 100644
--- a/crates/hir-def/src/item_tree/tests.rs
+++ b/crates/hir-def/src/item_tree/tests.rs
@@ -129,34 +129,40 @@ 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: 6
+                // AstId: 10
                 #[doc = " comment on Unit"]
                 Unit,
-                // AstId: 7
+                // AstId: 11
                 #[doc = " comment on Tuple"]
                 Tuple(
+                    // AstId: 13
                     pub(self) 0: u8,
                 ),
-                // AstId: 8
+                // AstId: 12
                 Struct {
+                    // AstId: 14
                     #[doc = " comment on a: u8"]
                     pub(self) a: u8,
                 },
@@ -195,7 +201,9 @@ trait Tr: SuperTrait + 'lifetime {
             // AstId: 3
             pub(self) fn f(
                 #[attr]
+                // AstId: 5
                 u8,
+                // AstId: 6
                 (),
             ) -> () { ... }
 
@@ -205,11 +213,12 @@ trait Tr: SuperTrait + 'lifetime {
                 Self: SuperTrait,
                 Self: 'lifetime
             {
-                // AstId: 6
+                // AstId: 8
                 pub(self) type Assoc: AssocBound = Default;
 
-                // AstId: 7
+                // AstId: 9
                 pub(self) fn method(
+                    // AstId: 10
                     self: &Self,
                 ) -> ();
             }
@@ -291,11 +300,17 @@ 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,
             }
         "#]],
@@ -316,9 +331,13 @@ 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>,
             }
         "#]],
@@ -352,12 +371,15 @@ 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
@@ -371,8 +393,9 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
                 T: 'a,
                 T: 'b
             {
-                // AstId: 9
+                // AstId: 12
                 pub(self) fn f<G>(
+                    // AstId: 13
                     impl Copy,
                 ) -> impl Copy
                 where
diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs
index 57866acc06..1c1f7055ef 100644
--- a/crates/hir-ty/src/tests/patterns.rs
+++ b/crates/hir-ty/src/tests/patterns.rs
@@ -1126,23 +1126,6 @@ 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
-
-}
 "#,
     );
 }