aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2020-04-25 15:24:44 +0100
committerJonas Schievink <[email protected]>2020-04-25 15:27:34 +0100
commit3cf2c3b943a5b373dbd333622c16f3d606fdb6ab (patch)
tree885a9f87b31e23ba305cd42e1a03a728d892c70d /crates
parent05981823bac91ba338110902fd435c6e3166f1d6 (diff)
Prefer core/alloc paths on #![no_std]
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_def/src/attr.rs23
-rw-r--r--crates/ra_hir_def/src/find_path.rs78
2 files changed, 87 insertions, 14 deletions
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 714a66b02..5a86af8ba 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -13,7 +13,8 @@ use ra_syntax::{
13use tt::Subtree; 13use tt::Subtree;
14 14
15use crate::{ 15use crate::{
16 db::DefDatabase, path::ModPath, src::HasChildSource, src::HasSource, AdtId, AttrDefId, Lookup, 16 db::DefDatabase, nameres::ModuleSource, path::ModPath, src::HasChildSource, src::HasSource,
17 AdtId, AttrDefId, Lookup,
17}; 18};
18 19
19#[derive(Default, Debug, Clone, PartialEq, Eq)] 20#[derive(Default, Debug, Clone, PartialEq, Eq)]
@@ -37,11 +38,19 @@ impl Attrs {
37 match def { 38 match def {
38 AttrDefId::ModuleId(module) => { 39 AttrDefId::ModuleId(module) => {
39 let def_map = db.crate_def_map(module.krate); 40 let def_map = db.crate_def_map(module.krate);
40 let src = match def_map[module.local_id].declaration_source(db) { 41 let mod_data = &def_map[module.local_id];
41 Some(it) => it, 42 match mod_data.declaration_source(db) {
42 None => return Attrs::default(), 43 Some(it) => {
43 }; 44 Attrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner))
44 Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner)) 45 }
46 None => Attrs::from_attrs_owner(
47 db,
48 mod_data.definition_source(db).as_ref().map(|src| match src {
49 ModuleSource::SourceFile(file) => file as &dyn AttrsOwner,
50 ModuleSource::Module(module) => module as &dyn AttrsOwner,
51 }),
52 ),
53 }
45 } 54 }
46 AttrDefId::FieldId(it) => { 55 AttrDefId::FieldId(it) => {
47 let src = it.parent.child_source(db); 56 let src = it.parent.child_source(db);
@@ -106,7 +115,9 @@ pub struct Attr {
106 115
107#[derive(Debug, Clone, PartialEq, Eq)] 116#[derive(Debug, Clone, PartialEq, Eq)]
108pub enum AttrInput { 117pub enum AttrInput {
118 /// `#[attr = "string"]`
109 Literal(SmolStr), 119 Literal(SmolStr),
120 /// `#[attr(subtree)]`
110 TokenTree(Subtree), 121 TokenTree(Subtree),
111} 122}
112 123
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
158fn select_best_path(old_path: ModPath, new_path: ModPath) -> ModPath { 164fn 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