about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2021-10-19 13:40:27 +0200
committerLukas Wirth <lukastw97@gmail.com>2021-10-19 13:42:36 +0200
commitaa9d0934887fced0437c1e09ea5255185cac5631 (patch)
treefcf982997ef6cfe365d5ef34c0a7b54ad55a7954
parent401daa5f77fd9cfb79d16fe3a54bc576d60b4c82 (diff)
downloadrust-aa9d0934887fced0437c1e09ea5255185cac5631.tar.gz
rust-aa9d0934887fced0437c1e09ea5255185cac5631.zip
Resolve derive attributes even when shadowed
-rw-r--r--crates/hir/src/semantics.rs12
-rw-r--r--crates/hir/src/source_analyzer.rs9
-rw-r--r--crates/ide_db/src/helpers.rs9
3 files changed, 23 insertions, 7 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index b6e5ee75313..ca23d85cb24 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -24,7 +24,7 @@ use syntax::{
 use crate::{
     db::HirDatabase,
     semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
-    source_analyzer::{resolve_hir_path, SourceAnalyzer},
+    source_analyzer::{resolve_hir_path, resolve_hir_path_as_macro, SourceAnalyzer},
     Access, AssocItem, Callable, ConstParam, Crate, Field, Function, HasSource, HirFileId, Impl,
     InFile, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait,
     Type, TypeAlias, TypeParam, VariantDef,
@@ -1134,4 +1134,14 @@ impl<'a> SemanticsScope<'a> {
         let path = Path::from_src(path.clone(), &ctx)?;
         resolve_hir_path(self.db, &self.resolver, &path)
     }
+
+    /// Resolve a path as-if it was written at the given scope. This is
+    /// necessary a heuristic, as it doesn't take hygiene into account.
+    // FIXME: This special casing solely exists for attributes for now
+    // ideally we should have a path resolution infra that properly knows about overlapping namespaces
+    pub fn speculative_resolve_as_mac(&self, path: &ast::Path) -> Option<MacroDef> {
+        let ctx = body::LowerCtx::new(self.db.upcast(), self.file_id);
+        let path = Path::from_src(path.clone(), &ctx)?;
+        resolve_hir_path_as_macro(self.db, &self.resolver, &path)
+    }
 }
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 960b290e266..08d0a02d796 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -502,6 +502,15 @@ pub(crate) fn resolve_hir_path(
     resolve_hir_path_(db, resolver, path, false)
 }
 
+#[inline]
+pub(crate) fn resolve_hir_path_as_macro(
+    db: &dyn HirDatabase,
+    resolver: &Resolver,
+    path: &Path,
+) -> Option<MacroDef> {
+    resolver.resolve_path_as_macro(db.upcast(), path.mod_path()).map(Into::into)
+}
+
 fn resolve_hir_path_(
     db: &dyn HirDatabase,
     resolver: &Resolver,
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs
index a8087d47fe2..173e55b33f6 100644
--- a/crates/ide_db/src/helpers.rs
+++ b/crates/ide_db/src/helpers.rs
@@ -53,12 +53,9 @@ pub fn try_resolve_derive_input_at(
         .take_while(|tok| tok.kind() != T!['('] && tok.kind() != T![,])
         .collect();
     let path = ast::Path::parse(&tokens.into_iter().rev().join("")).ok()?;
-    match sema.scope(tt.syntax()).speculative_resolve(&path) {
-        Some(hir::PathResolution::Macro(makro)) if makro.kind() == hir::MacroKind::Derive => {
-            Some(makro)
-        }
-        _ => None,
-    }
+    sema.scope(tt.syntax())
+        .speculative_resolve_as_mac(&path)
+        .filter(|mac| mac.kind() == hir::MacroKind::Derive)
 }
 
 /// Picks the token with the highest rank returned by the passed in function.