Repository: rust-analyzer/rust-analyzer
Pull request #10964 (2021-12-08 14:45:58)

minor: Move synstructure hack out of ItemTree lowering
Don't set the name to `None` for the rest of the IDE if it's generated by synstructure.

bors r+


Patch:
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index ad1c1f2ce5..b9f8c2f297 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -255,7 +255,7 @@ impl ImplData {
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct ConstData {
-    /// const _: () = ();
+    /// `None` for `const _: () = ();`
     pub name: Option<Name>,
     pub type_ref: Interned<TypeRef>,
     pub visibility: RawVisibility,
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 405cc2d00f..68d77084a3 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -648,7 +648,7 @@ pub struct Enum {
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct Const {
-    /// const _: () = ();
+    /// `None` for `const _: () = ();`
     pub name: Option<Name>,
     pub visibility: RawVisibilityId,
     pub type_ref: Interned<TypeRef>,
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index e9af991785..4396801116 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -375,12 +375,7 @@ impl<'a> Ctx<'a> {
     }
 
     fn lower_const(&mut self, konst: &ast::Const) -> FileItemTreeId<Const> {
-        let mut name = konst.name().map(|it| it.as_name());
-        if name.as_ref().map_or(false, |n| n.to_smol_str().starts_with("_DERIVE_")) {
-            // FIXME: this is a hack to treat consts generated by synstructure as unnamed
-            // remove this some time in the future
-            name = None;
-        }
+        let name = konst.name().map(|it| it.as_name());
         let type_ref = self.lower_type_ref_opt(konst.ty());
         let visibility = self.lower_visibility(konst);
         let ast_id = self.source_ast_id_map.ast_id(konst);
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 6b3f48b194..1e53d392e8 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -8,8 +8,9 @@ use arrayvec::ArrayVec;
 use base_db::{CrateId, Edition};
 use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
 use hir_def::{
-    lang_item::LangItemTarget, nameres::DefMap, AssocItemId, BlockId, FunctionId, GenericDefId,
-    HasModule, ImplId, ItemContainerId, Lookup, ModuleId, TraitId,
+    item_scope::ItemScope, lang_item::LangItemTarget, nameres::DefMap, AssocItemId, BlockId,
+    ConstId, FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId,
+    ModuleId, TraitId,
 };
 use hir_expand::name::Name;
 use rustc_hash::{FxHashMap, FxHashSet};
@@ -177,7 +178,7 @@ impl TraitImpls {
 
             // To better support custom derives, collect impls in all unnamed const items.
             // const _: () = { ... };
-            for konst in module_data.scope.unnamed_consts() {
+            for konst in collect_unnamed_consts(db, &module_data.scope) {
                 let body = db.body(konst.into());
                 for (_, block_def_map) in body.blocks(db.upcast()) {
                     self.collect_def_map(db, &block_def_map);
@@ -297,7 +298,7 @@ impl InherentImpls {
 
             // To better support custom derives, collect impls in all unnamed const items.
             // const _: () = { ... };
-            for konst in module_data.scope.unnamed_consts() {
+            for konst in collect_unnamed_consts(db, &module_data.scope) {
                 let body = db.body(konst.into());
                 for (_, block_def_map) in body.blocks(db.upcast()) {
                     self.collect_def_map(db, &block_def_map);
@@ -318,6 +319,34 @@ impl InherentImpls {
     }
 }
 
+fn collect_unnamed_consts<'a>(
+    db: &'a dyn HirDatabase,
+    scope: &'a ItemScope,
+) -> impl Iterator<Item = ConstId> + 'a {
+    let unnamed_consts = scope.unnamed_consts();
+
+    // FIXME: Also treat consts named `_DERIVE_*` as unnamed, since synstructure generates those.
+    // Should be removed once synstructure stops doing that.
+    let synstructure_hack_consts = scope.values().filter_map(|(item, _)| match item {
+        ModuleDefId::ConstId(id) => {
+            let loc = id.lookup(db.upcast());
+            let item_tree = loc.id.item_tree(db.upcast());
+            if item_tree[loc.id.value]
+                .name
+                .as_ref()
+                .map_or(false, |n| n.to_smol_str().starts_with("_DERIVE_"))
+            {
+                Some(id)
+            } else {
+                None
+            }
+        }
+        _ => None,
+    });
+
+    unnamed_consts.chain(synstructure_hack_consts)
+}
+
 pub fn def_crates(
     db: &dyn HirDatabase,
     ty: &Ty,


Test patch:
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs
index 9b1f682b61..731605ced1 100644
--- a/crates/hir_ty/src/tests/method_resolution.rs
+++ b/crates/hir_ty/src/tests/method_resolution.rs
@@ -1248,6 +1248,28 @@ fn f() {
     );
 }
 
+#[test]
+fn trait_impl_in_synstructure_const() {
+    check_types(
+        r#"
+struct S;
+
+trait Tr {
+    fn method(&self) -> u16;
+}
+
+const _DERIVE_Tr_: () = {
+    impl Tr for S {}
+};
+
+fn f() {
+    S.method();
+  //^^^^^^^^^^ u16
+}
+    "#,
+    );
+}
+
 #[test]
 fn inherent_impl_in_unnamed_const() {
     check_types(