aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ssr/src/resolving.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-08-12 14:50:34 +0100
committerGitHub <[email protected]>2020-08-12 14:50:34 +0100
commit1e8b2c498a01dc2c92d6008cdc5b611cf3a96b1e (patch)
treee1f4652227443b07f592ba156dad938e11ef2e0b /crates/ra_ssr/src/resolving.rs
parent5b8fdfe23100b88e4fd8e210ccf6b852f5c9bf2a (diff)
parent21d2cebcf1a417bce72da98aa638a20235c050db (diff)
Merge #5637
5637: SSR: Matching trait associated constants, types and functions r=matklad a=davidlattimore This fixes matching of things like `HashMap::default()` by resolving `HashMap` instead of `default` (which resolves to `Default::default`). Same for associated constants and types that are part of a trait implementation. However, we still don't support matching calls to trait methods. Co-authored-by: David Lattimore <[email protected]>
Diffstat (limited to 'crates/ra_ssr/src/resolving.rs')
-rw-r--r--crates/ra_ssr/src/resolving.rs31
1 files changed, 27 insertions, 4 deletions
diff --git a/crates/ra_ssr/src/resolving.rs b/crates/ra_ssr/src/resolving.rs
index df60048eb..d53bd46c7 100644
--- a/crates/ra_ssr/src/resolving.rs
+++ b/crates/ra_ssr/src/resolving.rs
@@ -5,7 +5,7 @@ use crate::{parsing, SsrError};
5use parsing::Placeholder; 5use parsing::Placeholder;
6use ra_db::FilePosition; 6use ra_db::FilePosition;
7use ra_syntax::{ast, SmolStr, SyntaxKind, SyntaxNode, SyntaxToken}; 7use ra_syntax::{ast, SmolStr, SyntaxKind, SyntaxNode, SyntaxToken};
8use rustc_hash::{FxHashMap, FxHashSet}; 8use rustc_hash::FxHashMap;
9use test_utils::mark; 9use test_utils::mark;
10 10
11pub(crate) struct ResolutionScope<'db> { 11pub(crate) struct ResolutionScope<'db> {
@@ -124,8 +124,10 @@ impl Resolver<'_, '_> {
124 .resolution_scope 124 .resolution_scope
125 .resolve_path(&path) 125 .resolve_path(&path)
126 .ok_or_else(|| error!("Failed to resolve path `{}`", node.text()))?; 126 .ok_or_else(|| error!("Failed to resolve path `{}`", node.text()))?;
127 resolved_paths.insert(node, ResolvedPath { resolution, depth }); 127 if self.ok_to_use_path_resolution(&resolution) {
128 return Ok(()); 128 resolved_paths.insert(node, ResolvedPath { resolution, depth });
129 return Ok(());
130 }
129 } 131 }
130 } 132 }
131 for node in node.children() { 133 for node in node.children() {
@@ -149,6 +151,27 @@ impl Resolver<'_, '_> {
149 } 151 }
150 false 152 false
151 } 153 }
154
155 fn ok_to_use_path_resolution(&self, resolution: &hir::PathResolution) -> bool {
156 match resolution {
157 hir::PathResolution::AssocItem(hir::AssocItem::Function(function)) => {
158 if function.has_self_param(self.resolution_scope.scope.db) {
159 // If we don't use this path resolution, then we won't be able to match method
160 // calls. e.g. `Foo::bar($s)` should match `x.bar()`.
161 true
162 } else {
163 mark::hit!(replace_associated_trait_default_function_call);
164 false
165 }
166 }
167 hir::PathResolution::AssocItem(_) => {
168 // Not a function. Could be a constant or an associated type.
169 mark::hit!(replace_associated_trait_constant);
170 false
171 }
172 _ => true,
173 }
174 }
152} 175}
153 176
154impl<'db> ResolutionScope<'db> { 177impl<'db> ResolutionScope<'db> {
@@ -195,7 +218,7 @@ impl<'db> ResolutionScope<'db> {
195 adt.ty(self.scope.db).iterate_path_candidates( 218 adt.ty(self.scope.db).iterate_path_candidates(
196 self.scope.db, 219 self.scope.db,
197 self.scope.module()?.krate(), 220 self.scope.module()?.krate(),
198 &FxHashSet::default(), 221 &self.scope.traits_in_scope(),
199 Some(hir_path.segments().last()?.name), 222 Some(hir_path.segments().last()?.name),
200 |_ty, assoc_item| Some(hir::PathResolution::AssocItem(assoc_item)), 223 |_ty, assoc_item| Some(hir::PathResolution::AssocItem(assoc_item)),
201 ) 224 )