aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/adt.rs22
-rw-r--r--crates/ra_hir_def/src/attr.rs25
-rw-r--r--crates/ra_hir_def/src/body.rs2
-rw-r--r--crates/ra_hir_def/src/body/lower.rs4
-rw-r--r--crates/ra_hir_def/src/body/scope.rs2
-rw-r--r--crates/ra_hir_def/src/child_by_source.rs6
-rw-r--r--crates/ra_hir_def/src/docs.rs2
-rw-r--r--crates/ra_hir_def/src/find_path.rs78
-rw-r--r--crates/ra_hir_def/src/keys.rs6
-rw-r--r--crates/ra_hir_def/src/lib.rs10
10 files changed, 117 insertions, 40 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 7c0d93691..753becc3d 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -14,7 +14,7 @@ use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner};
14use crate::{ 14use crate::{
15 body::CfgExpander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, 15 body::CfgExpander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace,
16 type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId, 16 type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId,
17 LocalStructFieldId, Lookup, ModuleId, StructId, UnionId, VariantId, 17 LocalFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
18}; 18};
19 19
20/// Note that we use `StructData` for unions as well! 20/// Note that we use `StructData` for unions as well!
@@ -38,14 +38,14 @@ pub struct EnumVariantData {
38 38
39#[derive(Debug, Clone, PartialEq, Eq)] 39#[derive(Debug, Clone, PartialEq, Eq)]
40pub enum VariantData { 40pub enum VariantData {
41 Record(Arena<StructFieldData>), 41 Record(Arena<FieldData>),
42 Tuple(Arena<StructFieldData>), 42 Tuple(Arena<FieldData>),
43 Unit, 43 Unit,
44} 44}
45 45
46/// A single field of an enum variant or struct 46/// A single field of an enum variant or struct
47#[derive(Debug, Clone, PartialEq, Eq)] 47#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct StructFieldData { 48pub struct FieldData {
49 pub name: Name, 49 pub name: Name,
50 pub type_ref: TypeRef, 50 pub type_ref: TypeRef,
51 pub visibility: RawVisibility, 51 pub visibility: RawVisibility,
@@ -133,15 +133,15 @@ impl VariantData {
133 } 133 }
134 } 134 }
135 135
136 pub fn fields(&self) -> &Arena<StructFieldData> { 136 pub fn fields(&self) -> &Arena<FieldData> {
137 const EMPTY: &Arena<StructFieldData> = &Arena::new(); 137 const EMPTY: &Arena<FieldData> = &Arena::new();
138 match &self { 138 match &self {
139 VariantData::Record(fields) | VariantData::Tuple(fields) => fields, 139 VariantData::Record(fields) | VariantData::Tuple(fields) => fields,
140 _ => EMPTY, 140 _ => EMPTY,
141 } 141 }
142 } 142 }
143 143
144 pub fn field(&self, name: &Name) -> Option<LocalStructFieldId> { 144 pub fn field(&self, name: &Name) -> Option<LocalFieldId> {
145 self.fields().iter().find_map(|(id, data)| if &data.name == name { Some(id) } else { None }) 145 self.fields().iter().find_map(|(id, data)| if &data.name == name { Some(id) } else { None })
146 } 146 }
147 147
@@ -155,7 +155,7 @@ impl VariantData {
155} 155}
156 156
157impl HasChildSource for VariantId { 157impl HasChildSource for VariantId {
158 type ChildId = LocalStructFieldId; 158 type ChildId = LocalFieldId;
159 type Value = Either<ast::TupleFieldDef, ast::RecordFieldDef>; 159 type Value = Either<ast::TupleFieldDef, ast::RecordFieldDef>;
160 160
161 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> { 161 fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> {
@@ -195,7 +195,7 @@ pub enum StructKind {
195fn lower_struct( 195fn lower_struct(
196 db: &dyn DefDatabase, 196 db: &dyn DefDatabase,
197 expander: &mut CfgExpander, 197 expander: &mut CfgExpander,
198 trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, 198 trace: &mut Trace<FieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>,
199 ast: &InFile<ast::StructKind>, 199 ast: &InFile<ast::StructKind>,
200) -> StructKind { 200) -> StructKind {
201 match &ast.value { 201 match &ast.value {
@@ -208,7 +208,7 @@ fn lower_struct(
208 208
209 trace.alloc( 209 trace.alloc(
210 || Either::Left(fd.clone()), 210 || Either::Left(fd.clone()),
211 || StructFieldData { 211 || FieldData {
212 name: Name::new_tuple_field(i), 212 name: Name::new_tuple_field(i),
213 type_ref: TypeRef::from_ast_opt(fd.type_ref()), 213 type_ref: TypeRef::from_ast_opt(fd.type_ref()),
214 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), 214 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
@@ -226,7 +226,7 @@ fn lower_struct(
226 226
227 trace.alloc( 227 trace.alloc(
228 || Either::Right(fd.clone()), 228 || Either::Right(fd.clone()),
229 || StructFieldData { 229 || FieldData {
230 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), 230 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
231 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), 231 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()),
232 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), 232 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 2f2e3e5ba..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,13 +38,21 @@ 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::StructFieldId(it) => { 55 AttrDefId::FieldId(it) => {
47 let src = it.parent.child_source(db); 56 let src = it.parent.child_source(db);
48 match &src.value[it.local_id] { 57 match &src.value[it.local_id] {
49 Either::Left(_tuple) => Attrs::default(), 58 Either::Left(_tuple) => Attrs::default(),
@@ -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/body.rs b/crates/ra_hir_def/src/body.rs
index 3b169440a..890cefcaf 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -27,7 +27,7 @@ use crate::{
27 AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, 27 AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId,
28}; 28};
29 29
30/// A subser of Exander that only deals with cfg attributes. We only need it to 30/// A subset of Exander that only deals with cfg attributes. We only need it to
31/// avoid cyclic queries in crate def map during enum processing. 31/// avoid cyclic queries in crate def map during enum processing.
32pub(crate) struct CfgExpander { 32pub(crate) struct CfgExpander {
33 cfg_options: CfgOptions, 33 cfg_options: CfgOptions,
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 0caedd8d8..571603854 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -141,6 +141,10 @@ impl ExprCollector<'_> {
141 141
142 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { 142 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
143 let syntax_ptr = AstPtr::new(&expr); 143 let syntax_ptr = AstPtr::new(&expr);
144 let attrs = self.expander.parse_attrs(&expr);
145 if !self.expander.is_cfg_enabled(&attrs) {
146 return self.missing_expr();
147 }
144 match expr { 148 match expr {
145 ast::Expr::IfExpr(e) => { 149 ast::Expr::IfExpr(e) => {
146 let then_branch = self.collect_block_opt(e.then_branch()); 150 let then_branch = self.collect_block_opt(e.then_branch());
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 5b36a7cc1..86f953c80 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -194,7 +194,7 @@ mod tests {
194 let (off, code) = extract_offset(code); 194 let (off, code) = extract_offset(code);
195 let code = { 195 let code = {
196 let mut buf = String::new(); 196 let mut buf = String::new();
197 let off = off.to_usize(); 197 let off: usize = off.into();
198 buf.push_str(&code[..off]); 198 buf.push_str(&code[..off]);
199 buf.push_str("marker"); 199 buf.push_str("marker");
200 buf.push_str(&code[off..]); 200 buf.push_str(&code[off..]);
diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs
index 7009f21d1..a885ec96d 100644
--- a/crates/ra_hir_def/src/child_by_source.rs
+++ b/crates/ra_hir_def/src/child_by_source.rs
@@ -12,8 +12,8 @@ use crate::{
12 item_scope::ItemScope, 12 item_scope::ItemScope,
13 keys, 13 keys,
14 src::{HasChildSource, HasSource}, 14 src::{HasChildSource, HasSource},
15 AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId, 15 AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, FieldId, ImplId, Lookup, ModuleDefId,
16 ModuleId, StructFieldId, TraitId, VariantId, 16 ModuleId, TraitId, VariantId,
17}; 17};
18 18
19pub trait ChildBySource { 19pub trait ChildBySource {
@@ -140,7 +140,7 @@ impl ChildBySource for VariantId {
140 let arena_map = self.child_source(db); 140 let arena_map = self.child_source(db);
141 let arena_map = arena_map.as_ref(); 141 let arena_map = arena_map.as_ref();
142 for (local_id, source) in arena_map.value.iter() { 142 for (local_id, source) in arena_map.value.iter() {
143 let id = StructFieldId { parent: *self, local_id }; 143 let id = FieldId { parent: *self, local_id };
144 match source { 144 match source {
145 Either::Left(source) => { 145 Either::Left(source) => {
146 res[keys::TUPLE_FIELD].insert(arena_map.with_value(source.clone()), id) 146 res[keys::TUPLE_FIELD].insert(arena_map.with_value(source.clone()), id)
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
index 0539a77d4..b221ae1ce 100644
--- a/crates/ra_hir_def/src/docs.rs
+++ b/crates/ra_hir_def/src/docs.rs
@@ -43,7 +43,7 @@ impl Documentation {
43 let src = def_map[module.local_id].declaration_source(db)?; 43 let src = def_map[module.local_id].declaration_source(db)?;
44 docs_from_ast(&src.value) 44 docs_from_ast(&src.value)
45 } 45 }
46 AttrDefId::StructFieldId(it) => { 46 AttrDefId::FieldId(it) => {
47 let src = it.parent.child_source(db); 47 let src = it.parent.child_source(db);
48 match &src.value[it.local_id] { 48 match &src.value[it.local_id] {
49 Either::Left(_tuple) => None, 49 Either::Left(_tuple) => None,
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
diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs
index 8cd70eb9a..a7349a21d 100644
--- a/crates/ra_hir_def/src/keys.rs
+++ b/crates/ra_hir_def/src/keys.rs
@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
8 8
9use crate::{ 9use crate::{
10 dyn_map::{DynMap, Policy}, 10 dyn_map::{DynMap, Policy},
11 ConstId, EnumId, EnumVariantId, FunctionId, ImplId, StaticId, StructFieldId, StructId, TraitId, 11 ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, StaticId, StructId, TraitId,
12 TypeAliasId, TypeParamId, UnionId, 12 TypeAliasId, TypeParamId, UnionId,
13}; 13};
14 14
@@ -25,8 +25,8 @@ pub const UNION: Key<ast::UnionDef, UnionId> = Key::new();
25pub const ENUM: Key<ast::EnumDef, EnumId> = Key::new(); 25pub const ENUM: Key<ast::EnumDef, EnumId> = Key::new();
26 26
27pub const ENUM_VARIANT: Key<ast::EnumVariant, EnumVariantId> = Key::new(); 27pub const ENUM_VARIANT: Key<ast::EnumVariant, EnumVariantId> = Key::new();
28pub const TUPLE_FIELD: Key<ast::TupleFieldDef, StructFieldId> = Key::new(); 28pub const TUPLE_FIELD: Key<ast::TupleFieldDef, FieldId> = Key::new();
29pub const RECORD_FIELD: Key<ast::RecordFieldDef, StructFieldId> = Key::new(); 29pub const RECORD_FIELD: Key<ast::RecordFieldDef, FieldId> = Key::new();
30pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new(); 30pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
31 31
32pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new(); 32pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 2d27bbdf8..518772e8a 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -133,12 +133,12 @@ pub struct EnumVariantId {
133pub type LocalEnumVariantId = Idx<adt::EnumVariantData>; 133pub type LocalEnumVariantId = Idx<adt::EnumVariantData>;
134 134
135#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 135#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
136pub struct StructFieldId { 136pub struct FieldId {
137 pub parent: VariantId, 137 pub parent: VariantId,
138 pub local_id: LocalStructFieldId, 138 pub local_id: LocalFieldId,
139} 139}
140 140
141pub type LocalStructFieldId = Idx<adt::StructFieldData>; 141pub type LocalFieldId = Idx<adt::FieldData>;
142 142
143#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 143#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
144pub struct ConstId(salsa::InternId); 144pub struct ConstId(salsa::InternId);
@@ -299,7 +299,7 @@ impl From<AssocItemId> for GenericDefId {
299#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 299#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
300pub enum AttrDefId { 300pub enum AttrDefId {
301 ModuleId(ModuleId), 301 ModuleId(ModuleId),
302 StructFieldId(StructFieldId), 302 FieldId(FieldId),
303 AdtId(AdtId), 303 AdtId(AdtId),
304 FunctionId(FunctionId), 304 FunctionId(FunctionId),
305 EnumVariantId(EnumVariantId), 305 EnumVariantId(EnumVariantId),
@@ -313,7 +313,7 @@ pub enum AttrDefId {
313 313
314impl_froms!( 314impl_froms!(
315 AttrDefId: ModuleId, 315 AttrDefId: ModuleId,
316 StructFieldId, 316 FieldId,
317 AdtId(StructId, EnumId, UnionId), 317 AdtId(StructId, EnumId, UnionId),
318 EnumVariantId, 318 EnumVariantId,
319 StaticId, 319 StaticId,