From 6b0870d12efd868202cfca45da651d21f2441031 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sat, 11 Apr 2020 17:00:31 +0200
Subject: Simplify

---
 crates/ra_hir_def/src/body.rs       |  5 +++++
 crates/ra_hir_def/src/body/lower.rs | 11 +++--------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index e09996c6f..ff0758da0 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -14,6 +14,7 @@ use ra_syntax::{ast, AstNode, AstPtr};
 use rustc_hash::FxHashMap;
 
 use crate::{
+    attr::Attrs,
     db::DefDatabase,
     expr::{Expr, ExprId, Pat, PatId},
     item_scope::BuiltinShadowMode,
@@ -102,6 +103,10 @@ impl Expander {
         InFile { file_id: self.current_file_id, value }
     }
 
+    pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
+        Attrs::new(owner, &self.hygiene)
+    }
+
     fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
         Path::from_src(path, &self.hygiene)
     }
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 9d6ee095e..06df88a34 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -2,9 +2,7 @@
 //! representation.
 
 use either::Either;
-
 use hir_expand::{
-    hygiene::Hygiene,
     name::{name, AsName, Name},
     MacroDefId, MacroDefKind,
 };
@@ -18,10 +16,8 @@ use ra_syntax::{
 };
 use test_utils::tested_by;
 
-use super::{ExprSource, PatSource};
 use crate::{
     adt::StructKind,
-    attr::Attrs,
     body::{Body, BodySourceMap, Expander, PatPtr, SyntheticSyntax},
     builtin_type::{BuiltinFloat, BuiltinInt},
     db::DefDatabase,
@@ -37,6 +33,8 @@ use crate::{
     ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
 };
 
+use super::{ExprSource, PatSource};
+
 pub(super) fn lower(
     db: &dyn DefDatabase,
     def: DefWithBodyId,
@@ -309,10 +307,7 @@ impl ExprCollector<'_> {
                         .inspect(|field| field_ptrs.push(AstPtr::new(field)))
                         .filter_map(|field| {
                             let module_id = ContainerId::DefWithBodyId(self.def).module(self.db);
-                            let attrs = Attrs::new(
-                                &field,
-                                &Hygiene::new(self.db.upcast(), self.expander.current_file_id),
-                            );
+                            let attrs = self.expander.parse_attrs(&field);
 
                             if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) {
                                 return None;
-- 
cgit v1.2.3


From e9519e103573e22ea0b461c81edd8cfc001e6a50 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sat, 11 Apr 2020 17:09:50 +0200
Subject: Pull Expander up

---
 crates/ra_hir_def/src/body.rs       | 17 ++++++++++++++++-
 crates/ra_hir_def/src/body/lower.rs |  8 +++-----
 crates/ra_hir_def/src/data.rs       | 10 +++++-----
 3 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index ff0758da0..48b797dd6 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -24,9 +24,11 @@ use crate::{
     src::HasSource,
     AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId,
 };
+use ra_cfg::CfgOptions;
 
 pub(crate) struct Expander {
     crate_def_map: Arc<CrateDefMap>,
+    cfg_options: CfgOptions,
     current_file_id: HirFileId,
     hygiene: Hygiene,
     ast_id_map: Arc<AstIdMap>,
@@ -43,7 +45,16 @@ impl Expander {
         let crate_def_map = db.crate_def_map(module.krate);
         let hygiene = Hygiene::new(db.upcast(), current_file_id);
         let ast_id_map = db.ast_id_map(current_file_id);
-        Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module, recursive_limit: 0 }
+        let cfg_options = db.crate_graph()[module.krate].cfg_options.clone();
+        Expander {
+            crate_def_map,
+            cfg_options,
+            current_file_id,
+            hygiene,
+            ast_id_map,
+            module,
+            recursive_limit: 0,
+        }
     }
 
     pub(crate) fn enter_expand<T: ast::AstNode>(
@@ -107,6 +118,10 @@ impl Expander {
         Attrs::new(owner, &self.hygiene)
     }
 
+    pub(crate) fn check_cfg(&self, attrs: &Attrs) -> bool {
+        attrs.is_cfg_enabled(&self.cfg_options)
+    }
+
     fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
         Path::from_src(path, &self.hygiene)
     }
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 06df88a34..6f56d3d7a 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -29,8 +29,8 @@ use crate::{
     path::GenericArgs,
     path::Path,
     type_ref::{Mutability, TypeRef},
-    AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, HasModule, Intern,
-    ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
+    AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
+    StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
 };
 
 use super::{ExprSource, PatSource};
@@ -298,7 +298,6 @@ impl ExprCollector<'_> {
                 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
             }
             ast::Expr::RecordLit(e) => {
-                let crate_graph = self.db.crate_graph();
                 let path = e.path().and_then(|path| self.expander.parse_path(path));
                 let mut field_ptrs = Vec::new();
                 let record_lit = if let Some(nfl) = e.record_field_list() {
@@ -306,10 +305,9 @@ impl ExprCollector<'_> {
                         .fields()
                         .inspect(|field| field_ptrs.push(AstPtr::new(field)))
                         .filter_map(|field| {
-                            let module_id = ContainerId::DefWithBodyId(self.def).module(self.db);
                             let attrs = self.expander.parse_attrs(&field);
 
-                            if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) {
+                            if !self.expander.check_cfg(&attrs) {
                                 return None;
                             }
 
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index b8fbf0ed4..dd0e679e8 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -20,7 +20,7 @@ use crate::{
     type_ref::{Mutability, TypeBound, TypeRef},
     visibility::RawVisibility,
     AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule,
-    ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
+    ImplId, Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -218,10 +218,11 @@ impl ImplData {
         let mut items = Vec::new();
 
         if let Some(item_list) = src.value.item_list() {
+            let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
             items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id));
             items.extend(collect_impl_items_in_macros(
                 db,
-                module_id,
+                &mut expander,
                 &src.with_value(item_list),
                 id,
             ));
@@ -268,18 +269,17 @@ impl ConstData {
 
 fn collect_impl_items_in_macros(
     db: &dyn DefDatabase,
-    module_id: ModuleId,
+    expander: &mut Expander,
     impl_def: &InFile<ast::ItemList>,
     id: ImplId,
 ) -> Vec<AssocItemId> {
-    let mut expander = Expander::new(db, impl_def.file_id, module_id);
     let mut res = Vec::new();
 
     // We set a limit to protect against infinite recursion
     let limit = 100;
 
     for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) {
-        res.extend(collect_impl_items_in_macro(db, &mut expander, m, id, limit))
+        res.extend(collect_impl_items_in_macro(db, expander, m, id, limit))
     }
 
     res
-- 
cgit v1.2.3


From ac21100f32be00c2b80982fa6faf31c0bfaf2c5f Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sat, 11 Apr 2020 17:12:17 +0200
Subject: Use Expander for cfg handling in impls

---
 crates/ra_hir_def/src/data.rs | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index dd0e679e8..446af9d9b 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -219,7 +219,13 @@ impl ImplData {
 
         if let Some(item_list) = src.value.item_list() {
             let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
-            items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id));
+            items.extend(collect_impl_items(
+                db,
+                &mut expander,
+                item_list.impl_items(),
+                src.file_id,
+                id,
+            ));
             items.extend(collect_impl_items_in_macros(
                 db,
                 &mut expander,
@@ -300,6 +306,7 @@ fn collect_impl_items_in_macro(
         let items: InFile<ast::MacroItems> = expander.to_source(items);
         let mut res = collect_impl_items(
             db,
+            expander,
             items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())),
             items.file_id,
             id,
@@ -319,32 +326,26 @@ fn collect_impl_items_in_macro(
 
 fn collect_impl_items(
     db: &dyn DefDatabase,
+    expander: &mut Expander,
     impl_items: impl Iterator<Item = ImplItem>,
     file_id: crate::HirFileId,
     id: ImplId,
 ) -> Vec<AssocItemId> {
     let items = db.ast_id_map(file_id);
-    let crate_graph = db.crate_graph();
-    let module_id = id.lookup(db).container.module(db);
 
     impl_items
         .filter_map(|item_node| match item_node {
             ast::ImplItem::FnDef(it) => {
+                let attrs = expander.parse_attrs(&it);
+                if !expander.check_cfg(&attrs) {
+                    return None;
+                }
                 let def = FunctionLoc {
                     container: AssocContainerId::ImplId(id),
                     ast_id: AstId::new(file_id, items.ast_id(&it)),
                 }
                 .intern(db);
-
-                if !db
-                    .function_data(def)
-                    .attrs
-                    .is_cfg_enabled(&crate_graph[module_id.krate].cfg_options)
-                {
-                    None
-                } else {
-                    Some(def.into())
-                }
+                Some(def.into())
             }
             ast::ImplItem::ConstDef(it) => {
                 let def = ConstLoc {
-- 
cgit v1.2.3


From b8eb1597c9a950a31b06d5625f2793d5237d756c Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sat, 11 Apr 2020 17:17:12 +0200
Subject: Use Expander for cfg handling in structs

---
 crates/ra_hir_def/src/adt.rs | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index be4b0accb..2619d106d 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -4,7 +4,6 @@ use std::sync::Arc;
 
 use either::Either;
 use hir_expand::{
-    hygiene::Hygiene,
     name::{AsName, Name},
     InFile,
 };
@@ -13,7 +12,7 @@ use ra_prof::profile;
 use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner};
 
 use crate::{
-    attr::Attrs, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace,
+    body::Expander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace,
     type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId,
     LocalStructFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
 };
@@ -125,8 +124,9 @@ fn lower_enum(
 
 impl VariantData {
     fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>, module_id: ModuleId) -> Self {
+        let mut expander = Expander::new(db, flavor.file_id, module_id);
         let mut trace = Trace::new_for_arena();
-        match lower_struct(db, &mut trace, &flavor, module_id) {
+        match lower_struct(db, &mut expander, &mut trace, &flavor) {
             StructKind::Tuple => VariantData::Tuple(trace.into_arena()),
             StructKind::Record => VariantData::Record(trace.into_arena()),
             StructKind::Unit => VariantData::Unit,
@@ -178,8 +178,9 @@ impl HasChildSource for VariantId {
                 it.lookup(db).container.module(db),
             ),
         };
+        let mut expander = Expander::new(db, src.file_id, module_id);
         let mut trace = Trace::new_for_map();
-        lower_struct(db, &mut trace, &src, module_id);
+        lower_struct(db, &mut expander, &mut trace, &src);
         src.with_value(trace.into_map())
     }
 }
@@ -193,16 +194,15 @@ pub enum StructKind {
 
 fn lower_struct(
     db: &dyn DefDatabase,
+    expander: &mut Expander,
     trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>,
     ast: &InFile<ast::StructKind>,
-    module_id: ModuleId,
 ) -> StructKind {
-    let crate_graph = db.crate_graph();
     match &ast.value {
         ast::StructKind::Tuple(fl) => {
             for (i, fd) in fl.fields().enumerate() {
-                let attrs = Attrs::new(&fd, &Hygiene::new(db.upcast(), ast.file_id));
-                if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) {
+                let attrs = expander.parse_attrs(&fd);
+                if !expander.check_cfg(&attrs) {
                     continue;
                 }
 
@@ -219,8 +219,8 @@ fn lower_struct(
         }
         ast::StructKind::Record(fl) => {
             for fd in fl.fields() {
-                let attrs = Attrs::new(&fd, &Hygiene::new(db.upcast(), ast.file_id));
-                if !attrs.is_cfg_enabled(&crate_graph[module_id.krate].cfg_options) {
+                let attrs = expander.parse_attrs(&fd);
+                if !expander.check_cfg(&attrs) {
                     continue;
                 }
 
-- 
cgit v1.2.3


From 55356332bfd22db159fef044b9e611b5b82b417c Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sat, 11 Apr 2020 17:18:42 +0200
Subject: Remove code duplication

---
 crates/ra_hir_def/src/attr.rs              | 1 +
 crates/ra_hir_def/src/nameres/collector.rs | 6 +-----
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 7b0c506b1..2f2e3e5ba 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -93,6 +93,7 @@ impl Attrs {
     }
 
     pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool {
+        // FIXME: handle cfg_attr :-)
         self.by_key("cfg").tt_values().all(|tt| cfg_options.is_cfg_enabled(tt) != Some(false))
     }
 }
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 8fe3f8617..1c33a6520 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -977,11 +977,7 @@ impl ModCollector<'_, '_> {
     }
 
     fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
-        // FIXME: handle cfg_attr :-)
-        attrs
-            .by_key("cfg")
-            .tt_values()
-            .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false))
+        attrs.is_cfg_enabled(self.def_collector.cfg_options)
     }
 }
 
-- 
cgit v1.2.3


From deb40d52aaa1989402fc01d65da389dc92fb66fa Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sat, 11 Apr 2020 17:20:26 +0200
Subject: Align naming

---
 crates/ra_hir_def/src/adt.rs        | 4 ++--
 crates/ra_hir_def/src/body.rs       | 2 +-
 crates/ra_hir_def/src/body/lower.rs | 3 +--
 crates/ra_hir_def/src/data.rs       | 2 +-
 4 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 2619d106d..c7c3c0bc7 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -202,7 +202,7 @@ fn lower_struct(
         ast::StructKind::Tuple(fl) => {
             for (i, fd) in fl.fields().enumerate() {
                 let attrs = expander.parse_attrs(&fd);
-                if !expander.check_cfg(&attrs) {
+                if !expander.is_cfg_enabled(&attrs) {
                     continue;
                 }
 
@@ -220,7 +220,7 @@ fn lower_struct(
         ast::StructKind::Record(fl) => {
             for fd in fl.fields() {
                 let attrs = expander.parse_attrs(&fd);
-                if !expander.check_cfg(&attrs) {
+                if !expander.is_cfg_enabled(&attrs) {
                     continue;
                 }
 
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 48b797dd6..7fe5403c0 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -118,7 +118,7 @@ impl Expander {
         Attrs::new(owner, &self.hygiene)
     }
 
-    pub(crate) fn check_cfg(&self, attrs: &Attrs) -> bool {
+    pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
         attrs.is_cfg_enabled(&self.cfg_options)
     }
 
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 6f56d3d7a..c1d7eb826 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -306,8 +306,7 @@ impl ExprCollector<'_> {
                         .inspect(|field| field_ptrs.push(AstPtr::new(field)))
                         .filter_map(|field| {
                             let attrs = self.expander.parse_attrs(&field);
-
-                            if !self.expander.check_cfg(&attrs) {
+                            if !self.expander.is_cfg_enabled(&attrs) {
                                 return None;
                             }
 
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 446af9d9b..56a20c5bd 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -337,7 +337,7 @@ fn collect_impl_items(
         .filter_map(|item_node| match item_node {
             ast::ImplItem::FnDef(it) => {
                 let attrs = expander.parse_attrs(&it);
-                if !expander.check_cfg(&attrs) {
+                if !expander.is_cfg_enabled(&attrs) {
                     return None;
                 }
                 let def = FunctionLoc {
-- 
cgit v1.2.3


From 38c67e5c0d4297f45ab2b78a00b59f737796d160 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sat, 11 Apr 2020 17:52:26 +0200
Subject: Avoid cyclic queries in name resolution when processing enums

---
 crates/ra_hir_def/src/adt.rs               |  8 ++---
 crates/ra_hir_def/src/body.rs              | 47 +++++++++++++++++++++++-------
 crates/ra_hir_def/src/nameres/collector.rs |  8 +++++
 3 files changed, 48 insertions(+), 15 deletions(-)

diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index c7c3c0bc7..7c0d93691 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -12,7 +12,7 @@ use ra_prof::profile;
 use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner};
 
 use crate::{
-    body::Expander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace,
+    body::CfgExpander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace,
     type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId,
     LocalStructFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
 };
@@ -124,7 +124,7 @@ fn lower_enum(
 
 impl VariantData {
     fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>, module_id: ModuleId) -> Self {
-        let mut expander = Expander::new(db, flavor.file_id, module_id);
+        let mut expander = CfgExpander::new(db, flavor.file_id, module_id.krate);
         let mut trace = Trace::new_for_arena();
         match lower_struct(db, &mut expander, &mut trace, &flavor) {
             StructKind::Tuple => VariantData::Tuple(trace.into_arena()),
@@ -178,7 +178,7 @@ impl HasChildSource for VariantId {
                 it.lookup(db).container.module(db),
             ),
         };
-        let mut expander = Expander::new(db, src.file_id, module_id);
+        let mut expander = CfgExpander::new(db, src.file_id, module_id.krate);
         let mut trace = Trace::new_for_map();
         lower_struct(db, &mut expander, &mut trace, &src);
         src.with_value(trace.into_map())
@@ -194,7 +194,7 @@ pub enum StructKind {
 
 fn lower_struct(
     db: &dyn DefDatabase,
-    expander: &mut Expander,
+    expander: &mut CfgExpander,
     trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>,
     ast: &InFile<ast::StructKind>,
 ) -> StructKind {
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 7fe5403c0..7fac6ce66 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -25,32 +25,57 @@ use crate::{
     AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId,
 };
 use ra_cfg::CfgOptions;
+use ra_db::CrateId;
+
+/// A subser of Exander that only deals with cfg attributes. We only need it to
+/// avoid cyclic queries in crate def map during enum processing.
+pub(crate) struct CfgExpander {
+    cfg_options: CfgOptions,
+    hygiene: Hygiene,
+}
 
 pub(crate) struct Expander {
+    cfg_expander: CfgExpander,
     crate_def_map: Arc<CrateDefMap>,
-    cfg_options: CfgOptions,
     current_file_id: HirFileId,
-    hygiene: Hygiene,
     ast_id_map: Arc<AstIdMap>,
     module: ModuleId,
     recursive_limit: usize,
 }
 
+impl CfgExpander {
+    pub(crate) fn new(
+        db: &dyn DefDatabase,
+        current_file_id: HirFileId,
+        krate: CrateId,
+    ) -> CfgExpander {
+        let hygiene = Hygiene::new(db.upcast(), current_file_id);
+        let cfg_options = db.crate_graph()[krate].cfg_options.clone();
+        CfgExpander { cfg_options, hygiene }
+    }
+
+    pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
+        Attrs::new(owner, &self.hygiene)
+    }
+
+    pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
+        attrs.is_cfg_enabled(&self.cfg_options)
+    }
+}
+
 impl Expander {
     pub(crate) fn new(
         db: &dyn DefDatabase,
         current_file_id: HirFileId,
         module: ModuleId,
     ) -> Expander {
+        let cfg_expander = CfgExpander::new(db, current_file_id, module.krate);
         let crate_def_map = db.crate_def_map(module.krate);
-        let hygiene = Hygiene::new(db.upcast(), current_file_id);
         let ast_id_map = db.ast_id_map(current_file_id);
-        let cfg_options = db.crate_graph()[module.krate].cfg_options.clone();
         Expander {
+            cfg_expander,
             crate_def_map,
-            cfg_options,
             current_file_id,
-            hygiene,
             ast_id_map,
             module,
             recursive_limit: 0,
@@ -87,7 +112,7 @@ impl Expander {
                         ast_id_map: mem::take(&mut self.ast_id_map),
                         bomb: DropBomb::new("expansion mark dropped"),
                     };
-                    self.hygiene = Hygiene::new(db.upcast(), file_id);
+                    self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id);
                     self.current_file_id = file_id;
                     self.ast_id_map = db.ast_id_map(file_id);
                     self.recursive_limit += 1;
@@ -103,7 +128,7 @@ impl Expander {
     }
 
     pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) {
-        self.hygiene = Hygiene::new(db.upcast(), mark.file_id);
+        self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id);
         self.current_file_id = mark.file_id;
         self.ast_id_map = mem::take(&mut mark.ast_id_map);
         self.recursive_limit -= 1;
@@ -115,15 +140,15 @@ impl Expander {
     }
 
     pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
-        Attrs::new(owner, &self.hygiene)
+        self.cfg_expander.parse_attrs(owner)
     }
 
     pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
-        attrs.is_cfg_enabled(&self.cfg_options)
+        self.cfg_expander.is_cfg_enabled(attrs)
     }
 
     fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
-        Path::from_src(path, &self.hygiene)
+        Path::from_src(path, &self.cfg_expander.hygiene)
     }
 
     fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> {
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 1c33a6520..98c74fe25 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -462,6 +462,14 @@ impl DefCollector<'_> {
                 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
                     tested_by!(glob_enum);
                     // glob import from enum => just import all the variants
+
+                    // XXX: urgh, so this works by accident! Here, we look at
+                    // the enum data, and, in theory, this might require us to
+                    // look back at the crate_def_map, creating a cycle. For
+                    // example, `enum E { crate::some_macro!(); }`. Luckely, the
+                    // only kind of macro that is allowed inside enum is a
+                    // `cfg_macro`, and we don't need to run name resolution for
+                    // it, but this is sheer luck!
                     let enum_data = self.db.enum_data(e);
                     let resolutions = enum_data
                         .variants
-- 
cgit v1.2.3


From f980b0752994a1b823499f6edb10fd9c4c285c42 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Sat, 11 Apr 2020 17:54:46 +0200
Subject: Make incremental nameres test harder

---
 crates/ra_hir_def/src/nameres/tests/incremental.rs | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs
index 496fc6b08..87165ac33 100644
--- a/crates/ra_hir_def/src/nameres/tests/incremental.rs
+++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs
@@ -32,6 +32,9 @@ fn typing_inside_a_function_should_not_invalidate_def_map() {
 
         use crate::foo::bar::Baz;
 
+        enum E { A, B }
+        use E::*;
+
         fn foo() -> i32 {
             1 + 1
         }
@@ -46,6 +49,9 @@ fn typing_inside_a_function_should_not_invalidate_def_map() {
 
         use crate::foo::bar::Baz;
 
+        enum E { A, B }
+        use E::*;
+
         fn foo() -> i32 { 92 }
         ",
     );
-- 
cgit v1.2.3