}
impl AssocItem {
+ pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
+ 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),
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;
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 {
#[derive(Debug)]
pub struct SemanticsScope<'a> {
pub db: &'a dyn HirDatabase,
+ file_id: HirFileId,
resolver: Resolver,
}
})
}
+ /// 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<PathResolution> {
+ 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<PathResolution> {
resolve_hir_path(self.db, &self.resolver, path)
}
pub(crate) struct ResolutionScope<'db> {
scope: hir::SemanticsScope<'db>,
- hygiene: hir::Hygiene,
node: SyntaxNode,
}
.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.
}
fn resolve_path(&self, path: &ast::Path) -> Option<hir::PathResolution> {
- 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