diff options
Diffstat (limited to 'crates/ra_hir_def/src/find_path.rs')
-rw-r--r-- | crates/ra_hir_def/src/find_path.rs | 78 |
1 files changed, 70 insertions, 8 deletions
diff --git a/crates/ra_hir_def/src/find_path.rs b/crates/ra_hir_def/src/find_path.rs index 81eff5bfe..70dcb03e6 100644 --- a/crates/ra_hir_def/src/find_path.rs +++ b/crates/ra_hir_def/src/find_path.rs | |||
@@ -19,7 +19,7 @@ impl ModPath { | |||
19 | 19 | ||
20 | // When std library is present, paths starting with `std::` | 20 | // When std library is present, paths starting with `std::` |
21 | // should be preferred over paths starting with `core::` and `alloc::` | 21 | // should be preferred over paths starting with `core::` and `alloc::` |
22 | fn should_start_with_std(&self) -> bool { | 22 | fn can_start_with_std(&self) -> bool { |
23 | self.segments | 23 | self.segments |
24 | .first() | 24 | .first() |
25 | .filter(|&first_segment| { | 25 | .filter(|&first_segment| { |
@@ -132,6 +132,9 @@ fn find_path_inner( | |||
132 | } | 132 | } |
133 | 133 | ||
134 | // - otherwise, look for modules containing (reexporting) it and import it from one of those | 134 | // - otherwise, look for modules containing (reexporting) it and import it from one of those |
135 | let crate_root = ModuleId { local_id: def_map.root, krate: from.krate }; | ||
136 | let crate_attrs = db.attrs(crate_root.into()); | ||
137 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); | ||
135 | let importable_locations = find_importable_locations(db, item, from); | 138 | let importable_locations = find_importable_locations(db, item, from); |
136 | let mut best_path = None; | 139 | let mut best_path = None; |
137 | let mut best_path_len = max_len; | 140 | let mut best_path_len = max_len; |
@@ -147,21 +150,32 @@ fn find_path_inner( | |||
147 | }; | 150 | }; |
148 | path.segments.push(name); | 151 | path.segments.push(name); |
149 | 152 | ||
150 | let new_path = | 153 | let new_path = if let Some(best_path) = best_path { |
151 | if let Some(best_path) = best_path { select_best_path(best_path, path) } else { path }; | 154 | select_best_path(best_path, path, prefer_no_std) |
155 | } else { | ||
156 | path | ||
157 | }; | ||
152 | best_path_len = new_path.len(); | 158 | best_path_len = new_path.len(); |
153 | best_path = Some(new_path); | 159 | best_path = Some(new_path); |
154 | } | 160 | } |
155 | best_path | 161 | best_path |
156 | } | 162 | } |
157 | 163 | ||
158 | fn select_best_path(old_path: ModPath, new_path: ModPath) -> ModPath { | 164 | fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -> ModPath { |
159 | if old_path.starts_with_std() && new_path.should_start_with_std() { | 165 | if old_path.starts_with_std() && new_path.can_start_with_std() { |
160 | tested_by!(prefer_std_paths); | 166 | tested_by!(prefer_std_paths); |
161 | old_path | 167 | if prefer_no_std { |
162 | } else if new_path.starts_with_std() && old_path.should_start_with_std() { | 168 | new_path |
169 | } else { | ||
170 | old_path | ||
171 | } | ||
172 | } else if new_path.starts_with_std() && old_path.can_start_with_std() { | ||
163 | tested_by!(prefer_std_paths); | 173 | tested_by!(prefer_std_paths); |
164 | new_path | 174 | if prefer_no_std { |
175 | old_path | ||
176 | } else { | ||
177 | new_path | ||
178 | } | ||
165 | } else if new_path.len() < old_path.len() { | 179 | } else if new_path.len() < old_path.len() { |
166 | new_path | 180 | new_path |
167 | } else { | 181 | } else { |
@@ -513,6 +527,54 @@ mod tests { | |||
513 | } | 527 | } |
514 | 528 | ||
515 | #[test] | 529 | #[test] |
530 | fn prefer_alloc_paths_over_std() { | ||
531 | covers!(prefer_std_paths); | ||
532 | let code = r#" | ||
533 | //- /main.rs crate:main deps:alloc,std | ||
534 | #![no_std] | ||
535 | |||
536 | <|> | ||
537 | |||
538 | //- /std.rs crate:std deps:alloc | ||
539 | |||
540 | pub mod sync { | ||
541 | pub use alloc::sync::Arc; | ||
542 | } | ||
543 | |||
544 | //- /zzz.rs crate:alloc | ||
545 | |||
546 | pub mod sync { | ||
547 | pub struct Arc; | ||
548 | } | ||
549 | "#; | ||
550 | check_found_path(code, "alloc::sync::Arc"); | ||
551 | } | ||
552 | |||
553 | #[test] | ||
554 | fn prefer_core_paths_over_std() { | ||
555 | covers!(prefer_std_paths); | ||
556 | let code = r#" | ||
557 | //- /main.rs crate:main deps:core,std | ||
558 | #![no_std] | ||
559 | |||
560 | <|> | ||
561 | |||
562 | //- /std.rs crate:std deps:core | ||
563 | |||
564 | pub mod fmt { | ||
565 | pub use core::fmt::Error; | ||
566 | } | ||
567 | |||
568 | //- /zzz.rs crate:core | ||
569 | |||
570 | pub mod fmt { | ||
571 | pub struct Error; | ||
572 | } | ||
573 | "#; | ||
574 | check_found_path(code, "core::fmt::Error"); | ||
575 | } | ||
576 | |||
577 | #[test] | ||
516 | fn prefer_shorter_paths_if_not_alloc() { | 578 | fn prefer_shorter_paths_if_not_alloc() { |
517 | let code = r#" | 579 | let code = r#" |
518 | //- /main.rs crate:main deps:megaalloc,std | 580 | //- /main.rs crate:main deps:megaalloc,std |