From 9664c57e60ec5662b3e8b063324d9ab7879d5570 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 13 Aug 2020 23:52:14 +0200 Subject: [PATCH] Make hygiene private to hir --- crates/hir/src/code_model.rs | 7 +++++++ crates/hir/src/lib.rs | 8 ++++++-- crates/hir/src/semantics.rs | 16 +++++++++++++--- 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 8ffb9e99b0..5dc3ae3b19 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs @@ -883,6 +883,13 @@ where } impl AssocItem { + pub fn name(self, db: &dyn HirDatabase) -> Option { + match self { + AssocItem::Function(it) => Some(it.name(db)), + AssocItem::Const(it) => it.name(db), + AssocItem::TypeAlias(it) => Some(it.name(db)), + } + } pub fn module(self, db: &dyn HirDatabase) -> Module { match self { AssocItem::Function(f) => f.module(db), diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 24a0f6b4b1..4ae2bd0855 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -52,8 +52,12 @@ pub use hir_def::{ type_ref::{Mutability, TypeRef}, }; pub use hir_expand::{ - hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, - MacroDefId, /* FIXME */ + name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, /* FIXME */ MacroDefId, MacroFile, Origin, }; pub use hir_ty::display::HirDisplay; + +// These are negative re-exports: pub using these names is forbidden, they +// should remain private to hir internals. +#[allow(unused)] +use hir_expand::hygiene::Hygiene; diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 1467d825d9..d8beac98a6 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -502,18 +502,19 @@ impl<'db> SemanticsImpl<'db> { fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> { let node = self.find_file(node.clone()); let resolver = self.analyze2(node.as_ref(), None).resolver; - SemanticsScope { db: self.db, resolver } + SemanticsScope { db: self.db, file_id: node.file_id, resolver } } fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> { let node = self.find_file(node.clone()); let resolver = self.analyze2(node.as_ref(), Some(offset)).resolver; - SemanticsScope { db: self.db, resolver } + SemanticsScope { db: self.db, file_id: node.file_id, resolver } } fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> { + let file_id = self.db.lookup_intern_trait(def.id).id.file_id; let resolver = def.id.resolver(self.db.upcast()); - SemanticsScope { db: self.db, resolver } + SemanticsScope { db: self.db, file_id, resolver } } fn analyze(&self, node: &SyntaxNode) -> SourceAnalyzer { @@ -709,6 +710,7 @@ fn find_root(node: &SyntaxNode) -> SyntaxNode { #[derive(Debug)] pub struct SemanticsScope<'a> { pub db: &'a dyn HirDatabase, + file_id: HirFileId, resolver: Resolver, } @@ -752,6 +754,14 @@ impl<'a> SemanticsScope<'a> { }) } + /// 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. + pub fn resolve_hypothetical(&self, path: &ast::Path) -> Option { + let hygiene = Hygiene::new(self.db.upcast(), self.file_id); + let path = Path::from_src(path.clone(), &hygiene)?; + self.resolve_hir_path(&path) + } + pub fn resolve_hir_path(&self, path: &Path) -> Option { resolve_hir_path(self.db, &self.resolver, path) } diff --git a/crates/ssr/src/resolving.rs b/crates/ssr/src/resolving.rs index 020fd79941..4441fb426a 100644 --- a/crates/ssr/src/resolving.rs +++ b/crates/ssr/src/resolving.rs @@ -10,7 +10,6 @@ use test_utils::mark; pub(crate) struct ResolutionScope<'db> { scope: hir::SemanticsScope<'db>, - hygiene: hir::Hygiene, node: SyntaxNode, } @@ -201,11 +200,7 @@ impl<'db> ResolutionScope<'db> { .unwrap_or_else(|| file.syntax().clone()); let node = pick_node_for_resolution(node); let scope = sema.scope(&node); - ResolutionScope { - scope, - hygiene: hir::Hygiene::new(sema.db, resolve_context.file_id.into()), - node, - } + ResolutionScope { scope, node } } /// Returns the function in which SSR was invoked, if any. @@ -214,24 +209,31 @@ impl<'db> ResolutionScope<'db> { } fn resolve_path(&self, path: &ast::Path) -> Option { - let hir_path = hir::Path::from_src(path.clone(), &self.hygiene)?; // First try resolving the whole path. This will work for things like // `std::collections::HashMap`, but will fail for things like // `std::collections::HashMap::new`. - if let Some(resolution) = self.scope.resolve_hir_path(&hir_path) { + if let Some(resolution) = self.scope.resolve_hypothetical(&path) { return Some(resolution); } // Resolution failed, try resolving the qualifier (e.g. `std::collections::HashMap` and if // that succeeds, then iterate through the candidates on the resolved type with the provided // name. - let resolved_qualifier = self.scope.resolve_hir_path_qualifier(&hir_path.qualifier()?)?; + let resolved_qualifier = self.scope.resolve_hypothetical(&path.qualifier()?)?; if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier { + let name = path.segment()?.name_ref()?; adt.ty(self.scope.db).iterate_path_candidates( self.scope.db, self.scope.module()?.krate(), &self.scope.traits_in_scope(), - Some(hir_path.segments().last()?.name), - |_ty, assoc_item| Some(hir::PathResolution::AssocItem(assoc_item)), + None, + |_ty, assoc_item| { + let item_name = assoc_item.name(self.scope.db)?; + if item_name.to_string().as_str() == name.text().as_str() { + Some(hir::PathResolution::AssocItem(assoc_item)) + } else { + None + } + }, ) } else { None