aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/code_model.rs7
-rw-r--r--crates/hir/src/lib.rs8
-rw-r--r--crates/hir/src/semantics.rs16
-rw-r--r--crates/ssr/src/resolving.rs24
4 files changed, 39 insertions, 16 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index 8ffb9e99b..5dc3ae3b1 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -883,6 +883,13 @@ where
883} 883}
884 884
885impl AssocItem { 885impl AssocItem {
886 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
887 match self {
888 AssocItem::Function(it) => Some(it.name(db)),
889 AssocItem::Const(it) => it.name(db),
890 AssocItem::TypeAlias(it) => Some(it.name(db)),
891 }
892 }
886 pub fn module(self, db: &dyn HirDatabase) -> Module { 893 pub fn module(self, db: &dyn HirDatabase) -> Module {
887 match self { 894 match self {
888 AssocItem::Function(f) => f.module(db), 895 AssocItem::Function(f) => f.module(db),
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 24a0f6b4b..4ae2bd085 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -52,8 +52,12 @@ pub use hir_def::{
52 type_ref::{Mutability, TypeRef}, 52 type_ref::{Mutability, TypeRef},
53}; 53};
54pub use hir_expand::{ 54pub use hir_expand::{
55 hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, 55 name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, /* FIXME */ MacroDefId,
56 MacroDefId, /* FIXME */
57 MacroFile, Origin, 56 MacroFile, Origin,
58}; 57};
59pub use hir_ty::display::HirDisplay; 58pub use hir_ty::display::HirDisplay;
59
60// These are negative re-exports: pub using these names is forbidden, they
61// should remain private to hir internals.
62#[allow(unused)]
63use hir_expand::hygiene::Hygiene;
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 1467d825d..d8beac98a 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -502,18 +502,19 @@ impl<'db> SemanticsImpl<'db> {
502 fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> { 502 fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> {
503 let node = self.find_file(node.clone()); 503 let node = self.find_file(node.clone());
504 let resolver = self.analyze2(node.as_ref(), None).resolver; 504 let resolver = self.analyze2(node.as_ref(), None).resolver;
505 SemanticsScope { db: self.db, resolver } 505 SemanticsScope { db: self.db, file_id: node.file_id, resolver }
506 } 506 }
507 507
508 fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> { 508 fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> {
509 let node = self.find_file(node.clone()); 509 let node = self.find_file(node.clone());
510 let resolver = self.analyze2(node.as_ref(), Some(offset)).resolver; 510 let resolver = self.analyze2(node.as_ref(), Some(offset)).resolver;
511 SemanticsScope { db: self.db, resolver } 511 SemanticsScope { db: self.db, file_id: node.file_id, resolver }
512 } 512 }
513 513
514 fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> { 514 fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> {
515 let file_id = self.db.lookup_intern_trait(def.id).id.file_id;
515 let resolver = def.id.resolver(self.db.upcast()); 516 let resolver = def.id.resolver(self.db.upcast());
516 SemanticsScope { db: self.db, resolver } 517 SemanticsScope { db: self.db, file_id, resolver }
517 } 518 }
518 519
519 fn analyze(&self, node: &SyntaxNode) -> SourceAnalyzer { 520 fn analyze(&self, node: &SyntaxNode) -> SourceAnalyzer {
@@ -709,6 +710,7 @@ fn find_root(node: &SyntaxNode) -> SyntaxNode {
709#[derive(Debug)] 710#[derive(Debug)]
710pub struct SemanticsScope<'a> { 711pub struct SemanticsScope<'a> {
711 pub db: &'a dyn HirDatabase, 712 pub db: &'a dyn HirDatabase,
713 file_id: HirFileId,
712 resolver: Resolver, 714 resolver: Resolver,
713} 715}
714 716
@@ -752,6 +754,14 @@ impl<'a> SemanticsScope<'a> {
752 }) 754 })
753 } 755 }
754 756
757 /// Resolve a path as-if it was written at the given scope. This is
758 /// necessary a heuristic, as it doesn't take hygiene into account.
759 pub fn resolve_hypothetical(&self, path: &ast::Path) -> Option<PathResolution> {
760 let hygiene = Hygiene::new(self.db.upcast(), self.file_id);
761 let path = Path::from_src(path.clone(), &hygiene)?;
762 self.resolve_hir_path(&path)
763 }
764
755 pub fn resolve_hir_path(&self, path: &Path) -> Option<PathResolution> { 765 pub fn resolve_hir_path(&self, path: &Path) -> Option<PathResolution> {
756 resolve_hir_path(self.db, &self.resolver, path) 766 resolve_hir_path(self.db, &self.resolver, path)
757 } 767 }
diff --git a/crates/ssr/src/resolving.rs b/crates/ssr/src/resolving.rs
index 020fd7994..4441fb426 100644
--- a/crates/ssr/src/resolving.rs
+++ b/crates/ssr/src/resolving.rs
@@ -10,7 +10,6 @@ use test_utils::mark;
10 10
11pub(crate) struct ResolutionScope<'db> { 11pub(crate) struct ResolutionScope<'db> {
12 scope: hir::SemanticsScope<'db>, 12 scope: hir::SemanticsScope<'db>,
13 hygiene: hir::Hygiene,
14 node: SyntaxNode, 13 node: SyntaxNode,
15} 14}
16 15
@@ -201,11 +200,7 @@ impl<'db> ResolutionScope<'db> {
201 .unwrap_or_else(|| file.syntax().clone()); 200 .unwrap_or_else(|| file.syntax().clone());
202 let node = pick_node_for_resolution(node); 201 let node = pick_node_for_resolution(node);
203 let scope = sema.scope(&node); 202 let scope = sema.scope(&node);
204 ResolutionScope { 203 ResolutionScope { scope, node }
205 scope,
206 hygiene: hir::Hygiene::new(sema.db, resolve_context.file_id.into()),
207 node,
208 }
209 } 204 }
210 205
211 /// Returns the function in which SSR was invoked, if any. 206 /// Returns the function in which SSR was invoked, if any.
@@ -214,24 +209,31 @@ impl<'db> ResolutionScope<'db> {
214 } 209 }
215 210
216 fn resolve_path(&self, path: &ast::Path) -> Option<hir::PathResolution> { 211 fn resolve_path(&self, path: &ast::Path) -> Option<hir::PathResolution> {
217 let hir_path = hir::Path::from_src(path.clone(), &self.hygiene)?;
218 // First try resolving the whole path. This will work for things like 212 // First try resolving the whole path. This will work for things like
219 // `std::collections::HashMap`, but will fail for things like 213 // `std::collections::HashMap`, but will fail for things like
220 // `std::collections::HashMap::new`. 214 // `std::collections::HashMap::new`.
221 if let Some(resolution) = self.scope.resolve_hir_path(&hir_path) { 215 if let Some(resolution) = self.scope.resolve_hypothetical(&path) {
222 return Some(resolution); 216 return Some(resolution);
223 } 217 }
224 // Resolution failed, try resolving the qualifier (e.g. `std::collections::HashMap` and if 218 // Resolution failed, try resolving the qualifier (e.g. `std::collections::HashMap` and if
225 // that succeeds, then iterate through the candidates on the resolved type with the provided 219 // that succeeds, then iterate through the candidates on the resolved type with the provided
226 // name. 220 // name.
227 let resolved_qualifier = self.scope.resolve_hir_path_qualifier(&hir_path.qualifier()?)?; 221 let resolved_qualifier = self.scope.resolve_hypothetical(&path.qualifier()?)?;
228 if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier { 222 if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier {
223 let name = path.segment()?.name_ref()?;
229 adt.ty(self.scope.db).iterate_path_candidates( 224 adt.ty(self.scope.db).iterate_path_candidates(
230 self.scope.db, 225 self.scope.db,
231 self.scope.module()?.krate(), 226 self.scope.module()?.krate(),
232 &self.scope.traits_in_scope(), 227 &self.scope.traits_in_scope(),
233 Some(hir_path.segments().last()?.name), 228 None,
234 |_ty, assoc_item| Some(hir::PathResolution::AssocItem(assoc_item)), 229 |_ty, assoc_item| {
230 let item_name = assoc_item.name(self.scope.db)?;
231 if item_name.to_string().as_str() == name.text().as_str() {
232 Some(hir::PathResolution::AssocItem(assoc_item))
233 } else {
234 None
235 }
236 },
235 ) 237 )
236 } else { 238 } else {
237 None 239 None