@@ -132,11 +132,17 @@ pub struct LocatedImport {
132
132
pub import_path : ModPath ,
133
133
pub item_to_import : ItemInNs ,
134
134
pub original_item : ItemInNs ,
135
+ pub original_path : Option < ModPath > ,
135
136
}
136
137
137
138
impl LocatedImport {
138
- pub fn new ( import_path : ModPath , item_to_import : ItemInNs , original_item : ItemInNs ) -> Self {
139
- Self { import_path, item_to_import, original_item }
139
+ pub fn new (
140
+ import_path : ModPath ,
141
+ item_to_import : ItemInNs ,
142
+ original_item : ItemInNs ,
143
+ original_path : Option < ModPath > ,
144
+ ) -> Self {
145
+ Self { import_path, item_to_import, original_item, original_path }
140
146
}
141
147
142
148
pub fn original_item_name ( & self , db : & RootDatabase ) -> Option < Name > {
@@ -238,7 +244,9 @@ impl<'a> ImportAssets<'a> {
238
244
let _p = profile:: span ( "import_assets::applicable_defs" ) ;
239
245
let current_crate = self . module_with_candidate . krate ( ) ;
240
246
241
- let mod_path = |item| get_mod_path ( db, item, & self . module_with_candidate , prefixed) ;
247
+ let mod_path = |item| {
248
+ get_mod_path ( db, item_for_path_search ( db, item) ?, & self . module_with_candidate , prefixed)
249
+ } ;
242
250
243
251
match & self . import_candidate {
244
252
ImportCandidate :: Path ( path_candidate) => {
@@ -276,7 +284,9 @@ fn path_applicable_imports(
276
284
Qualifier :: Absent => {
277
285
return items_with_candidate_name
278
286
. into_iter ( )
279
- . filter_map ( |item| Some ( LocatedImport :: new ( mod_path ( item) ?, item, item) ) )
287
+ . filter_map ( |item| {
288
+ Some ( LocatedImport :: new ( mod_path ( item) ?, item, item, mod_path ( item) ) )
289
+ } )
280
290
. collect ( ) ;
281
291
}
282
292
Qualifier :: FirstSegmentUnresolved ( first_segment, qualifier) => {
@@ -300,46 +310,69 @@ fn import_for_item(
300
310
original_item : ItemInNs ,
301
311
) -> Option < LocatedImport > {
302
312
let _p = profile:: span ( "import_assets::import_for_item" ) ;
303
- let ( item_candidate, trait_to_import) = match original_item. as_module_def_id ( ) {
304
- Some ( module_def_id) => {
305
- match ModuleDef :: from ( module_def_id) . as_assoc_item ( db) . map ( |assoc| assoc. container ( db) )
306
- {
307
- Some ( AssocItemContainer :: Trait ( trait_) ) => {
308
- let trait_item = ItemInNs :: from ( ModuleDef :: from ( trait_) ) ;
309
- ( trait_item, Some ( trait_item) )
310
- }
311
- Some ( AssocItemContainer :: Impl ( impl_) ) => {
312
- ( ItemInNs :: from ( ModuleDef :: from ( impl_. target_ty ( db) . as_adt ( ) ?) ) , None )
313
- }
314
- None => ( original_item, None ) ,
315
- }
316
- }
317
- None => ( original_item, None ) ,
318
- } ;
319
- let import_path_candidate = mod_path ( item_candidate) ?;
320
313
314
+ let original_item_candidate = item_for_path_search ( db, original_item) ?;
315
+ let import_path_candidate = mod_path ( original_item_candidate) ?;
321
316
let import_path_string = import_path_candidate. to_string ( ) ;
317
+
322
318
if !import_path_string. contains ( unresolved_first_segment)
323
319
|| !import_path_string. contains ( unresolved_qualifier)
324
320
{
325
321
return None ;
326
322
}
327
323
328
- let segment_import = find_import_for_segment ( db, item_candidate, & unresolved_first_segment) ?;
329
- Some ( match ( segment_import == item_candidate, trait_to_import) {
324
+ let segment_import =
325
+ find_import_for_segment ( db, original_item_candidate, & unresolved_first_segment) ?;
326
+ let trait_item_to_import = original_item
327
+ . as_module_def_id ( )
328
+ . and_then ( |module_def_id| {
329
+ ModuleDef :: from ( module_def_id) . as_assoc_item ( db) ?. containing_trait ( db)
330
+ } )
331
+ . map ( |trait_| ItemInNs :: from ( ModuleDef :: from ( trait_) ) ) ;
332
+ Some ( match ( segment_import == original_item_candidate, trait_item_to_import) {
330
333
( true , Some ( _) ) => {
331
334
// FIXME we should be able to import both the trait and the segment,
332
335
// but it's unclear what to do with overlapping edits (merge imports?)
333
336
// especially in case of lazy completion edit resolutions.
334
337
return None ;
335
338
}
336
- ( false , Some ( trait_to_import) ) => {
337
- LocatedImport :: new ( mod_path ( trait_to_import) ?, trait_to_import, original_item)
338
- }
339
- ( true , None ) => LocatedImport :: new ( import_path_candidate, item_candidate, original_item) ,
340
- ( false , None ) => {
341
- LocatedImport :: new ( mod_path ( segment_import) ?, segment_import, original_item)
339
+ ( false , Some ( trait_to_import) ) => LocatedImport :: new (
340
+ mod_path ( trait_to_import) ?,
341
+ trait_to_import,
342
+ original_item,
343
+ mod_path ( original_item) ,
344
+ ) ,
345
+ ( true , None ) => LocatedImport :: new (
346
+ import_path_candidate,
347
+ original_item_candidate,
348
+ original_item,
349
+ mod_path ( original_item) ,
350
+ ) ,
351
+ ( false , None ) => LocatedImport :: new (
352
+ mod_path ( segment_import) ?,
353
+ segment_import,
354
+ original_item,
355
+ mod_path ( original_item) ,
356
+ ) ,
357
+ } )
358
+ }
359
+
360
+ fn item_for_path_search ( db : & RootDatabase , item : ItemInNs ) -> Option < ItemInNs > {
361
+ Some ( match item {
362
+ ItemInNs :: Types ( module_def_id) | ItemInNs :: Values ( module_def_id) => {
363
+ let module_def = ModuleDef :: from ( module_def_id) ;
364
+
365
+ match module_def. as_assoc_item ( db) {
366
+ Some ( assoc_item) => match assoc_item. container ( db) {
367
+ AssocItemContainer :: Trait ( trait_) => ItemInNs :: from ( ModuleDef :: from ( trait_) ) ,
368
+ AssocItemContainer :: Impl ( impl_) => {
369
+ ItemInNs :: from ( ModuleDef :: from ( impl_. target_ty ( db) . as_adt ( ) ?) )
370
+ }
371
+ } ,
372
+ None => item,
373
+ }
342
374
}
375
+ ItemInNs :: Macros ( _) => item,
343
376
} )
344
377
}
345
378
@@ -420,10 +453,12 @@ fn trait_applicable_items(
420
453
}
421
454
422
455
let item = ItemInNs :: from ( ModuleDef :: from ( assoc. containing_trait ( db) ?) ) ;
456
+ let original_item = assoc_to_item ( assoc) ;
423
457
located_imports. insert ( LocatedImport :: new (
424
458
mod_path ( item) ?,
425
459
item,
426
- assoc_to_item ( assoc) ,
460
+ original_item,
461
+ mod_path ( original_item) ,
427
462
) ) ;
428
463
}
429
464
None :: < ( ) >
@@ -439,10 +474,12 @@ fn trait_applicable_items(
439
474
let assoc = function. as_assoc_item ( db) ?;
440
475
if required_assoc_items. contains ( & assoc) {
441
476
let item = ItemInNs :: from ( ModuleDef :: from ( assoc. containing_trait ( db) ?) ) ;
477
+ let original_item = assoc_to_item ( assoc) ;
442
478
located_imports. insert ( LocatedImport :: new (
443
479
mod_path ( item) ?,
444
480
item,
445
- assoc_to_item ( assoc) ,
481
+ original_item,
482
+ mod_path ( original_item) ,
446
483
) ) ;
447
484
}
448
485
None :: < ( ) >
0 commit comments