about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-def/src/item_tree.rs8
-rw-r--r--crates/hir-def/src/item_tree/lower.rs9
-rw-r--r--crates/hir-def/src/item_tree/pretty.rs6
-rw-r--r--crates/hir-def/src/nameres/collector.rs99
-rw-r--r--crates/hir-def/src/nameres/diagnostics.rs6
-rw-r--r--crates/hir-expand/src/ast_id_map.rs7
-rw-r--r--crates/hir/src/diagnostics.rs2
-rw-r--r--crates/ide-diagnostics/src/handlers/inactive_code.rs25
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs567
-rw-r--r--crates/syntax/src/tests/sourcegen_ast.rs34
10 files changed, 730 insertions, 33 deletions
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 3342d4db4aa..570344596de 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -943,6 +943,7 @@ impl AssocItem {
 pub struct Variant {
     pub name: Name,
     pub fields: Fields,
+    pub ast_id: FileAstId<ast::Variant>,
 }
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -952,10 +953,17 @@ pub enum Fields {
     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 7f2551e9418..077a1b619dd 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -184,7 +184,8 @@ impl<'a> Ctx<'a> {
         let name = field.name()?.as_name();
         let visibility = self.lower_visibility(field);
         let type_ref = self.lower_type_ref_opt(field.ty());
-        let res = Field { name, type_ref, visibility };
+        let ast_id = FieldAstId::Record(self.source_ast_id_map.ast_id(field));
+        let res = Field { name, type_ref, visibility, ast_id };
         Some(res)
     }
 
@@ -203,7 +204,8 @@ impl<'a> Ctx<'a> {
         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>> {
@@ -247,7 +249,8 @@ impl<'a> Ctx<'a> {
     fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> {
         let name = variant.name()?.as_name();
         let fields = self.lower_fields(&variant.kind());
-        let res = Variant { name, fields };
+        let ast_id = self.source_ast_id_map.ast_id(variant);
+        let res = Variant { name, fields, ast_id };
         Some(res)
     }
 
diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs
index 34dd817fd13..da1643152c2 100644
--- a/crates/hir-def/src/item_tree/pretty.rs
+++ b/crates/hir-def/src/item_tree/pretty.rs
@@ -115,7 +115,7 @@ impl<'a> Printer<'a> {
                 w!(self, "{{");
                 self.indented(|this| {
                     for field in fields.clone() {
-                        let Field { visibility, name, type_ref } = &this.tree[field];
+                        let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field];
                         this.print_attrs_of(field);
                         this.print_visibility(*visibility);
                         w!(this, "{}: ", name);
@@ -129,7 +129,7 @@ impl<'a> Printer<'a> {
                 w!(self, "(");
                 self.indented(|this| {
                     for field in fields.clone() {
-                        let Field { visibility, name, type_ref } = &this.tree[field];
+                        let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field];
                         this.print_attrs_of(field);
                         this.print_visibility(*visibility);
                         w!(this, "{}: ", name);
@@ -323,7 +323,7 @@ impl<'a> Printer<'a> {
                 self.print_where_clause_and_opening_brace(generic_params);
                 self.indented(|this| {
                     for variant in variants.clone() {
-                        let Variant { name, fields } = &this.tree[variant];
+                        let Variant { name, fields, ast_id: _ } = &this.tree[variant];
                         this.print_attrs_of(variant);
                         w!(this, "{}", name);
                         this.print_fields(fields);
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 9242b48c593..5f0cf9c4ac8 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -32,8 +32,8 @@ use crate::{
     derive_macro_as_call_id,
     item_scope::{ImportType, PerNsGlobImports},
     item_tree::{
-        self, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall,
-        MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
+        self, FieldAstId, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
+        MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
     },
     macro_call_as_call_id, macro_id_to_def_id,
     nameres::{
@@ -1511,7 +1511,10 @@ impl ModCollector<'_, '_> {
             let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
             if let Some(cfg) = attrs.cfg() {
                 if !self.is_cfg_enabled(&cfg) {
-                    self.emit_unconfigured_diagnostic(item, &cfg);
+                    self.emit_unconfigured_diagnostic(
+                        InFile::new(self.file_id(), item.ast_id(&self.item_tree).upcast()),
+                        &cfg,
+                    );
                     continue;
                 }
             }
@@ -1523,22 +1526,20 @@ impl ModCollector<'_, '_> {
             }
 
             let db = self.def_collector.db;
-            let module = self.def_collector.def_map.module_id(self.module_id);
-            let def_map = &mut self.def_collector.def_map;
+            let module_id = self.module_id;
+            let module = self.def_collector.def_map.module_id(module_id);
             let update_def =
                 |def_collector: &mut DefCollector<'_>, id, name: &Name, vis, has_constructor| {
-                    def_collector.def_map.modules[self.module_id].scope.declare(id);
+                    def_collector.def_map.modules[module_id].scope.declare(id);
                     def_collector.update(
-                        self.module_id,
+                        module_id,
                         &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
                         vis,
                         ImportType::Named,
                     )
                 };
             let resolve_vis = |def_map: &DefMap, visibility| {
-                def_map
-                    .resolve_visibility(db, self.module_id, visibility)
-                    .unwrap_or(Visibility::Public)
+                def_map.resolve_visibility(db, module_id, visibility).unwrap_or(Visibility::Public)
             };
 
             match item {
@@ -1594,6 +1595,7 @@ impl ModCollector<'_, '_> {
                     let fn_id =
                         FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
 
+                    let def_map = &self.def_collector.def_map;
                     let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
                     if self.def_collector.is_proc_macro {
                         if self.module_id == def_map.root {
@@ -1614,7 +1616,10 @@ impl ModCollector<'_, '_> {
                 ModItem::Struct(id) => {
                     let it = &self.item_tree[id];
 
-                    let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+                    self.process_fields(&it.fields);
+
+                    let vis =
+                        resolve_vis(&self.def_collector.def_map, &self.item_tree[it.visibility]);
                     update_def(
                         self.def_collector,
                         StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
@@ -1628,7 +1633,10 @@ impl ModCollector<'_, '_> {
                 ModItem::Union(id) => {
                     let it = &self.item_tree[id];
 
-                    let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+                    self.process_fields(&it.fields);
+
+                    let vis =
+                        resolve_vis(&self.def_collector.def_map, &self.item_tree[it.visibility]);
                     update_def(
                         self.def_collector,
                         UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
@@ -1642,7 +1650,21 @@ impl ModCollector<'_, '_> {
                 ModItem::Enum(id) => {
                     let it = &self.item_tree[id];
 
-                    let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+                    for id in it.variants.clone() {
+                        let variant = &self.item_tree[id];
+                        let attrs = self.item_tree.attrs(self.def_collector.db, krate, id.into());
+                        if let Some(cfg) = attrs.cfg() {
+                            if !self.is_cfg_enabled(&cfg) {
+                                self.emit_unconfigured_diagnostic(
+                                    InFile::new(self.file_id(), variant.ast_id.upcast()),
+                                    &cfg,
+                                );
+                            }
+                        }
+                    }
+
+                    let vis =
+                        resolve_vis(&self.def_collector.def_map, &self.item_tree[it.visibility]);
                     update_def(
                         self.def_collector,
                         EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
@@ -1660,7 +1682,10 @@ impl ModCollector<'_, '_> {
 
                     match &it.name {
                         Some(name) => {
-                            let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+                            let vis = resolve_vis(
+                                &self.def_collector.def_map,
+                                &self.item_tree[it.visibility],
+                            );
                             update_def(self.def_collector, const_id.into(), name, vis, false);
                         }
                         None => {
@@ -1674,7 +1699,8 @@ impl ModCollector<'_, '_> {
                 ModItem::Static(id) => {
                     let it = &self.item_tree[id];
 
-                    let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+                    let vis =
+                        resolve_vis(&self.def_collector.def_map, &self.item_tree[it.visibility]);
                     update_def(
                         self.def_collector,
                         StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) }
@@ -1688,7 +1714,8 @@ impl ModCollector<'_, '_> {
                 ModItem::Trait(id) => {
                     let it = &self.item_tree[id];
 
-                    let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+                    let vis =
+                        resolve_vis(&self.def_collector.def_map, &self.item_tree[it.visibility]);
                     update_def(
                         self.def_collector,
                         TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
@@ -1702,7 +1729,8 @@ impl ModCollector<'_, '_> {
                 ModItem::TypeAlias(id) => {
                     let it = &self.item_tree[id];
 
-                    let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+                    let vis =
+                        resolve_vis(&self.def_collector.def_map, &self.item_tree[it.visibility]);
                     update_def(
                         self.def_collector,
                         TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) }
@@ -2115,17 +2143,44 @@ impl ModCollector<'_, '_> {
         }
     }
 
+    fn process_fields(&mut self, fields: &Fields) {
+        match fields {
+            Fields::Record(range) | Fields::Tuple(range) => {
+                for id in range.clone() {
+                    let field = &self.item_tree[id];
+                    let attrs = self.item_tree.attrs(
+                        self.def_collector.db,
+                        self.def_collector.def_map.krate,
+                        id.into(),
+                    );
+                    if let Some(cfg) = attrs.cfg() {
+                        if !self.is_cfg_enabled(&cfg) {
+                            self.emit_unconfigured_diagnostic(
+                                InFile::new(
+                                    self.file_id(),
+                                    match field.ast_id {
+                                        FieldAstId::Record(it) => it.upcast(),
+                                        FieldAstId::Tuple(it) => it.upcast(),
+                                    },
+                                ),
+                                &cfg,
+                            );
+                        }
+                    }
+                }
+            }
+            Fields::Unit => {}
+        }
+    }
+
     fn is_cfg_enabled(&self, cfg: &CfgExpr) -> bool {
         self.def_collector.cfg_options.check(cfg) != Some(false)
     }
 
-    fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
-        let ast_id = item.ast_id(self.item_tree);
-
-        let ast_id = InFile::new(self.file_id(), ast_id);
+    fn emit_unconfigured_diagnostic(&mut self, ast: AstId<ast::AnyHasAttrs>, cfg: &CfgExpr) {
         self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
             self.module_id,
-            ast_id,
+            ast,
             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 ed7e920fd2b..06614229198 100644
--- a/crates/hir-def/src/nameres/diagnostics.rs
+++ b/crates/hir-def/src/nameres/diagnostics.rs
@@ -4,7 +4,7 @@ use base_db::CrateId;
 use cfg::{CfgExpr, CfgOptions};
 use hir_expand::MacroCallKind;
 use la_arena::Idx;
-use syntax::ast;
+use syntax::ast::{self, AnyHasAttrs};
 
 use crate::{
     attr::AttrId,
@@ -22,7 +22,7 @@ pub enum DefDiagnosticKind {
 
     UnresolvedImport { id: ItemTreeId<item_tree::Import>, index: Idx<ast::UseTree> },
 
-    UnconfiguredCode { ast: AstId<ast::Item>, cfg: CfgExpr, opts: CfgOptions },
+    UnconfiguredCode { ast: AstId<AnyHasAttrs>, cfg: CfgExpr, opts: CfgOptions },
 
     UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId },
 
@@ -75,7 +75,7 @@ impl DefDiagnostic {
 
     pub fn unconfigured_code(
         container: LocalModuleId,
-        ast: AstId<ast::Item>,
+        ast: AstId<ast::AnyHasAttrs>,
         cfg: CfgExpr,
         opts: CfgOptions,
     ) -> Self {
diff --git a/crates/hir-expand/src/ast_id_map.rs b/crates/hir-expand/src/ast_id_map.rs
index 11c0a6764e9..2b27db0e950 100644
--- a/crates/hir-expand/src/ast_id_map.rs
+++ b/crates/hir-expand/src/ast_id_map.rs
@@ -93,7 +93,12 @@ impl AstIdMap {
         // trait does not change ids of top-level items, which helps caching.
         bdfs(node, |it| {
             let kind = it.kind();
-            if ast::Item::can_cast(kind) || ast::BlockExpr::can_cast(kind) {
+            if ast::Item::can_cast(kind)
+                || ast::BlockExpr::can_cast(kind)
+                || ast::Variant::can_cast(kind)
+                || ast::RecordField::can_cast(kind)
+                || ast::TupleField::can_cast(kind)
+            {
                 res.alloc(&it);
                 true
             } else {
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 5edc16d8bce..c5dc60f1ec5 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -1,7 +1,7 @@
 //! Re-export diagnostics such that clients of `hir` don't have to depend on
 //! low-level crates.
 //!
-//! This probably isn't the best way to do this -- ideally, diagnistics should
+//! This probably isn't the best way to do this -- ideally, diagnostics should
 //! be expressed in terms of hir types themselves.
 use base_db::CrateId;
 use cfg::{CfgExpr, CfgOptions};
diff --git a/crates/ide-diagnostics/src/handlers/inactive_code.rs b/crates/ide-diagnostics/src/handlers/inactive_code.rs
index 04918891b25..c22e25b0637 100644
--- a/crates/ide-diagnostics/src/handlers/inactive_code.rs
+++ b/crates/ide-diagnostics/src/handlers/inactive_code.rs
@@ -140,4 +140,29 @@ trait Bar {
 "#,
         );
     }
+
+    #[test]
+    fn inactive_fields() {
+        check(
+            r#"
+enum Foo {
+  #[cfg(a)] Bar,
+//^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
+}
+
+struct Baz {
+  #[cfg(a)] baz: String,
+//^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
+}
+
+struct Qux(#[cfg(a)] String);
+         //^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
+
+union FooBar {
+  #[cfg(a)] baz: u32,
+//^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
+}
+"#,
+        );
+    }
 }
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 449402e5f5b..f4664f3aaea 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -3894,6 +3894,12 @@ impl AstNode for AnyHasArgList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From<CallExpr> for AnyHasArgList {
+    fn from(node: CallExpr) -> AnyHasArgList { AnyHasArgList::new(node) }
+}
+impl From<MethodCallExpr> for AnyHasArgList {
+    fn from(node: MethodCallExpr) -> AnyHasArgList { AnyHasArgList::new(node) }
+}
 impl AnyHasAttrs {
     #[inline]
     pub fn new<T: ast::HasAttrs>(node: T) -> AnyHasAttrs {
@@ -3978,6 +3984,207 @@ impl AstNode for AnyHasAttrs {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From<MacroCall> for AnyHasAttrs {
+    fn from(node: MacroCall) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<SourceFile> for AnyHasAttrs {
+    fn from(node: SourceFile) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<Const> for AnyHasAttrs {
+    fn from(node: Const) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<Enum> for AnyHasAttrs {
+    fn from(node: Enum) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<ExternBlock> for AnyHasAttrs {
+    fn from(node: ExternBlock) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<ExternCrate> for AnyHasAttrs {
+    fn from(node: ExternCrate) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<Fn> for AnyHasAttrs {
+    fn from(node: Fn) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<Impl> for AnyHasAttrs {
+    fn from(node: Impl) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<MacroRules> for AnyHasAttrs {
+    fn from(node: MacroRules) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<MacroDef> for AnyHasAttrs {
+    fn from(node: MacroDef) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<Module> for AnyHasAttrs {
+    fn from(node: Module) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<Static> for AnyHasAttrs {
+    fn from(node: Static) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<Struct> for AnyHasAttrs {
+    fn from(node: Struct) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<Trait> for AnyHasAttrs {
+    fn from(node: Trait) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<TypeAlias> for AnyHasAttrs {
+    fn from(node: TypeAlias) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<Union> for AnyHasAttrs {
+    fn from(node: Union) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<Use> for AnyHasAttrs {
+    fn from(node: Use) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<ItemList> for AnyHasAttrs {
+    fn from(node: ItemList) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<BlockExpr> for AnyHasAttrs {
+    fn from(node: BlockExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<SelfParam> for AnyHasAttrs {
+    fn from(node: SelfParam) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<Param> for AnyHasAttrs {
+    fn from(node: Param) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<RecordField> for AnyHasAttrs {
+    fn from(node: RecordField) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<TupleField> for AnyHasAttrs {
+    fn from(node: TupleField) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<Variant> for AnyHasAttrs {
+    fn from(node: Variant) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<AssocItemList> for AnyHasAttrs {
+    fn from(node: AssocItemList) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<ExternItemList> for AnyHasAttrs {
+    fn from(node: ExternItemList) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<ConstParam> for AnyHasAttrs {
+    fn from(node: ConstParam) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<LifetimeParam> for AnyHasAttrs {
+    fn from(node: LifetimeParam) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<TypeParam> for AnyHasAttrs {
+    fn from(node: TypeParam) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<LetStmt> for AnyHasAttrs {
+    fn from(node: LetStmt) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<ArrayExpr> for AnyHasAttrs {
+    fn from(node: ArrayExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<AwaitExpr> for AnyHasAttrs {
+    fn from(node: AwaitExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<BinExpr> for AnyHasAttrs {
+    fn from(node: BinExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<BoxExpr> for AnyHasAttrs {
+    fn from(node: BoxExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<BreakExpr> for AnyHasAttrs {
+    fn from(node: BreakExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<CallExpr> for AnyHasAttrs {
+    fn from(node: CallExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<CastExpr> for AnyHasAttrs {
+    fn from(node: CastExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<ClosureExpr> for AnyHasAttrs {
+    fn from(node: ClosureExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<ContinueExpr> for AnyHasAttrs {
+    fn from(node: ContinueExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<FieldExpr> for AnyHasAttrs {
+    fn from(node: FieldExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<ForExpr> for AnyHasAttrs {
+    fn from(node: ForExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<IfExpr> for AnyHasAttrs {
+    fn from(node: IfExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<IndexExpr> for AnyHasAttrs {
+    fn from(node: IndexExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<Literal> for AnyHasAttrs {
+    fn from(node: Literal) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<LoopExpr> for AnyHasAttrs {
+    fn from(node: LoopExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<MatchExpr> for AnyHasAttrs {
+    fn from(node: MatchExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<MethodCallExpr> for AnyHasAttrs {
+    fn from(node: MethodCallExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<ParenExpr> for AnyHasAttrs {
+    fn from(node: ParenExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<PathExpr> for AnyHasAttrs {
+    fn from(node: PathExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<PrefixExpr> for AnyHasAttrs {
+    fn from(node: PrefixExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<RangeExpr> for AnyHasAttrs {
+    fn from(node: RangeExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<RefExpr> for AnyHasAttrs {
+    fn from(node: RefExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<ReturnExpr> for AnyHasAttrs {
+    fn from(node: ReturnExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<TryExpr> for AnyHasAttrs {
+    fn from(node: TryExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<TupleExpr> for AnyHasAttrs {
+    fn from(node: TupleExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<WhileExpr> for AnyHasAttrs {
+    fn from(node: WhileExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<YieldExpr> for AnyHasAttrs {
+    fn from(node: YieldExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<LetExpr> for AnyHasAttrs {
+    fn from(node: LetExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<UnderscoreExpr> for AnyHasAttrs {
+    fn from(node: UnderscoreExpr) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<StmtList> for AnyHasAttrs {
+    fn from(node: StmtList) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<RecordExprFieldList> for AnyHasAttrs {
+    fn from(node: RecordExprFieldList) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<RecordExprField> for AnyHasAttrs {
+    fn from(node: RecordExprField) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<MatchArmList> for AnyHasAttrs {
+    fn from(node: MatchArmList) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<MatchArm> for AnyHasAttrs {
+    fn from(node: MatchArm) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<IdentPat> for AnyHasAttrs {
+    fn from(node: IdentPat) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<RestPat> for AnyHasAttrs {
+    fn from(node: RestPat) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
+impl From<RecordPatField> for AnyHasAttrs {
+    fn from(node: RecordPatField) -> AnyHasAttrs { AnyHasAttrs::new(node) }
+}
 impl AnyHasDocComments {
     #[inline]
     pub fn new<T: ast::HasDocComments>(node: T) -> AnyHasDocComments {
@@ -4015,6 +4222,66 @@ impl AstNode for AnyHasDocComments {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From<MacroCall> for AnyHasDocComments {
+    fn from(node: MacroCall) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<SourceFile> for AnyHasDocComments {
+    fn from(node: SourceFile) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<Const> for AnyHasDocComments {
+    fn from(node: Const) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<Enum> for AnyHasDocComments {
+    fn from(node: Enum) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<ExternBlock> for AnyHasDocComments {
+    fn from(node: ExternBlock) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<ExternCrate> for AnyHasDocComments {
+    fn from(node: ExternCrate) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<Fn> for AnyHasDocComments {
+    fn from(node: Fn) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<Impl> for AnyHasDocComments {
+    fn from(node: Impl) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<MacroRules> for AnyHasDocComments {
+    fn from(node: MacroRules) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<MacroDef> for AnyHasDocComments {
+    fn from(node: MacroDef) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<Module> for AnyHasDocComments {
+    fn from(node: Module) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<Static> for AnyHasDocComments {
+    fn from(node: Static) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<Struct> for AnyHasDocComments {
+    fn from(node: Struct) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<Trait> for AnyHasDocComments {
+    fn from(node: Trait) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<TypeAlias> for AnyHasDocComments {
+    fn from(node: TypeAlias) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<Union> for AnyHasDocComments {
+    fn from(node: Union) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<Use> for AnyHasDocComments {
+    fn from(node: Use) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<RecordField> for AnyHasDocComments {
+    fn from(node: RecordField) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<TupleField> for AnyHasDocComments {
+    fn from(node: TupleField) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
+impl From<Variant> for AnyHasDocComments {
+    fn from(node: Variant) -> AnyHasDocComments { AnyHasDocComments::new(node) }
+}
 impl AnyHasGenericParams {
     #[inline]
     pub fn new<T: ast::HasGenericParams>(node: T) -> AnyHasGenericParams {
@@ -4030,6 +4297,27 @@ impl AstNode for AnyHasGenericParams {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From<Enum> for AnyHasGenericParams {
+    fn from(node: Enum) -> AnyHasGenericParams { AnyHasGenericParams::new(node) }
+}
+impl From<Fn> for AnyHasGenericParams {
+    fn from(node: Fn) -> AnyHasGenericParams { AnyHasGenericParams::new(node) }
+}
+impl From<Impl> for AnyHasGenericParams {
+    fn from(node: Impl) -> AnyHasGenericParams { AnyHasGenericParams::new(node) }
+}
+impl From<Struct> for AnyHasGenericParams {
+    fn from(node: Struct) -> AnyHasGenericParams { AnyHasGenericParams::new(node) }
+}
+impl From<Trait> for AnyHasGenericParams {
+    fn from(node: Trait) -> AnyHasGenericParams { AnyHasGenericParams::new(node) }
+}
+impl From<TypeAlias> for AnyHasGenericParams {
+    fn from(node: TypeAlias) -> AnyHasGenericParams { AnyHasGenericParams::new(node) }
+}
+impl From<Union> for AnyHasGenericParams {
+    fn from(node: Union) -> AnyHasGenericParams { AnyHasGenericParams::new(node) }
+}
 impl AnyHasLoopBody {
     #[inline]
     pub fn new<T: ast::HasLoopBody>(node: T) -> AnyHasLoopBody {
@@ -4043,6 +4331,15 @@ impl AstNode for AnyHasLoopBody {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From<ForExpr> for AnyHasLoopBody {
+    fn from(node: ForExpr) -> AnyHasLoopBody { AnyHasLoopBody::new(node) }
+}
+impl From<LoopExpr> for AnyHasLoopBody {
+    fn from(node: LoopExpr) -> AnyHasLoopBody { AnyHasLoopBody::new(node) }
+}
+impl From<WhileExpr> for AnyHasLoopBody {
+    fn from(node: WhileExpr) -> AnyHasLoopBody { AnyHasLoopBody::new(node) }
+}
 impl AnyHasModuleItem {
     #[inline]
     pub fn new<T: ast::HasModuleItem>(node: T) -> AnyHasModuleItem {
@@ -4056,6 +4353,15 @@ impl AstNode for AnyHasModuleItem {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From<MacroItems> for AnyHasModuleItem {
+    fn from(node: MacroItems) -> AnyHasModuleItem { AnyHasModuleItem::new(node) }
+}
+impl From<SourceFile> for AnyHasModuleItem {
+    fn from(node: SourceFile) -> AnyHasModuleItem { AnyHasModuleItem::new(node) }
+}
+impl From<ItemList> for AnyHasModuleItem {
+    fn from(node: ItemList) -> AnyHasModuleItem { AnyHasModuleItem::new(node) }
+}
 impl AnyHasName {
     #[inline]
     pub fn new<T: ast::HasName>(node: T) -> AnyHasName {
@@ -4091,6 +4397,60 @@ impl AstNode for AnyHasName {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From<Const> for AnyHasName {
+    fn from(node: Const) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<Enum> for AnyHasName {
+    fn from(node: Enum) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<Fn> for AnyHasName {
+    fn from(node: Fn) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<MacroRules> for AnyHasName {
+    fn from(node: MacroRules) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<MacroDef> for AnyHasName {
+    fn from(node: MacroDef) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<Module> for AnyHasName {
+    fn from(node: Module) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<Static> for AnyHasName {
+    fn from(node: Static) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<Struct> for AnyHasName {
+    fn from(node: Struct) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<Trait> for AnyHasName {
+    fn from(node: Trait) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<TypeAlias> for AnyHasName {
+    fn from(node: TypeAlias) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<Union> for AnyHasName {
+    fn from(node: Union) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<Rename> for AnyHasName {
+    fn from(node: Rename) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<SelfParam> for AnyHasName {
+    fn from(node: SelfParam) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<RecordField> for AnyHasName {
+    fn from(node: RecordField) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<Variant> for AnyHasName {
+    fn from(node: Variant) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<ConstParam> for AnyHasName {
+    fn from(node: ConstParam) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<TypeParam> for AnyHasName {
+    fn from(node: TypeParam) -> AnyHasName { AnyHasName::new(node) }
+}
+impl From<IdentPat> for AnyHasName {
+    fn from(node: IdentPat) -> AnyHasName { AnyHasName::new(node) }
+}
 impl AnyHasTypeBounds {
     #[inline]
     pub fn new<T: ast::HasTypeBounds>(node: T) -> AnyHasTypeBounds {
@@ -4109,6 +4469,24 @@ impl AstNode for AnyHasTypeBounds {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From<AssocTypeArg> for AnyHasTypeBounds {
+    fn from(node: AssocTypeArg) -> AnyHasTypeBounds { AnyHasTypeBounds::new(node) }
+}
+impl From<Trait> for AnyHasTypeBounds {
+    fn from(node: Trait) -> AnyHasTypeBounds { AnyHasTypeBounds::new(node) }
+}
+impl From<TypeAlias> for AnyHasTypeBounds {
+    fn from(node: TypeAlias) -> AnyHasTypeBounds { AnyHasTypeBounds::new(node) }
+}
+impl From<LifetimeParam> for AnyHasTypeBounds {
+    fn from(node: LifetimeParam) -> AnyHasTypeBounds { AnyHasTypeBounds::new(node) }
+}
+impl From<TypeParam> for AnyHasTypeBounds {
+    fn from(node: TypeParam) -> AnyHasTypeBounds { AnyHasTypeBounds::new(node) }
+}
+impl From<WherePred> for AnyHasTypeBounds {
+    fn from(node: WherePred) -> AnyHasTypeBounds { AnyHasTypeBounds::new(node) }
+}
 impl AnyHasVisibility {
     #[inline]
     pub fn new<T: ast::HasVisibility>(node: T) -> AnyHasVisibility {
@@ -4143,6 +4521,195 @@ impl AstNode for AnyHasVisibility {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From<Const> for AnyHasVisibility {
+    fn from(node: Const) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<Enum> for AnyHasVisibility {
+    fn from(node: Enum) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<ExternCrate> for AnyHasVisibility {
+    fn from(node: ExternCrate) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<Fn> for AnyHasVisibility {
+    fn from(node: Fn) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<Impl> for AnyHasVisibility {
+    fn from(node: Impl) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<MacroRules> for AnyHasVisibility {
+    fn from(node: MacroRules) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<MacroDef> for AnyHasVisibility {
+    fn from(node: MacroDef) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<Module> for AnyHasVisibility {
+    fn from(node: Module) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<Static> for AnyHasVisibility {
+    fn from(node: Static) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<Struct> for AnyHasVisibility {
+    fn from(node: Struct) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<Trait> for AnyHasVisibility {
+    fn from(node: Trait) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<TypeAlias> for AnyHasVisibility {
+    fn from(node: TypeAlias) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<Union> for AnyHasVisibility {
+    fn from(node: Union) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<Use> for AnyHasVisibility {
+    fn from(node: Use) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<RecordField> for AnyHasVisibility {
+    fn from(node: RecordField) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<TupleField> for AnyHasVisibility {
+    fn from(node: TupleField) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<Variant> for AnyHasVisibility {
+    fn from(node: Variant) -> AnyHasVisibility { AnyHasVisibility::new(node) }
+}
+impl From<Item> for AnyHasAttrs {
+    fn from(node: Item) -> AnyHasAttrs {
+        match node {
+            Item::Const(it) => AnyHasAttrs::new(it),
+            Item::Enum(it) => AnyHasAttrs::new(it),
+            Item::ExternBlock(it) => AnyHasAttrs::new(it),
+            Item::ExternCrate(it) => AnyHasAttrs::new(it),
+            Item::Fn(it) => AnyHasAttrs::new(it),
+            Item::Impl(it) => AnyHasAttrs::new(it),
+            Item::MacroCall(it) => AnyHasAttrs::new(it),
+            Item::MacroRules(it) => AnyHasAttrs::new(it),
+            Item::MacroDef(it) => AnyHasAttrs::new(it),
+            Item::Module(it) => AnyHasAttrs::new(it),
+            Item::Static(it) => AnyHasAttrs::new(it),
+            Item::Struct(it) => AnyHasAttrs::new(it),
+            Item::Trait(it) => AnyHasAttrs::new(it),
+            Item::TypeAlias(it) => AnyHasAttrs::new(it),
+            Item::Union(it) => AnyHasAttrs::new(it),
+            Item::Use(it) => AnyHasAttrs::new(it),
+        }
+    }
+}
+impl From<Adt> for AnyHasAttrs {
+    fn from(node: Adt) -> AnyHasAttrs {
+        match node {
+            Adt::Enum(it) => AnyHasAttrs::new(it),
+            Adt::Struct(it) => AnyHasAttrs::new(it),
+            Adt::Union(it) => AnyHasAttrs::new(it),
+        }
+    }
+}
+impl From<AssocItem> for AnyHasAttrs {
+    fn from(node: AssocItem) -> AnyHasAttrs {
+        match node {
+            AssocItem::Const(it) => AnyHasAttrs::new(it),
+            AssocItem::Fn(it) => AnyHasAttrs::new(it),
+            AssocItem::MacroCall(it) => AnyHasAttrs::new(it),
+            AssocItem::TypeAlias(it) => AnyHasAttrs::new(it),
+        }
+    }
+}
+impl From<ExternItem> for AnyHasAttrs {
+    fn from(node: ExternItem) -> AnyHasAttrs {
+        match node {
+            ExternItem::Fn(it) => AnyHasAttrs::new(it),
+            ExternItem::MacroCall(it) => AnyHasAttrs::new(it),
+            ExternItem::Static(it) => AnyHasAttrs::new(it),
+            ExternItem::TypeAlias(it) => AnyHasAttrs::new(it),
+        }
+    }
+}
+impl From<GenericParam> for AnyHasAttrs {
+    fn from(node: GenericParam) -> AnyHasAttrs {
+        match node {
+            GenericParam::ConstParam(it) => AnyHasAttrs::new(it),
+            GenericParam::LifetimeParam(it) => AnyHasAttrs::new(it),
+            GenericParam::TypeParam(it) => AnyHasAttrs::new(it),
+        }
+    }
+}
+impl From<Item> for AnyHasDocComments {
+    fn from(node: Item) -> AnyHasDocComments {
+        match node {
+            Item::Const(it) => AnyHasDocComments::new(it),
+            Item::Enum(it) => AnyHasDocComments::new(it),
+            Item::ExternBlock(it) => AnyHasDocComments::new(it),
+            Item::ExternCrate(it) => AnyHasDocComments::new(it),
+            Item::Fn(it) => AnyHasDocComments::new(it),
+            Item::Impl(it) => AnyHasDocComments::new(it),
+            Item::MacroCall(it) => AnyHasDocComments::new(it),
+            Item::MacroRules(it) => AnyHasDocComments::new(it),
+            Item::MacroDef(it) => AnyHasDocComments::new(it),
+            Item::Module(it) => AnyHasDocComments::new(it),
+            Item::Static(it) => AnyHasDocComments::new(it),
+            Item::Struct(it) => AnyHasDocComments::new(it),
+            Item::Trait(it) => AnyHasDocComments::new(it),
+            Item::TypeAlias(it) => AnyHasDocComments::new(it),
+            Item::Union(it) => AnyHasDocComments::new(it),
+            Item::Use(it) => AnyHasDocComments::new(it),
+        }
+    }
+}
+impl From<Adt> for AnyHasDocComments {
+    fn from(node: Adt) -> AnyHasDocComments {
+        match node {
+            Adt::Enum(it) => AnyHasDocComments::new(it),
+            Adt::Struct(it) => AnyHasDocComments::new(it),
+            Adt::Union(it) => AnyHasDocComments::new(it),
+        }
+    }
+}
+impl From<AssocItem> for AnyHasDocComments {
+    fn from(node: AssocItem) -> AnyHasDocComments {
+        match node {
+            AssocItem::Const(it) => AnyHasDocComments::new(it),
+            AssocItem::Fn(it) => AnyHasDocComments::new(it),
+            AssocItem::MacroCall(it) => AnyHasDocComments::new(it),
+            AssocItem::TypeAlias(it) => AnyHasDocComments::new(it),
+        }
+    }
+}
+impl From<ExternItem> for AnyHasDocComments {
+    fn from(node: ExternItem) -> AnyHasDocComments {
+        match node {
+            ExternItem::Fn(it) => AnyHasDocComments::new(it),
+            ExternItem::MacroCall(it) => AnyHasDocComments::new(it),
+            ExternItem::Static(it) => AnyHasDocComments::new(it),
+            ExternItem::TypeAlias(it) => AnyHasDocComments::new(it),
+        }
+    }
+}
+impl From<Adt> for AnyHasGenericParams {
+    fn from(node: Adt) -> AnyHasGenericParams {
+        match node {
+            Adt::Enum(it) => AnyHasGenericParams::new(it),
+            Adt::Struct(it) => AnyHasGenericParams::new(it),
+            Adt::Union(it) => AnyHasGenericParams::new(it),
+        }
+    }
+}
+impl From<Adt> for AnyHasName {
+    fn from(node: Adt) -> AnyHasName {
+        match node {
+            Adt::Enum(it) => AnyHasName::new(it),
+            Adt::Struct(it) => AnyHasName::new(it),
+            Adt::Union(it) => AnyHasName::new(it),
+        }
+    }
+}
+impl From<Adt> for AnyHasVisibility {
+    fn from(node: Adt) -> AnyHasVisibility {
+        match node {
+            Adt::Enum(it) => AnyHasVisibility::new(it),
+            Adt::Struct(it) => AnyHasVisibility::new(it),
+            Adt::Union(it) => AnyHasVisibility::new(it),
+        }
+    }
+}
 impl std::fmt::Display for GenericArg {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
diff --git a/crates/syntax/src/tests/sourcegen_ast.rs b/crates/syntax/src/tests/sourcegen_ast.rs
index 70b54843dba..56d7c98d58a 100644
--- a/crates/syntax/src/tests/sourcegen_ast.rs
+++ b/crates/syntax/src/tests/sourcegen_ast.rs
@@ -229,6 +229,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
                 .iter()
                 .map(|name| format_ident!("{}", to_upper_snake_case(&name.name.to_string())))
                 .collect();
+            let node_names: Vec<_> = nodes.iter().map(|n| format_ident!("{}", n.name)).collect();
 
             (
                 quote! {
@@ -259,11 +260,43 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
                             &self.syntax
                         }
                     }
+
+                    #(
+                        impl From<#node_names> for #name {
+                            fn from(node: #node_names) -> #name {
+                                #name::new(node)
+                            }
+                        }
+                    )*
                 },
             )
         })
         .unzip();
 
+    let any_enum_boilerplate_impls: Vec<_> = grammar
+        .enums
+        .iter()
+        .flat_map(|en| en.traits.iter().map(move |t| (t, en)))
+        .sorted_by_key(|(k, _)| *k)
+        .map(|(target_name, en)| {
+            let target_name = format_ident!("Any{}", target_name);
+            let enum_name = format_ident!("{}", en.name);
+            let variants: Vec<_> = en.variants.iter().map(|var| format_ident!("{}", var)).collect();
+
+            quote! {
+                impl From<#enum_name> for #target_name {
+                    fn from(node: #enum_name) -> #target_name {
+                        match node {
+                            #(
+                                #enum_name::#variants(it) => #target_name::new(it),
+                            )*
+                        }
+                    }
+                }
+            }
+        })
+        .collect();
+
     let enum_names = grammar.enums.iter().map(|it| &it.name);
     let node_names = grammar.nodes.iter().map(|it| &it.name);
 
@@ -305,6 +338,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
         #(#node_boilerplate_impls)*
         #(#enum_boilerplate_impls)*
         #(#any_node_boilerplate_impls)*
+        #(#any_enum_boilerplate_impls)*
         #(#display_impls)*
     };