diff options
-rw-r--r-- | crates/hir/src/lib.rs | 11 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/flyimport.rs | 65 | ||||
-rw-r--r-- | crates/ide_db/src/helpers/import_assets.rs | 212 |
3 files changed, 126 insertions, 162 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 62692c2c1..c4691d34c 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -1115,6 +1115,7 @@ pub enum AssocItem { | |||
1115 | Const(Const), | 1115 | Const(Const), |
1116 | TypeAlias(TypeAlias), | 1116 | TypeAlias(TypeAlias), |
1117 | } | 1117 | } |
1118 | #[derive(Debug)] | ||
1118 | pub enum AssocItemContainer { | 1119 | pub enum AssocItemContainer { |
1119 | Trait(Trait), | 1120 | Trait(Trait), |
1120 | Impl(Impl), | 1121 | Impl(Impl), |
@@ -2148,6 +2149,16 @@ impl ScopeDef { | |||
2148 | } | 2149 | } |
2149 | } | 2150 | } |
2150 | 2151 | ||
2152 | impl From<ItemInNs> for ScopeDef { | ||
2153 | fn from(item: ItemInNs) -> Self { | ||
2154 | match item { | ||
2155 | ItemInNs::Types(id) => ScopeDef::ModuleDef(id.into()), | ||
2156 | ItemInNs::Values(id) => ScopeDef::ModuleDef(id.into()), | ||
2157 | ItemInNs::Macros(id) => ScopeDef::MacroDef(id.into()), | ||
2158 | } | ||
2159 | } | ||
2160 | } | ||
2161 | |||
2151 | pub trait HasVisibility { | 2162 | pub trait HasVisibility { |
2152 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility; | 2163 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility; |
2153 | fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool { | 2164 | fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool { |
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs index d6adf70b1..55439d0e5 100644 --- a/crates/ide_completion/src/completions/flyimport.rs +++ b/crates/ide_completion/src/completions/flyimport.rs | |||
@@ -95,20 +95,20 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext) | |||
95 | .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind) | 95 | .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind) |
96 | .into_iter() | 96 | .into_iter() |
97 | .map(|import| { | 97 | .map(|import| { |
98 | let proposed_def = match import.item_to_display() { | 98 | let def_to_display = match import.item_to_display() { |
99 | ItemInNs::Types(id) => ScopeDef::ModuleDef(id.into()), | 99 | ItemInNs::Types(id) => ScopeDef::ModuleDef(id.into()), |
100 | ItemInNs::Values(id) => ScopeDef::ModuleDef(id.into()), | 100 | ItemInNs::Values(id) => ScopeDef::ModuleDef(id.into()), |
101 | ItemInNs::Macros(id) => ScopeDef::MacroDef(id.into()), | 101 | ItemInNs::Macros(id) => ScopeDef::MacroDef(id.into()), |
102 | }; | 102 | }; |
103 | (import, proposed_def) | 103 | (import, def_to_display) |
104 | }) | 104 | }) |
105 | .collect::<Vec<_>>(); | 105 | .collect::<Vec<_>>(); |
106 | all_mod_paths.sort_by_cached_key(|(import, _)| { | 106 | all_mod_paths.sort_by_cached_key(|(import, _)| { |
107 | compute_fuzzy_completion_order_key(import.display_path(), &user_input_lowercased) | 107 | compute_fuzzy_completion_order_key(import.display_path(), &user_input_lowercased) |
108 | }); | 108 | }); |
109 | 109 | ||
110 | acc.add_all(all_mod_paths.into_iter().filter_map(|(import, definition)| { | 110 | acc.add_all(all_mod_paths.into_iter().filter_map(|(import, def_to_display)| { |
111 | let import_for_trait_assoc_item = match definition { | 111 | let import_for_trait_assoc_item = match def_to_display { |
112 | ScopeDef::ModuleDef(module_def) => module_def | 112 | ScopeDef::ModuleDef(module_def) => module_def |
113 | .as_assoc_item(ctx.db) | 113 | .as_assoc_item(ctx.db) |
114 | .and_then(|assoc| assoc.containing_trait(ctx.db)) | 114 | .and_then(|assoc| assoc.containing_trait(ctx.db)) |
@@ -117,7 +117,7 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext) | |||
117 | }; | 117 | }; |
118 | let import_edit = | 118 | let import_edit = |
119 | ImportEdit { import, import_scope: import_scope.clone(), import_for_trait_assoc_item }; | 119 | ImportEdit { import, import_scope: import_scope.clone(), import_for_trait_assoc_item }; |
120 | render_resolution_with_import(RenderContext::new(ctx), import_edit, &definition) | 120 | render_resolution_with_import(RenderContext::new(ctx), import_edit, &def_to_display) |
121 | })); | 121 | })); |
122 | Some(()) | 122 | Some(()) |
123 | } | 123 | } |
@@ -870,59 +870,4 @@ fn main() { | |||
870 | "#, | 870 | "#, |
871 | ); | 871 | ); |
872 | } | 872 | } |
873 | |||
874 | #[test] | ||
875 | fn unresolved_assoc_item_container_and_trait_with_path() { | ||
876 | check_edit( | ||
877 | "TEST_ASSOC", | ||
878 | r#" | ||
879 | mod foo { | ||
880 | pub mod bar { | ||
881 | pub trait SomeTrait { | ||
882 | const TEST_ASSOC: usize; | ||
883 | } | ||
884 | } | ||
885 | |||
886 | pub mod baz { | ||
887 | use super::bar::SomeTrait; | ||
888 | |||
889 | pub struct Item; | ||
890 | |||
891 | impl SomeTrait for Item { | ||
892 | const TEST_ASSOC: usize = 3; | ||
893 | } | ||
894 | } | ||
895 | } | ||
896 | |||
897 | fn main() { | ||
898 | baz::Item::TEST_A$0 | ||
899 | } | ||
900 | "#, | ||
901 | r#" | ||
902 | use foo::{bar::SomeTrait, baz}; | ||
903 | |||
904 | mod foo { | ||
905 | pub mod bar { | ||
906 | pub trait SomeTrait { | ||
907 | const TEST_ASSOC: usize; | ||
908 | } | ||
909 | } | ||
910 | |||
911 | pub mod baz { | ||
912 | use super::bar::SomeTrait; | ||
913 | |||
914 | pub struct Item; | ||
915 | |||
916 | impl SomeTrait for Item { | ||
917 | const TEST_ASSOC: usize = 3; | ||
918 | } | ||
919 | } | ||
920 | } | ||
921 | |||
922 | fn main() { | ||
923 | baz::Item::TEST_ASSOC | ||
924 | } | ||
925 | "#, | ||
926 | ); | ||
927 | } | ||
928 | } | 873 | } |
diff --git a/crates/ide_db/src/helpers/import_assets.rs b/crates/ide_db/src/helpers/import_assets.rs index b25786928..2909ecd45 100644 --- a/crates/ide_db/src/helpers/import_assets.rs +++ b/crates/ide_db/src/helpers/import_assets.rs | |||
@@ -130,25 +130,23 @@ impl<'a> ImportAssets<'a> { | |||
130 | 130 | ||
131 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 131 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
132 | pub struct LocatedImport { | 132 | pub struct LocatedImport { |
133 | // TODO kb extract both into a separate struct + add another field: `assoc_item_name: Optional<String|Name>` | ||
133 | import_path: ModPath, | 134 | import_path: ModPath, |
134 | item_to_import: ItemInNs, | 135 | item_to_import: ItemInNs, |
135 | import_display_override: Option<(ModPath, ItemInNs)>, | 136 | data_to_display: Option<(ModPath, ItemInNs)>, |
136 | } | 137 | } |
137 | 138 | ||
138 | impl LocatedImport { | 139 | impl LocatedImport { |
139 | pub fn new( | 140 | pub fn new( |
140 | import_path: ModPath, | 141 | import_path: ModPath, |
141 | item_to_import: ItemInNs, | 142 | item_to_import: ItemInNs, |
142 | import_display_override: Option<(ModPath, ItemInNs)>, | 143 | data_to_display: Option<(ModPath, ItemInNs)>, |
143 | ) -> Self { | 144 | ) -> Self { |
144 | Self { import_path, item_to_import, import_display_override } | 145 | Self { import_path, item_to_import, data_to_display } |
145 | } | 146 | } |
146 | 147 | ||
147 | pub fn display_path(&self) -> &ModPath { | 148 | pub fn display_path(&self) -> &ModPath { |
148 | self.import_display_override | 149 | self.data_to_display.as_ref().map(|(mod_pathh, _)| mod_pathh).unwrap_or(&self.import_path) |
149 | .as_ref() | ||
150 | .map(|(mod_path, _)| mod_path) | ||
151 | .unwrap_or(&self.import_path) | ||
152 | } | 150 | } |
153 | 151 | ||
154 | pub fn import_path(&self) -> &ModPath { | 152 | pub fn import_path(&self) -> &ModPath { |
@@ -156,7 +154,7 @@ impl LocatedImport { | |||
156 | } | 154 | } |
157 | 155 | ||
158 | pub fn item_to_display(&self) -> ItemInNs { | 156 | pub fn item_to_display(&self) -> ItemInNs { |
159 | self.import_display_override.as_ref().map(|&(_, item)| item).unwrap_or(self.item_to_import) | 157 | self.data_to_display.as_ref().map(|&(_, item)| item).unwrap_or(self.item_to_import) |
160 | } | 158 | } |
161 | 159 | ||
162 | pub fn item_to_import(&self) -> ItemInNs { | 160 | pub fn item_to_import(&self) -> ItemInNs { |
@@ -200,7 +198,7 @@ impl<'a> ImportAssets<'a> { | |||
200 | let current_crate = self.module_with_candidate.krate(); | 198 | let current_crate = self.module_with_candidate.krate(); |
201 | let scope_definitions = self.scope_definitions(); | 199 | let scope_definitions = self.scope_definitions(); |
202 | 200 | ||
203 | let imports_for_candidate_name = match self.name_to_import() { | 201 | let defs_for_candidate_name = match self.name_to_import() { |
204 | NameToImport::Exact(exact_name) => { | 202 | NameToImport::Exact(exact_name) => { |
205 | imports_locator::find_exact_imports(sema, current_crate, exact_name.clone()) | 203 | imports_locator::find_exact_imports(sema, current_crate, exact_name.clone()) |
206 | } | 204 | } |
@@ -226,7 +224,7 @@ impl<'a> ImportAssets<'a> { | |||
226 | } | 224 | } |
227 | }; | 225 | }; |
228 | 226 | ||
229 | self.applicable_defs(sema.db, prefixed, imports_for_candidate_name) | 227 | self.applicable_defs(sema.db, prefixed, defs_for_candidate_name) |
230 | .into_iter() | 228 | .into_iter() |
231 | .filter(|import| import.import_path().len() > 1) | 229 | .filter(|import| import.import_path().len() > 1) |
232 | .filter(|import| { | 230 | .filter(|import| { |
@@ -252,32 +250,31 @@ impl<'a> ImportAssets<'a> { | |||
252 | &self, | 250 | &self, |
253 | db: &RootDatabase, | 251 | db: &RootDatabase, |
254 | prefixed: Option<PrefixKind>, | 252 | prefixed: Option<PrefixKind>, |
255 | unfiltered_defs: impl Iterator<Item = Either<ModuleDef, MacroDef>>, | 253 | defs_for_candidate_name: impl Iterator<Item = Either<ModuleDef, MacroDef>>, |
256 | ) -> FxHashSet<LocatedImport> { | 254 | ) -> FxHashSet<LocatedImport> { |
257 | let current_crate = self.module_with_candidate.krate(); | 255 | let current_crate = self.module_with_candidate.krate(); |
258 | 256 | ||
259 | let import_path_locator = | 257 | let mod_path = |item| get_mod_path(db, item, &self.module_with_candidate, prefixed); |
260 | |item| get_mod_path(db, item, &self.module_with_candidate, prefixed); | ||
261 | 258 | ||
262 | match &self.import_candidate { | 259 | match &self.import_candidate { |
263 | ImportCandidate::Path(path_candidate) => { | 260 | ImportCandidate::Path(path_candidate) => { |
264 | path_applicable_imports(db, path_candidate, import_path_locator, unfiltered_defs) | 261 | path_applicable_imports(db, path_candidate, mod_path, defs_for_candidate_name) |
265 | } | 262 | } |
266 | ImportCandidate::TraitAssocItem(trait_candidate) => trait_applicable_items( | 263 | ImportCandidate::TraitAssocItem(trait_candidate) => trait_applicable_items( |
267 | db, | 264 | db, |
268 | current_crate, | 265 | current_crate, |
269 | trait_candidate, | 266 | trait_candidate, |
270 | true, | 267 | true, |
271 | import_path_locator, | 268 | mod_path, |
272 | unfiltered_defs, | 269 | defs_for_candidate_name, |
273 | ), | 270 | ), |
274 | ImportCandidate::TraitMethod(trait_candidate) => trait_applicable_items( | 271 | ImportCandidate::TraitMethod(trait_candidate) => trait_applicable_items( |
275 | db, | 272 | db, |
276 | current_crate, | 273 | current_crate, |
277 | trait_candidate, | 274 | trait_candidate, |
278 | false, | 275 | false, |
279 | import_path_locator, | 276 | mod_path, |
280 | unfiltered_defs, | 277 | defs_for_candidate_name, |
281 | ), | 278 | ), |
282 | } | 279 | } |
283 | } | 280 | } |
@@ -286,103 +283,114 @@ impl<'a> ImportAssets<'a> { | |||
286 | fn path_applicable_imports( | 283 | fn path_applicable_imports( |
287 | db: &RootDatabase, | 284 | db: &RootDatabase, |
288 | path_candidate: &PathImportCandidate, | 285 | path_candidate: &PathImportCandidate, |
289 | import_path_locator: impl Fn(ItemInNs) -> Option<ModPath>, | 286 | mod_path: impl Fn(ItemInNs) -> Option<ModPath> + Copy, |
290 | unfiltered_defs: impl Iterator<Item = Either<ModuleDef, MacroDef>>, | 287 | defs_for_candidate_name: impl Iterator<Item = Either<ModuleDef, MacroDef>>, |
291 | ) -> FxHashSet<LocatedImport> { | 288 | ) -> FxHashSet<LocatedImport> { |
292 | let applicable_items = unfiltered_defs | 289 | let items_for_candidate_name = |
293 | .filter_map(|def| { | 290 | defs_for_candidate_name.map(|def| def.either(ItemInNs::from, ItemInNs::from)); |
294 | let (assoc_original, candidate) = match def { | ||
295 | Either::Left(module_def) => match module_def.as_assoc_item(db) { | ||
296 | Some(assoc_item) => match assoc_item.container(db) { | ||
297 | AssocItemContainer::Trait(trait_) => { | ||
298 | (Some(module_def), ItemInNs::from(ModuleDef::from(trait_))) | ||
299 | } | ||
300 | AssocItemContainer::Impl(impl_) => ( | ||
301 | Some(module_def), | ||
302 | ItemInNs::from(ModuleDef::from(impl_.target_ty(db).as_adt()?)), | ||
303 | ), | ||
304 | }, | ||
305 | None => (None, ItemInNs::from(module_def)), | ||
306 | }, | ||
307 | Either::Right(macro_def) => (None, ItemInNs::from(macro_def)), | ||
308 | }; | ||
309 | Some((assoc_original, candidate)) | ||
310 | }) | ||
311 | .filter_map(|(assoc_original, candidate)| { | ||
312 | import_path_locator(candidate).zip(Some((assoc_original, candidate))) | ||
313 | }); | ||
314 | 291 | ||
315 | let (unresolved_first_segment, unresolved_qualifier) = match &path_candidate.qualifier { | 292 | let (unresolved_first_segment, unresolved_qualifier) = match &path_candidate.qualifier { |
316 | Qualifier::Absent => { | 293 | Qualifier::Absent => { |
317 | return applicable_items | 294 | return items_for_candidate_name |
318 | .map(|(candidate_path, (_, candidate))| { | 295 | .filter_map(|item| Some(LocatedImport::new(mod_path(item)?, item, None))) |
319 | LocatedImport::new(candidate_path, candidate, None) | ||
320 | }) | ||
321 | .collect(); | 296 | .collect(); |
322 | } | 297 | } |
323 | Qualifier::FirstSegmentUnresolved(first_segment, qualifier) => (first_segment, qualifier), | 298 | Qualifier::FirstSegmentUnresolved(first_segment, qualifier) => { |
299 | (first_segment.to_string(), qualifier.to_string()) | ||
300 | } | ||
324 | }; | 301 | }; |
325 | 302 | ||
326 | let unresolved_qualifier_string = unresolved_qualifier.to_string(); | 303 | items_for_candidate_name |
327 | let unresolved_first_segment_string = unresolved_first_segment.to_string(); | 304 | .filter_map(|item| { |
328 | 305 | import_for_item(db, mod_path, &unresolved_first_segment, &unresolved_qualifier, item) | |
329 | applicable_items | ||
330 | .filter(|(candidate_path, _)| { | ||
331 | let candidate_path_string = candidate_path.to_string(); | ||
332 | candidate_path_string.contains(&unresolved_qualifier_string) | ||
333 | && candidate_path_string.contains(&unresolved_first_segment_string) | ||
334 | }) | ||
335 | .filter_map(|(candidate_path, (assoc_original, candidate))| { | ||
336 | let found_segment_resolution = item_name(db, candidate) | ||
337 | .map(|name| name.to_string() == unresolved_first_segment_string) | ||
338 | .unwrap_or(false); | ||
339 | let (import_path, item_to_import) = if found_segment_resolution { | ||
340 | (candidate_path.clone(), candidate) | ||
341 | } else { | ||
342 | let matching_module = | ||
343 | module_with_matching_name(db, &unresolved_first_segment_string, candidate)?; | ||
344 | let module_item = ItemInNs::from(ModuleDef::from(matching_module)); | ||
345 | (import_path_locator(module_item)?, module_item) | ||
346 | }; | ||
347 | |||
348 | Some(match assoc_original { | ||
349 | Some(assoc_original) => LocatedImport::new( | ||
350 | import_path.clone(), | ||
351 | item_to_import, | ||
352 | Some((import_path, ItemInNs::from(assoc_original))), | ||
353 | ), | ||
354 | None => LocatedImport::new( | ||
355 | import_path, | ||
356 | item_to_import, | ||
357 | if found_segment_resolution { None } else { Some((candidate_path, candidate)) }, | ||
358 | ), | ||
359 | }) | ||
360 | }) | 306 | }) |
361 | .collect() | 307 | .collect() |
362 | } | 308 | } |
363 | 309 | ||
364 | fn item_module(db: &RootDatabase, item: ItemInNs) -> Option<Module> { | 310 | fn import_for_item( |
365 | match item { | 311 | db: &RootDatabase, |
366 | ItemInNs::Types(module_def_id) => ModuleDef::from(module_def_id).module(db), | 312 | mod_path: impl Fn(ItemInNs) -> Option<ModPath>, |
367 | ItemInNs::Values(module_def_id) => ModuleDef::from(module_def_id).module(db), | 313 | unresolved_first_segment: &str, |
368 | ItemInNs::Macros(macro_def_id) => MacroDef::from(macro_def_id).module(db), | 314 | unresolved_qualifier: &str, |
315 | original_item: ItemInNs, | ||
316 | ) -> Option<LocatedImport> { | ||
317 | let (item_candidate, trait_to_import) = match original_item { | ||
318 | ItemInNs::Types(module_def_id) | ItemInNs::Values(module_def_id) => { | ||
319 | match ModuleDef::from(module_def_id).as_assoc_item(db).map(|assoc| assoc.container(db)) | ||
320 | { | ||
321 | Some(AssocItemContainer::Trait(trait_)) => { | ||
322 | let trait_item = ItemInNs::from(ModuleDef::from(trait_)); | ||
323 | (trait_item, Some(trait_item)) | ||
324 | } | ||
325 | Some(AssocItemContainer::Impl(impl_)) => { | ||
326 | (ItemInNs::from(ModuleDef::from(impl_.target_ty(db).as_adt()?)), None) | ||
327 | } | ||
328 | None => (original_item, None), | ||
329 | } | ||
330 | } | ||
331 | ItemInNs::Macros(_) => (original_item, None), | ||
332 | }; | ||
333 | let import_path_candidate = mod_path(item_candidate)?; | ||
334 | |||
335 | let import_path_string = import_path_candidate.to_string(); | ||
336 | if !import_path_string.contains(unresolved_first_segment) | ||
337 | || !import_path_string.contains(unresolved_qualifier) | ||
338 | { | ||
339 | return None; | ||
369 | } | 340 | } |
341 | |||
342 | let segment_import = find_import_for_segment(db, item_candidate, &unresolved_first_segment)?; | ||
343 | let data_to_display = Some((import_path_candidate.clone(), original_item)); | ||
344 | Some(match (segment_import == item_candidate, trait_to_import) { | ||
345 | (true, Some(_)) => { | ||
346 | // FIXME we should be able to import both the trait and the segment, | ||
347 | // but it's unclear what to do with overlapping edits (merge imports?) | ||
348 | // especially in case of lazy completion edit resolutions. | ||
349 | return None; | ||
350 | } | ||
351 | (false, Some(trait_to_import)) => { | ||
352 | LocatedImport::new(mod_path(trait_to_import)?, trait_to_import, data_to_display) | ||
353 | } | ||
354 | (true, None) => LocatedImport::new(import_path_candidate, item_candidate, data_to_display), | ||
355 | (false, None) => { | ||
356 | LocatedImport::new(mod_path(segment_import)?, segment_import, data_to_display) | ||
357 | } | ||
358 | }) | ||
370 | } | 359 | } |
371 | 360 | ||
372 | fn module_with_matching_name( | 361 | fn find_import_for_segment( |
373 | db: &RootDatabase, | 362 | db: &RootDatabase, |
374 | unresolved_first_segment_string: &str, | 363 | original_item: ItemInNs, |
364 | unresolved_first_segment: &str, | ||
365 | ) -> Option<ItemInNs> { | ||
366 | let segment_is_name = item_name(db, original_item) | ||
367 | .map(|name| name.to_string() == unresolved_first_segment) | ||
368 | .unwrap_or(false); | ||
369 | |||
370 | Some(if segment_is_name { | ||
371 | original_item | ||
372 | } else { | ||
373 | let matching_module = | ||
374 | module_with_segment_name(db, &unresolved_first_segment, original_item)?; | ||
375 | ItemInNs::from(ModuleDef::from(matching_module)) | ||
376 | }) | ||
377 | } | ||
378 | |||
379 | fn module_with_segment_name( | ||
380 | db: &RootDatabase, | ||
381 | segment_name: &str, | ||
375 | candidate: ItemInNs, | 382 | candidate: ItemInNs, |
376 | ) -> Option<Module> { | 383 | ) -> Option<Module> { |
377 | let mut current_module = item_module(db, candidate); | 384 | let mut current_module = match candidate { |
385 | ItemInNs::Types(module_def_id) => ModuleDef::from(module_def_id).module(db), | ||
386 | ItemInNs::Values(module_def_id) => ModuleDef::from(module_def_id).module(db), | ||
387 | ItemInNs::Macros(macro_def_id) => MacroDef::from(macro_def_id).module(db), | ||
388 | }; | ||
378 | while let Some(module) = current_module { | 389 | while let Some(module) = current_module { |
379 | match module.name(db) { | 390 | if let Some(module_name) = module.name(db) { |
380 | Some(module_name) => { | 391 | if module_name.to_string() == segment_name { |
381 | if module_name.to_string().as_str() == unresolved_first_segment_string { | 392 | return Some(module); |
382 | return Some(module); | ||
383 | } | ||
384 | } | 393 | } |
385 | None => {} | ||
386 | } | 394 | } |
387 | current_module = module.parent(db); | 395 | current_module = module.parent(db); |
388 | } | 396 | } |
@@ -394,12 +402,12 @@ fn trait_applicable_items( | |||
394 | current_crate: Crate, | 402 | current_crate: Crate, |
395 | trait_candidate: &TraitImportCandidate, | 403 | trait_candidate: &TraitImportCandidate, |
396 | trait_assoc_item: bool, | 404 | trait_assoc_item: bool, |
397 | import_path_locator: impl Fn(ItemInNs) -> Option<ModPath>, | 405 | mod_path: impl Fn(ItemInNs) -> Option<ModPath>, |
398 | unfiltered_defs: impl Iterator<Item = Either<ModuleDef, MacroDef>>, | 406 | defs_for_candidate_name: impl Iterator<Item = Either<ModuleDef, MacroDef>>, |
399 | ) -> FxHashSet<LocatedImport> { | 407 | ) -> FxHashSet<LocatedImport> { |
400 | let mut required_assoc_items = FxHashSet::default(); | 408 | let mut required_assoc_items = FxHashSet::default(); |
401 | 409 | ||
402 | let trait_candidates = unfiltered_defs | 410 | let trait_candidates = defs_for_candidate_name |
403 | .filter_map(|input| match input { | 411 | .filter_map(|input| match input { |
404 | Either::Left(module_def) => module_def.as_assoc_item(db), | 412 | Either::Left(module_def) => module_def.as_assoc_item(db), |
405 | _ => None, | 413 | _ => None, |
@@ -428,12 +436,12 @@ fn trait_applicable_items( | |||
428 | } | 436 | } |
429 | 437 | ||
430 | let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); | 438 | let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); |
431 | let item_path = import_path_locator(item)?; | 439 | let item_path = mod_path(item)?; |
432 | 440 | ||
433 | let assoc_item = assoc_to_item(assoc); | 441 | let assoc_item = assoc_to_item(assoc); |
434 | let assoc_item_path = match assoc.container(db) { | 442 | let assoc_item_path = match assoc.container(db) { |
435 | AssocItemContainer::Trait(_) => item_path.clone(), | 443 | AssocItemContainer::Trait(_) => item_path.clone(), |
436 | AssocItemContainer::Impl(impl_) => import_path_locator(ItemInNs::from( | 444 | AssocItemContainer::Impl(impl_) => mod_path(ItemInNs::from( |
437 | ModuleDef::from(impl_.target_ty(db).as_adt()?), | 445 | ModuleDef::from(impl_.target_ty(db).as_adt()?), |
438 | ))?, | 446 | ))?, |
439 | }; | 447 | }; |
@@ -457,12 +465,12 @@ fn trait_applicable_items( | |||
457 | let assoc = function.as_assoc_item(db)?; | 465 | let assoc = function.as_assoc_item(db)?; |
458 | if required_assoc_items.contains(&assoc) { | 466 | if required_assoc_items.contains(&assoc) { |
459 | let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); | 467 | let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); |
460 | let item_path = import_path_locator(item)?; | 468 | let item_path = mod_path(item)?; |
461 | 469 | ||
462 | let assoc_item = assoc_to_item(assoc); | 470 | let assoc_item = assoc_to_item(assoc); |
463 | let assoc_item_path = match assoc.container(db) { | 471 | let assoc_item_path = match assoc.container(db) { |
464 | AssocItemContainer::Trait(_) => item_path.clone(), | 472 | AssocItemContainer::Trait(_) => item_path.clone(), |
465 | AssocItemContainer::Impl(impl_) => import_path_locator(ItemInNs::from( | 473 | AssocItemContainer::Impl(impl_) => mod_path(ItemInNs::from( |
466 | ModuleDef::from(impl_.target_ty(db).as_adt()?), | 474 | ModuleDef::from(impl_.target_ty(db).as_adt()?), |
467 | ))?, | 475 | ))?, |
468 | }; | 476 | }; |