diff options
-rw-r--r-- | crates/hir/src/code_model.rs | 7 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/hir/src/semantics.rs | 16 | ||||
-rw-r--r-- | crates/ssr/src/resolving.rs | 24 |
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 | ||
885 | impl AssocItem { | 885 | impl 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 | }; |
54 | pub use hir_expand::{ | 54 | pub 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 | }; |
59 | pub use hir_ty::display::HirDisplay; | 58 | pub 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)] | ||
63 | use 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)] |
710 | pub struct SemanticsScope<'a> { | 711 | pub 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 | ||
11 | pub(crate) struct ResolutionScope<'db> { | 11 | pub(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 |