@@ -11,6 +11,34 @@ use hir_expand::name::{known, Name};
1111
1212const MAX_PATH_LEN : usize = 15 ;
1313
14+ impl ModPath {
15+ fn starts_with_std ( & self ) -> bool {
16+ self . segments . first ( ) . filter ( |& first_segment| first_segment == & known:: std) . is_some ( )
17+ }
18+
19+ // When std library is present, paths starting with `std::`
20+ // should be preferred over paths starting with `core::` and `alloc::`
21+ fn should_start_with_std ( & self ) -> bool {
22+ self . segments
23+ . first ( )
24+ . filter ( |& first_segment| {
25+ first_segment == & known:: alloc || first_segment == & known:: core
26+ } )
27+ . is_some ( )
28+ }
29+
30+ fn len ( & self ) -> usize {
31+ self . segments . len ( )
32+ + match self . kind {
33+ PathKind :: Plain => 0 ,
34+ PathKind :: Super ( i) => i as usize ,
35+ PathKind :: Crate => 1 ,
36+ PathKind :: Abs => 0 ,
37+ PathKind :: DollarCrate ( _) => 1 ,
38+ }
39+ }
40+ }
41+
1442// FIXME: handle local items
1543
1644/// Find a path that can be used to refer to a certain item. This can depend on
@@ -102,7 +130,7 @@ fn find_path_inner(
102130 let mut best_path = None ;
103131 let mut best_path_len = max_len;
104132 for ( module_id, name) in importable_locations {
105- let mut new_path = match find_path_inner (
133+ let mut path = match find_path_inner (
106134 db,
107135 ItemInNs :: Types ( ModuleDefId :: ModuleId ( module_id) ) ,
108136 from,
@@ -111,51 +139,28 @@ fn find_path_inner(
111139 None => continue ,
112140 Some ( path) => path,
113141 } ;
114- new_path . segments . push ( name) ;
142+ path . segments . push ( name) ;
115143
116- if prefer_new_path ( best_path_len , best_path . as_ref ( ) , & new_path) {
117- best_path_len = path_len ( & new_path ) ;
118- best_path = Some ( new_path) ;
119- }
144+ let new_path =
145+ if let Some ( best_path ) = best_path { select_best_path ( best_path , path ) } else { path } ;
146+ best_path_len = new_path. len ( ) ;
147+ best_path = Some ( new_path ) ;
120148 }
121149 best_path
122150}
123151
124- fn prefer_new_path ( old_path_len : usize , old_path : Option < & ModPath > , new_path : & ModPath ) -> bool {
125- match ( old_path. and_then ( |mod_path| mod_path. segments . first ( ) ) , new_path. segments . first ( ) ) {
126- ( Some ( old_path_start) , Some ( new_path_start) )
127- if old_path_start == & known:: std && use_std_instead ( new_path_start) =>
128- {
129- false
130- }
131- ( Some ( old_path_start) , Some ( new_path_start) )
132- if new_path_start == & known:: std && use_std_instead ( old_path_start) =>
133- {
134- true
135- }
136- ( None , Some ( _) ) => true ,
137- ( Some ( _) , None ) => false ,
138- _ => path_len ( new_path) < old_path_len,
152+ fn select_best_path ( old_path : ModPath , new_path : ModPath ) -> ModPath {
153+ if old_path. starts_with_std ( ) && new_path. should_start_with_std ( ) {
154+ old_path
155+ } else if new_path. starts_with_std ( ) && old_path. should_start_with_std ( ) {
156+ new_path
157+ } else if new_path. len ( ) < old_path. len ( ) {
158+ new_path
159+ } else {
160+ old_path
139161 }
140162}
141163
142- // When std library is present, paths starting with `std::`
143- // should be preferred over paths starting with `core::` and `alloc::`
144- fn use_std_instead ( name : & Name ) -> bool {
145- name == & known:: core || name == & known:: alloc
146- }
147-
148- fn path_len ( path : & ModPath ) -> usize {
149- path. segments . len ( )
150- + match path. kind {
151- PathKind :: Plain => 0 ,
152- PathKind :: Super ( i) => i as usize ,
153- PathKind :: Crate => 1 ,
154- PathKind :: Abs => 0 ,
155- PathKind :: DollarCrate ( _) => 1 ,
156- }
157- }
158-
159164fn find_importable_locations (
160165 db : & impl DefDatabase ,
161166 item : ItemInNs ,
0 commit comments