aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorSeivan Heidari <[email protected]>2019-10-31 08:43:20 +0000
committerSeivan Heidari <[email protected]>2019-10-31 08:43:20 +0000
commit8edda0e7b164009d6c03bb3d4be603fb38ad2e2a (patch)
tree744cf81075d394e2f9c06afb07642a2601800dda /crates/ra_hir
parent49562d36b97ddde34cf7585a8c2e8f232519b657 (diff)
parentd067afb064a7fa67b172abf561b7d80740cd6f18 (diff)
Merge branch 'master' into feature/themes
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/Cargo.toml8
-rw-r--r--crates/ra_hir/src/adt.rs11
-rw-r--r--crates/ra_hir/src/attr.rs90
-rw-r--r--crates/ra_hir/src/code_model.rs182
-rw-r--r--crates/ra_hir/src/code_model/src.rs30
-rw-r--r--crates/ra_hir/src/db.rs94
-rw-r--r--crates/ra_hir/src/debug.rs6
-rw-r--r--crates/ra_hir/src/either.rs54
-rw-r--r--crates/ra_hir/src/expr.rs6
-rw-r--r--crates/ra_hir/src/expr/lower.rs26
-rw-r--r--crates/ra_hir/src/expr/validation.rs2
-rw-r--r--crates/ra_hir/src/from_source.rs52
-rw-r--r--crates/ra_hir/src/generics.rs20
-rw-r--r--crates/ra_hir/src/ids.rs363
-rw-r--r--crates/ra_hir/src/impl_block.rs24
-rw-r--r--crates/ra_hir/src/lang_item.rs16
-rw-r--r--crates/ra_hir/src/lib.rs40
-rw-r--r--crates/ra_hir/src/marks.rs1
-rw-r--r--crates/ra_hir/src/mock.rs1
-rw-r--r--crates/ra_hir/src/name.rs142
-rw-r--r--crates/ra_hir/src/nameres.rs51
-rw-r--r--crates/ra_hir/src/nameres/collector.rs56
-rw-r--r--crates/ra_hir/src/nameres/mod_resolution.rs87
-rw-r--r--crates/ra_hir/src/nameres/raw.rs403
-rw-r--r--crates/ra_hir/src/nameres/tests/mod_resolution.rs2
-rw-r--r--crates/ra_hir/src/path.rs417
-rw-r--r--crates/ra_hir/src/resolve.rs41
-rw-r--r--crates/ra_hir/src/source_binder.rs73
-rw-r--r--crates/ra_hir/src/source_id.rs161
-rw-r--r--crates/ra_hir/src/traits.rs7
-rw-r--r--crates/ra_hir/src/ty.rs4
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs3
-rw-r--r--crates/ra_hir/src/ty/infer.rs8
-rw-r--r--crates/ra_hir/src/ty/infer/coerce.rs3
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs5
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs6
-rw-r--r--crates/ra_hir/src/ty/lower.rs23
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs15
-rw-r--r--crates/ra_hir/src/ty/primitive.rs22
-rw-r--r--crates/ra_hir/src/ty/traits.rs6
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs157
-rw-r--r--crates/ra_hir/src/type_alias.rs5
-rw-r--r--crates/ra_hir/src/type_ref.rs162
43 files changed, 431 insertions, 2454 deletions
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index 54c09788a..5df371bc0 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -19,12 +19,14 @@ ra_cfg = { path = "../ra_cfg" }
19ra_db = { path = "../ra_db" } 19ra_db = { path = "../ra_db" }
20mbe = { path = "../ra_mbe", package = "ra_mbe" } 20mbe = { path = "../ra_mbe", package = "ra_mbe" }
21tt = { path = "../ra_tt", package = "ra_tt" } 21tt = { path = "../ra_tt", package = "ra_tt" }
22hir_expand = { path = "../ra_hir_expand", package = "ra_hir_expand" }
23hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
22test_utils = { path = "../test_utils" } 24test_utils = { path = "../test_utils" }
23ra_prof = { path = "../ra_prof" } 25ra_prof = { path = "../ra_prof" }
24 26
25chalk-solve = { git = "https://github.com/rust-lang/chalk.git" } 27chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "8314f2fcec8582a58c24b638f1a259d4145a0809" }
26chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git" } 28chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "8314f2fcec8582a58c24b638f1a259d4145a0809" }
27chalk-ir = { git = "https://github.com/rust-lang/chalk.git" } 29chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "8314f2fcec8582a58c24b638f1a259d4145a0809" }
28lalrpop-intern = "0.15.1" 30lalrpop-intern = "0.15.1"
29 31
30[dev-dependencies] 32[dev-dependencies]
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index 3e9cd3c63..4fa2062bd 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -3,13 +3,14 @@
3 3
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use hir_def::{type_ref::TypeRef, LocalEnumVariantId};
7use hir_expand::name::AsName;
6use ra_arena::{impl_arena_id, Arena, RawId}; 8use ra_arena::{impl_arena_id, Arena, RawId};
7use ra_syntax::ast::{self, NameOwner, StructKind, TypeAscriptionOwner}; 9use ra_syntax::ast::{self, NameOwner, StructKind, TypeAscriptionOwner};
8 10
9use crate::{ 11use crate::{
10 db::{AstDatabase, DefDatabase, HirDatabase}, 12 db::{AstDatabase, DefDatabase, HirDatabase},
11 type_ref::TypeRef, 13 Enum, EnumVariant, FieldSource, HasSource, Module, Name, Source, Struct, StructField,
12 AsName, Enum, EnumVariant, FieldSource, HasSource, Module, Name, Source, Struct, StructField,
13}; 14};
14 15
15impl Struct { 16impl Struct {
@@ -67,7 +68,7 @@ impl EnumVariant {
67#[derive(Debug, Clone, PartialEq, Eq)] 68#[derive(Debug, Clone, PartialEq, Eq)]
68pub struct EnumData { 69pub struct EnumData {
69 pub(crate) name: Option<Name>, 70 pub(crate) name: Option<Name>,
70 pub(crate) variants: Arena<EnumVariantId, EnumVariantData>, 71 pub(crate) variants: Arena<LocalEnumVariantId, EnumVariantData>,
71} 72}
72 73
73impl EnumData { 74impl EnumData {
@@ -84,10 +85,6 @@ impl EnumData {
84 } 85 }
85} 86}
86 87
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
88pub(crate) struct EnumVariantId(RawId);
89impl_arena_id!(EnumVariantId);
90
91#[derive(Debug, Clone, PartialEq, Eq)] 88#[derive(Debug, Clone, PartialEq, Eq)]
92pub(crate) struct EnumVariantData { 89pub(crate) struct EnumVariantData {
93 pub(crate) name: Option<Name>, 90 pub(crate) name: Option<Name>,
diff --git a/crates/ra_hir/src/attr.rs b/crates/ra_hir/src/attr.rs
deleted file mode 100644
index bd159a566..000000000
--- a/crates/ra_hir/src/attr.rs
+++ /dev/null
@@ -1,90 +0,0 @@
1//! A higher level attributes based on TokenTree, with also some shortcuts.
2
3use std::sync::Arc;
4
5use mbe::ast_to_token_tree;
6use ra_cfg::CfgOptions;
7use ra_syntax::{
8 ast::{self, AstNode, AttrsOwner},
9 SmolStr,
10};
11use tt::Subtree;
12
13use crate::{db::AstDatabase, path::Path, HirFileId, Source};
14
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub(crate) struct Attr {
17 pub(crate) path: Path,
18 pub(crate) input: Option<AttrInput>,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub enum AttrInput {
23 Literal(SmolStr),
24 TokenTree(Subtree),
25}
26
27impl Attr {
28 pub(crate) fn from_src(
29 Source { file_id, ast }: Source<ast::Attr>,
30 db: &impl AstDatabase,
31 ) -> Option<Attr> {
32 let path = Path::from_src(Source { file_id, ast: ast.path()? }, db)?;
33 let input = match ast.input() {
34 None => None,
35 Some(ast::AttrInput::Literal(lit)) => {
36 // FIXME: escape? raw string?
37 let value = lit.syntax().first_token()?.text().trim_matches('"').into();
38 Some(AttrInput::Literal(value))
39 }
40 Some(ast::AttrInput::TokenTree(tt)) => {
41 Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0))
42 }
43 };
44
45 Some(Attr { path, input })
46 }
47
48 pub(crate) fn from_attrs_owner(
49 file_id: HirFileId,
50 owner: &dyn AttrsOwner,
51 db: &impl AstDatabase,
52 ) -> Option<Arc<[Attr]>> {
53 let mut attrs = owner.attrs().peekable();
54 if attrs.peek().is_none() {
55 // Avoid heap allocation
56 return None;
57 }
58 Some(attrs.flat_map(|ast| Attr::from_src(Source { file_id, ast }, db)).collect())
59 }
60
61 pub(crate) fn is_simple_atom(&self, name: &str) -> bool {
62 // FIXME: Avoid cloning
63 self.path.as_ident().map_or(false, |s| s.to_string() == name)
64 }
65
66 // FIXME: handle cfg_attr :-)
67 pub(crate) fn as_cfg(&self) -> Option<&Subtree> {
68 if !self.is_simple_atom("cfg") {
69 return None;
70 }
71 match &self.input {
72 Some(AttrInput::TokenTree(subtree)) => Some(subtree),
73 _ => None,
74 }
75 }
76
77 pub(crate) fn as_path(&self) -> Option<&SmolStr> {
78 if !self.is_simple_atom("path") {
79 return None;
80 }
81 match &self.input {
82 Some(AttrInput::Literal(it)) => Some(it),
83 _ => None,
84 }
85 }
86
87 pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> Option<bool> {
88 cfg_options.is_cfg_enabled(self.as_cfg()?)
89 }
90}
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 8eb3c577d..b32aa145e 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -5,11 +5,17 @@ pub(crate) mod docs;
5 5
6use std::sync::Arc; 6use std::sync::Arc;
7 7
8use ra_db::{CrateId, Edition, FileId}; 8use hir_def::{
9 builtin_type::BuiltinType,
10 type_ref::{Mutability, TypeRef},
11 CrateModuleId, LocalEnumVariantId, ModuleId,
12};
13use hir_expand::name::{self, AsName};
14use ra_db::{CrateId, Edition};
9use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 15use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
10 16
11use crate::{ 17use crate::{
12 adt::{EnumVariantId, StructFieldId, VariantDef}, 18 adt::{StructFieldId, VariantDef},
13 db::{AstDatabase, DefDatabase, HirDatabase}, 19 db::{AstDatabase, DefDatabase, HirDatabase},
14 diagnostics::DiagnosticSink, 20 diagnostics::DiagnosticSink,
15 expr::{validation::ExprValidator, Body, BodySourceMap}, 21 expr::{validation::ExprValidator, Body, BodySourceMap},
@@ -19,20 +25,11 @@ use crate::{
19 TypeAliasId, 25 TypeAliasId,
20 }, 26 },
21 impl_block::ImplBlock, 27 impl_block::ImplBlock,
22 name::{ 28 nameres::{ImportId, ModuleScope, Namespace},
23 BOOL, CHAR, F32, F64, I128, I16, I32, I64, I8, ISIZE, SELF_TYPE, STR, U128, U16, U32, U64,
24 U8, USIZE,
25 },
26 nameres::{CrateModuleId, ImportId, ModuleScope, Namespace},
27 resolve::{Resolver, Scope, TypeNs}, 29 resolve::{Resolver, Scope, TypeNs},
28 traits::TraitData, 30 traits::TraitData,
29 ty::{ 31 ty::{InferenceResult, TraitRef},
30 primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness}, 32 Either, HasSource, Name, Ty,
31 InferenceResult, TraitRef,
32 },
33 type_ref::Mutability,
34 type_ref::TypeRef,
35 AsName, AstId, Either, HasSource, Name, Ty,
36}; 33};
37 34
38/// hir::Crate describes a single crate. It's the main interface with which 35/// hir::Crate describes a single crate. It's the main interface with which
@@ -67,8 +64,7 @@ impl Crate {
67 64
68 pub fn root_module(self, db: &impl DefDatabase) -> Option<Module> { 65 pub fn root_module(self, db: &impl DefDatabase) -> Option<Module> {
69 let module_id = db.crate_def_map(self).root(); 66 let module_id = db.crate_def_map(self).root();
70 let module = Module { krate: self, module_id }; 67 Some(Module::new(self, module_id))
71 Some(module)
72 } 68 }
73 69
74 pub fn edition(self, db: &impl DefDatabase) -> Edition { 70 pub fn edition(self, db: &impl DefDatabase) -> Edition {
@@ -83,43 +79,7 @@ impl Crate {
83 79
84#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 80#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
85pub struct Module { 81pub struct Module {
86 pub(crate) krate: Crate, 82 pub(crate) id: ModuleId,
87 pub(crate) module_id: CrateModuleId,
88}
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
91pub enum BuiltinType {
92 Char,
93 Bool,
94 Str,
95 Int(IntTy),
96 Float(FloatTy),
97}
98
99impl BuiltinType {
100 #[rustfmt::skip]
101 pub(crate) const ALL: &'static [(Name, BuiltinType)] = &[
102 (CHAR, BuiltinType::Char),
103 (BOOL, BuiltinType::Bool),
104 (STR, BuiltinType::Str),
105
106 (ISIZE, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::Xsize })),
107 (I8, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X8 })),
108 (I16, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X16 })),
109 (I32, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X32 })),
110 (I64, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X64 })),
111 (I128, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X128 })),
112
113 (USIZE, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize })),
114 (U8, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X8 })),
115 (U16, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X16 })),
116 (U32, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X32 })),
117 (U64, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X64 })),
118 (U128, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X128 })),
119
120 (F32, BuiltinType::Float(FloatTy { bitness: FloatBitness::X32 })),
121 (F64, BuiltinType::Float(FloatTy { bitness: FloatBitness::X64 })),
122 ];
123} 83}
124 84
125/// The defs which can be visible in the module. 85/// The defs which can be visible in the module.
@@ -148,39 +108,19 @@ impl_froms!(
148 BuiltinType 108 BuiltinType
149); 109);
150 110
151pub enum ModuleSource { 111pub use hir_def::ModuleSource;
152 SourceFile(ast::SourceFile),
153 Module(ast::Module),
154}
155 112
156impl ModuleSource { 113impl Module {
157 pub(crate) fn new( 114 pub(crate) fn new(krate: Crate, crate_module_id: CrateModuleId) -> Module {
158 db: &(impl DefDatabase + AstDatabase), 115 Module { id: ModuleId { krate: krate.crate_id, module_id: crate_module_id } }
159 file_id: Option<FileId>,
160 decl_id: Option<AstId<ast::Module>>,
161 ) -> ModuleSource {
162 match (file_id, decl_id) {
163 (Some(file_id), _) => {
164 let source_file = db.parse(file_id).tree();
165 ModuleSource::SourceFile(source_file)
166 }
167 (None, Some(item_id)) => {
168 let module = item_id.to_node(db);
169 assert!(module.item_list().is_some(), "expected inline module");
170 ModuleSource::Module(module)
171 }
172 (None, None) => panic!(),
173 }
174 } 116 }
175}
176 117
177impl Module {
178 /// Name of this module. 118 /// Name of this module.
179 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 119 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
180 let def_map = db.crate_def_map(self.krate); 120 let def_map = db.crate_def_map(self.krate());
181 let parent = def_map[self.module_id].parent?; 121 let parent = def_map[self.id.module_id].parent?;
182 def_map[parent].children.iter().find_map(|(name, module_id)| { 122 def_map[parent].children.iter().find_map(|(name, module_id)| {
183 if *module_id == self.module_id { 123 if *module_id == self.id.module_id {
184 Some(name.clone()) 124 Some(name.clone())
185 } else { 125 } else {
186 None 126 None
@@ -200,29 +140,29 @@ impl Module {
200 } 140 }
201 141
202 /// Returns the crate this module is part of. 142 /// Returns the crate this module is part of.
203 pub fn krate(self, _db: &impl DefDatabase) -> Option<Crate> { 143 pub fn krate(self) -> Crate {
204 Some(self.krate) 144 Crate { crate_id: self.id.krate }
205 } 145 }
206 146
207 /// Topmost parent of this module. Every module has a `crate_root`, but some 147 /// Topmost parent of this module. Every module has a `crate_root`, but some
208 /// might be missing `krate`. This can happen if a module's file is not included 148 /// might be missing `krate`. This can happen if a module's file is not included
209 /// in the module tree of any target in `Cargo.toml`. 149 /// in the module tree of any target in `Cargo.toml`.
210 pub fn crate_root(self, db: &impl DefDatabase) -> Module { 150 pub fn crate_root(self, db: &impl DefDatabase) -> Module {
211 let def_map = db.crate_def_map(self.krate); 151 let def_map = db.crate_def_map(self.krate());
212 self.with_module_id(def_map.root()) 152 self.with_module_id(def_map.root())
213 } 153 }
214 154
215 /// Finds a child module with the specified name. 155 /// Finds a child module with the specified name.
216 pub fn child(self, db: &impl HirDatabase, name: &Name) -> Option<Module> { 156 pub fn child(self, db: &impl HirDatabase, name: &Name) -> Option<Module> {
217 let def_map = db.crate_def_map(self.krate); 157 let def_map = db.crate_def_map(self.krate());
218 let child_id = def_map[self.module_id].children.get(name)?; 158 let child_id = def_map[self.id.module_id].children.get(name)?;
219 Some(self.with_module_id(*child_id)) 159 Some(self.with_module_id(*child_id))
220 } 160 }
221 161
222 /// Iterates over all child modules. 162 /// Iterates over all child modules.
223 pub fn children(self, db: &impl DefDatabase) -> impl Iterator<Item = Module> { 163 pub fn children(self, db: &impl DefDatabase) -> impl Iterator<Item = Module> {
224 let def_map = db.crate_def_map(self.krate); 164 let def_map = db.crate_def_map(self.krate());
225 let children = def_map[self.module_id] 165 let children = def_map[self.id.module_id]
226 .children 166 .children
227 .iter() 167 .iter()
228 .map(|(_, module_id)| self.with_module_id(*module_id)) 168 .map(|(_, module_id)| self.with_module_id(*module_id))
@@ -232,8 +172,8 @@ impl Module {
232 172
233 /// Finds a parent module. 173 /// Finds a parent module.
234 pub fn parent(self, db: &impl DefDatabase) -> Option<Module> { 174 pub fn parent(self, db: &impl DefDatabase) -> Option<Module> {
235 let def_map = db.crate_def_map(self.krate); 175 let def_map = db.crate_def_map(self.krate());
236 let parent_id = def_map[self.module_id].parent?; 176 let parent_id = def_map[self.id.module_id].parent?;
237 Some(self.with_module_id(parent_id)) 177 Some(self.with_module_id(parent_id))
238 } 178 }
239 179
@@ -249,11 +189,11 @@ impl Module {
249 189
250 /// Returns a `ModuleScope`: a set of items, visible in this module. 190 /// Returns a `ModuleScope`: a set of items, visible in this module.
251 pub fn scope(self, db: &impl HirDatabase) -> ModuleScope { 191 pub fn scope(self, db: &impl HirDatabase) -> ModuleScope {
252 db.crate_def_map(self.krate)[self.module_id].scope.clone() 192 db.crate_def_map(self.krate())[self.id.module_id].scope.clone()
253 } 193 }
254 194
255 pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { 195 pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) {
256 db.crate_def_map(self.krate).add_diagnostics(db, self.module_id, sink); 196 db.crate_def_map(self.krate()).add_diagnostics(db, self.id.module_id, sink);
257 for decl in self.declarations(db) { 197 for decl in self.declarations(db) {
258 match decl { 198 match decl {
259 crate::ModuleDef::Function(f) => f.diagnostics(db, sink), 199 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
@@ -277,13 +217,13 @@ impl Module {
277 } 217 }
278 218
279 pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver { 219 pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver {
280 let def_map = db.crate_def_map(self.krate); 220 let def_map = db.crate_def_map(self.krate());
281 Resolver::default().push_module_scope(def_map, self.module_id) 221 Resolver::default().push_module_scope(def_map, self.id.module_id)
282 } 222 }
283 223
284 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> { 224 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> {
285 let def_map = db.crate_def_map(self.krate); 225 let def_map = db.crate_def_map(self.krate());
286 def_map[self.module_id] 226 def_map[self.id.module_id]
287 .scope 227 .scope
288 .entries() 228 .entries()
289 .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None }) 229 .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
@@ -303,7 +243,7 @@ impl Module {
303 } 243 }
304 244
305 fn with_module_id(self, module_id: CrateModuleId) -> Module { 245 fn with_module_id(self, module_id: CrateModuleId) -> Module {
306 Module { module_id, krate: self.krate } 246 Module::new(self.krate(), module_id)
307 } 247 }
308} 248}
309 249
@@ -340,11 +280,11 @@ pub struct Struct {
340 280
341impl Struct { 281impl Struct {
342 pub fn module(self, db: &impl DefDatabase) -> Module { 282 pub fn module(self, db: &impl DefDatabase) -> Module {
343 self.id.module(db) 283 Module { id: self.id.module(db) }
344 } 284 }
345 285
346 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 286 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
347 self.module(db).krate(db) 287 Some(self.module(db).krate())
348 } 288 }
349 289
350 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 290 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
@@ -402,7 +342,7 @@ impl Union {
402 } 342 }
403 343
404 pub fn module(self, db: &impl HirDatabase) -> Module { 344 pub fn module(self, db: &impl HirDatabase) -> Module {
405 self.id.module(db) 345 Module { id: self.id.module(db) }
406 } 346 }
407 347
408 pub fn ty(self, db: &impl HirDatabase) -> Ty { 348 pub fn ty(self, db: &impl HirDatabase) -> Ty {
@@ -428,11 +368,11 @@ pub struct Enum {
428 368
429impl Enum { 369impl Enum {
430 pub fn module(self, db: &impl DefDatabase) -> Module { 370 pub fn module(self, db: &impl DefDatabase) -> Module {
431 self.id.module(db) 371 Module { id: self.id.module(db) }
432 } 372 }
433 373
434 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 374 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
435 self.module(db).krate(db) 375 Some(self.module(db).krate())
436 } 376 }
437 377
438 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 378 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
@@ -470,7 +410,7 @@ impl Enum {
470#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 410#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
471pub struct EnumVariant { 411pub struct EnumVariant {
472 pub(crate) parent: Enum, 412 pub(crate) parent: Enum,
473 pub(crate) id: EnumVariantId, 413 pub(crate) id: LocalEnumVariantId,
474} 414}
475 415
476impl EnumVariant { 416impl EnumVariant {
@@ -523,12 +463,14 @@ impl Adt {
523 } 463 }
524 464
525 pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> { 465 pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
526 match self { 466 Some(
527 Adt::Struct(s) => s.module(db), 467 match self {
528 Adt::Union(s) => s.module(db), 468 Adt::Struct(s) => s.module(db),
529 Adt::Enum(e) => e.module(db), 469 Adt::Union(s) => s.module(db),
530 } 470 Adt::Enum(e) => e.module(db),
531 .krate(db) 471 }
472 .krate(),
473 )
532 } 474 }
533 475
534 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { 476 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
@@ -643,7 +585,7 @@ impl FnData {
643 let self_type = if let Some(type_ref) = self_param.ascribed_type() { 585 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
644 TypeRef::from_ast(type_ref) 586 TypeRef::from_ast(type_ref)
645 } else { 587 } else {
646 let self_type = TypeRef::Path(SELF_TYPE.into()); 588 let self_type = TypeRef::Path(name::SELF_TYPE.into());
647 match self_param.kind() { 589 match self_param.kind() {
648 ast::SelfParamKind::Owned => self_type, 590 ast::SelfParamKind::Owned => self_type,
649 ast::SelfParamKind::Ref => { 591 ast::SelfParamKind::Ref => {
@@ -692,11 +634,11 @@ impl FnData {
692 634
693impl Function { 635impl Function {
694 pub fn module(self, db: &impl DefDatabase) -> Module { 636 pub fn module(self, db: &impl DefDatabase) -> Module {
695 self.id.module(db) 637 Module { id: self.id.module(db) }
696 } 638 }
697 639
698 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 640 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
699 self.module(db).krate(db) 641 Some(self.module(db).krate())
700 } 642 }
701 643
702 pub fn name(self, db: &impl HirDatabase) -> Name { 644 pub fn name(self, db: &impl HirDatabase) -> Name {
@@ -770,11 +712,11 @@ pub struct Const {
770 712
771impl Const { 713impl Const {
772 pub fn module(self, db: &impl DefDatabase) -> Module { 714 pub fn module(self, db: &impl DefDatabase) -> Module {
773 self.id.module(db) 715 Module { id: self.id.module(db) }
774 } 716 }
775 717
776 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 718 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
777 self.module(db).krate(db) 719 Some(self.module(db).krate())
778 } 720 }
779 721
780 pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> { 722 pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> {
@@ -867,11 +809,11 @@ pub struct Static {
867 809
868impl Static { 810impl Static {
869 pub fn module(self, db: &impl DefDatabase) -> Module { 811 pub fn module(self, db: &impl DefDatabase) -> Module {
870 self.id.module(db) 812 Module { id: self.id.module(db) }
871 } 813 }
872 814
873 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 815 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
874 self.module(db).krate(db) 816 Some(self.module(db).krate())
875 } 817 }
876 818
877 pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> { 819 pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> {
@@ -896,7 +838,7 @@ pub struct Trait {
896 838
897impl Trait { 839impl Trait {
898 pub fn module(self, db: &impl DefDatabase) -> Module { 840 pub fn module(self, db: &impl DefDatabase) -> Module {
899 self.id.module(db) 841 Module { id: self.id.module(db) }
900 } 842 }
901 843
902 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 844 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
@@ -917,9 +859,7 @@ impl Trait {
917 .where_predicates 859 .where_predicates
918 .iter() 860 .iter()
919 .filter_map(|pred| match &pred.type_ref { 861 .filter_map(|pred| match &pred.type_ref {
920 TypeRef::Path(p) if p.as_ident() == Some(&crate::name::SELF_TYPE) => { 862 TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(),
921 pred.bound.as_path()
922 }
923 _ => None, 863 _ => None,
924 }) 864 })
925 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) { 865 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) {
@@ -998,11 +938,11 @@ pub struct TypeAlias {
998 938
999impl TypeAlias { 939impl TypeAlias {
1000 pub fn module(self, db: &impl DefDatabase) -> Module { 940 pub fn module(self, db: &impl DefDatabase) -> Module {
1001 self.id.module(db) 941 Module { id: self.id.module(db) }
1002 } 942 }
1003 943
1004 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 944 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
1005 self.module(db).krate(db) 945 Some(self.module(db).krate())
1006 } 946 }
1007 947
1008 /// The containing impl block, if this is a method. 948 /// The containing impl block, if this is a method.
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index fdae26906..5c7f61eef 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -1,9 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use ra_syntax::{ 3use ra_syntax::ast::{self, AstNode};
4 ast::{self, AstNode},
5 SyntaxNode,
6};
7 4
8use crate::{ 5use crate::{
9 db::{AstDatabase, DefDatabase, HirDatabase}, 6 db::{AstDatabase, DefDatabase, HirDatabase},
@@ -12,34 +9,21 @@ use crate::{
12 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, 9 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
13}; 10};
14 11
15#[derive(Debug, PartialEq, Eq, Clone, Copy)] 12pub use hir_def::Source;
16pub struct Source<T> {
17 pub file_id: HirFileId,
18 pub ast: T,
19}
20 13
21pub trait HasSource { 14pub trait HasSource {
22 type Ast; 15 type Ast;
23 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<Self::Ast>; 16 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<Self::Ast>;
24} 17}
25 18
26impl<T> Source<T> {
27 pub(crate) fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> {
28 Source { file_id: self.file_id, ast: f(self.ast) }
29 }
30 pub(crate) fn file_syntax(&self, db: &impl AstDatabase) -> SyntaxNode {
31 db.parse_or_expand(self.file_id).expect("source created from invalid file")
32 }
33}
34
35/// NB: Module is !HasSource, because it has two source nodes at the same time: 19/// NB: Module is !HasSource, because it has two source nodes at the same time:
36/// definition and declaration. 20/// definition and declaration.
37impl Module { 21impl Module {
38 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. 22 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
39 pub fn definition_source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ModuleSource> { 23 pub fn definition_source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ModuleSource> {
40 let def_map = db.crate_def_map(self.krate); 24 let def_map = db.crate_def_map(self.krate());
41 let decl_id = def_map[self.module_id].declaration; 25 let decl_id = def_map[self.id.module_id].declaration;
42 let file_id = def_map[self.module_id].definition; 26 let file_id = def_map[self.id.module_id].definition;
43 let ast = ModuleSource::new(db, file_id, decl_id); 27 let ast = ModuleSource::new(db, file_id, decl_id);
44 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id()); 28 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id());
45 Source { file_id, ast } 29 Source { file_id, ast }
@@ -51,8 +35,8 @@ impl Module {
51 self, 35 self,
52 db: &(impl DefDatabase + AstDatabase), 36 db: &(impl DefDatabase + AstDatabase),
53 ) -> Option<Source<ast::Module>> { 37 ) -> Option<Source<ast::Module>> {
54 let def_map = db.crate_def_map(self.krate); 38 let def_map = db.crate_def_map(self.krate());
55 let decl = def_map[self.module_id].declaration?; 39 let decl = def_map[self.id.module_id].declaration?;
56 let ast = decl.to_node(db); 40 let ast = decl.to_node(db);
57 Some(Source { file_id: decl.file_id(), ast }) 41 Some(Source { file_id: decl.file_id(), ast })
58 } 42 }
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 489a3b19c..ebfd970eb 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -2,8 +2,8 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use ra_db::{salsa, SourceDatabase}; 5use ra_db::salsa;
6use ra_syntax::{ast, Parse, SmolStr, SyntaxNode}; 6use ra_syntax::SmolStr;
7 7
8use crate::{ 8use crate::{
9 adt::{EnumData, StructData}, 9 adt::{EnumData, StructData},
@@ -12,81 +12,30 @@ use crate::{
12 ids, 12 ids,
13 impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks}, 13 impl_block::{ImplBlock, ImplSourceMap, ModuleImplBlocks},
14 lang_item::{LangItemTarget, LangItems}, 14 lang_item::{LangItemTarget, LangItems},
15 nameres::{CrateDefMap, ImportSourceMap, Namespace, RawItems}, 15 nameres::{CrateDefMap, Namespace},
16 traits::TraitData, 16 traits::TraitData,
17 ty::{ 17 ty::{
18 method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate, 18 method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate,
19 InferenceResult, Substs, Ty, TypableDef, TypeCtor, 19 InferenceResult, Substs, Ty, TypableDef, TypeCtor,
20 }, 20 },
21 type_alias::TypeAliasData, 21 type_alias::TypeAliasData,
22 AstIdMap, Const, ConstData, Crate, DefWithBody, Enum, ErasedFileAstId, ExprScopes, FnData, 22 Const, ConstData, Crate, DefWithBody, Enum, ExprScopes, FnData, Function, Module, Static,
23 Function, HirFileId, MacroCallLoc, MacroDefId, Module, Static, Struct, StructField, Trait, 23 Struct, StructField, Trait, TypeAlias,
24 TypeAlias,
25}; 24};
26 25
27/// We store all interned things in the single QueryGroup. 26pub use hir_def::db::{
28/// 27 DefDatabase2, DefDatabase2Storage, InternDatabase, InternDatabaseStorage, RawItemsQuery,
29/// This is done mainly to allow both "volatile" `AstDatabase` and "stable" 28 RawItemsWithSourceMapQuery,
30/// `DefDatabase` to access macros, without adding hard dependencies between the 29};
31/// two. 30pub use hir_expand::db::{
32#[salsa::query_group(InternDatabaseStorage)] 31 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
33pub trait InternDatabase: SourceDatabase { 32 ParseMacroQuery,
34 #[salsa::interned] 33};
35 fn intern_macro(&self, macro_call: MacroCallLoc) -> ids::MacroCallId;
36 #[salsa::interned]
37 fn intern_function(&self, loc: ids::ItemLoc<ast::FnDef>) -> ids::FunctionId;
38 #[salsa::interned]
39 fn intern_struct(&self, loc: ids::ItemLoc<ast::StructDef>) -> ids::StructId;
40 #[salsa::interned]
41 fn intern_enum(&self, loc: ids::ItemLoc<ast::EnumDef>) -> ids::EnumId;
42 #[salsa::interned]
43 fn intern_const(&self, loc: ids::ItemLoc<ast::ConstDef>) -> ids::ConstId;
44 #[salsa::interned]
45 fn intern_static(&self, loc: ids::ItemLoc<ast::StaticDef>) -> ids::StaticId;
46 #[salsa::interned]
47 fn intern_trait(&self, loc: ids::ItemLoc<ast::TraitDef>) -> ids::TraitId;
48 #[salsa::interned]
49 fn intern_type_alias(&self, loc: ids::ItemLoc<ast::TypeAliasDef>) -> ids::TypeAliasId;
50
51 // Interned IDs for Chalk integration
52 #[salsa::interned]
53 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId;
54 #[salsa::interned]
55 fn intern_impl(&self, impl_: Impl) -> ids::GlobalImplId;
56}
57
58/// This database has access to source code, so queries here are not really
59/// incremental.
60#[salsa::query_group(AstDatabaseStorage)]
61pub trait AstDatabase: InternDatabase {
62 #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)]
63 fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
64
65 #[salsa::transparent]
66 #[salsa::invoke(crate::source_id::AstIdMap::file_item_query)]
67 fn ast_id_to_node(&self, file_id: HirFileId, ast_id: ErasedFileAstId) -> SyntaxNode;
68
69 #[salsa::transparent]
70 #[salsa::invoke(crate::ids::HirFileId::parse_or_expand_query)]
71 fn parse_or_expand(&self, file_id: HirFileId) -> Option<SyntaxNode>;
72
73 #[salsa::invoke(crate::ids::HirFileId::parse_macro_query)]
74 fn parse_macro(&self, macro_file: ids::MacroFile) -> Option<Parse<SyntaxNode>>;
75
76 #[salsa::invoke(crate::ids::macro_def_query)]
77 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>;
78
79 #[salsa::invoke(crate::ids::macro_arg_query)]
80 fn macro_arg(&self, macro_call: ids::MacroCallId) -> Option<Arc<tt::Subtree>>;
81
82 #[salsa::invoke(crate::ids::macro_expand_query)]
83 fn macro_expand(&self, macro_call: ids::MacroCallId) -> Result<Arc<tt::Subtree>, String>;
84}
85 34
86// This database uses `AstDatabase` internally, 35// This database uses `AstDatabase` internally,
87#[salsa::query_group(DefDatabaseStorage)] 36#[salsa::query_group(DefDatabaseStorage)]
88#[salsa::requires(AstDatabase)] 37#[salsa::requires(AstDatabase)]
89pub trait DefDatabase: InternDatabase + HirDebugDatabase { 38pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
90 #[salsa::invoke(crate::adt::StructData::struct_data_query)] 39 #[salsa::invoke(crate::adt::StructData::struct_data_query)]
91 fn struct_data(&self, s: Struct) -> Arc<StructData>; 40 fn struct_data(&self, s: Struct) -> Arc<StructData>;
92 41
@@ -99,15 +48,6 @@ pub trait DefDatabase: InternDatabase + HirDebugDatabase {
99 #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)] 48 #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)]
100 fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex; 49 fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex;
101 50
102 #[salsa::invoke(RawItems::raw_items_with_source_map_query)]
103 fn raw_items_with_source_map(
104 &self,
105 file_id: HirFileId,
106 ) -> (Arc<RawItems>, Arc<ImportSourceMap>);
107
108 #[salsa::invoke(RawItems::raw_items_query)]
109 fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>;
110
111 #[salsa::invoke(CrateDefMap::crate_def_map_query)] 51 #[salsa::invoke(CrateDefMap::crate_def_map_query)]
112 fn crate_def_map(&self, krate: Crate) -> Arc<CrateDefMap>; 52 fn crate_def_map(&self, krate: Crate) -> Arc<CrateDefMap>;
113 53
@@ -202,6 +142,12 @@ pub trait HirDatabase: DefDatabase + AstDatabase {
202 #[salsa::invoke(crate::ty::traits::trait_solver_query)] 142 #[salsa::invoke(crate::ty::traits::trait_solver_query)]
203 fn trait_solver(&self, krate: Crate) -> crate::ty::traits::TraitSolver; 143 fn trait_solver(&self, krate: Crate) -> crate::ty::traits::TraitSolver;
204 144
145 // Interned IDs for Chalk integration
146 #[salsa::interned]
147 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId;
148 #[salsa::interned]
149 fn intern_impl(&self, impl_: Impl) -> ids::GlobalImplId;
150
205 #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)] 151 #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)]
206 fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>; 152 fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>;
207 153
diff --git a/crates/ra_hir/src/debug.rs b/crates/ra_hir/src/debug.rs
index 48b69000b..4f3e922c3 100644
--- a/crates/ra_hir/src/debug.rs
+++ b/crates/ra_hir/src/debug.rs
@@ -36,12 +36,6 @@ impl Module {
36 } 36 }
37} 37}
38 38
39impl HirFileId {
40 pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ {
41 debug_fn(move |fmt| db.debug_hir_file_id(self, fmt))
42 }
43}
44
45pub trait HirDebugHelper: HirDatabase { 39pub trait HirDebugHelper: HirDatabase {
46 fn crate_name(&self, _krate: CrateId) -> Option<String> { 40 fn crate_name(&self, _krate: CrateId) -> Option<String> {
47 None 41 None
diff --git a/crates/ra_hir/src/either.rs b/crates/ra_hir/src/either.rs
deleted file mode 100644
index 83583ef8b..000000000
--- a/crates/ra_hir/src/either.rs
+++ /dev/null
@@ -1,54 +0,0 @@
1//! FIXME: write short doc here
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
4pub enum Either<A, B> {
5 A(A),
6 B(B),
7}
8
9impl<A, B> Either<A, B> {
10 pub fn either<R, F1, F2>(self, f1: F1, f2: F2) -> R
11 where
12 F1: FnOnce(A) -> R,
13 F2: FnOnce(B) -> R,
14 {
15 match self {
16 Either::A(a) => f1(a),
17 Either::B(b) => f2(b),
18 }
19 }
20 pub fn map<U, V, F1, F2>(self, f1: F1, f2: F2) -> Either<U, V>
21 where
22 F1: FnOnce(A) -> U,
23 F2: FnOnce(B) -> V,
24 {
25 match self {
26 Either::A(a) => Either::A(f1(a)),
27 Either::B(b) => Either::B(f2(b)),
28 }
29 }
30 pub fn map_a<U, F>(self, f: F) -> Either<U, B>
31 where
32 F: FnOnce(A) -> U,
33 {
34 self.map(f, |it| it)
35 }
36 pub fn a(self) -> Option<A> {
37 match self {
38 Either::A(it) => Some(it),
39 Either::B(_) => None,
40 }
41 }
42 pub fn b(self) -> Option<B> {
43 match self {
44 Either::A(_) => None,
45 Either::B(it) => Some(it),
46 }
47 }
48 pub fn as_ref(&self) -> Either<&A, &B> {
49 match self {
50 Either::A(it) => Either::A(it),
51 Either::B(it) => Either::B(it),
52 }
53 }
54}
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index d238741ba..6e23197a4 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -6,15 +6,17 @@ pub(crate) mod validation;
6 6
7use std::{ops::Index, sync::Arc}; 7use std::{ops::Index, sync::Arc};
8 8
9use hir_def::{
10 path::GenericArgs,
11 type_ref::{Mutability, TypeRef},
12};
9use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 13use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
10use ra_syntax::{ast, AstPtr}; 14use ra_syntax::{ast, AstPtr};
11use rustc_hash::FxHashMap; 15use rustc_hash::FxHashMap;
12 16
13use crate::{ 17use crate::{
14 db::HirDatabase, 18 db::HirDatabase,
15 path::GenericArgs,
16 ty::primitive::{UncertainFloatTy, UncertainIntTy}, 19 ty::primitive::{UncertainFloatTy, UncertainIntTy},
17 type_ref::{Mutability, TypeRef},
18 DefWithBody, Either, HasSource, Name, Path, Resolver, Source, 20 DefWithBody, Either, HasSource, Name, Path, Resolver, Source,
19}; 21};
20 22
diff --git a/crates/ra_hir/src/expr/lower.rs b/crates/ra_hir/src/expr/lower.rs
index 50ea429ea..6463dd65e 100644
--- a/crates/ra_hir/src/expr/lower.rs
+++ b/crates/ra_hir/src/expr/lower.rs
@@ -1,5 +1,10 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir_def::{path::GenericArgs, type_ref::TypeRef};
4use hir_expand::{
5 hygiene::Hygiene,
6 name::{self, AsName, Name},
7};
3use ra_arena::Arena; 8use ra_arena::Arena;
4use ra_syntax::{ 9use ra_syntax::{
5 ast::{ 10 ast::{
@@ -12,11 +17,8 @@ use test_utils::tested_by;
12 17
13use crate::{ 18use crate::{
14 db::HirDatabase, 19 db::HirDatabase,
15 name::{AsName, Name, SELF_PARAM},
16 path::GenericArgs,
17 ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy}, 20 ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy},
18 type_ref::TypeRef, 21 AstId, DefWithBody, Either, HirFileId, MacroCallLoc, MacroFileKind, Mutability, Path, Resolver,
19 DefWithBody, Either, HirFileId, MacroCallLoc, MacroFileKind, Mutability, Path, Resolver,
20 Source, 22 Source,
21}; 23};
22 24
@@ -78,7 +80,7 @@ where
78 let ptr = AstPtr::new(&self_param); 80 let ptr = AstPtr::new(&self_param);
79 let param_pat = self.alloc_pat( 81 let param_pat = self.alloc_pat(
80 Pat::Bind { 82 Pat::Bind {
81 name: SELF_PARAM, 83 name: name::SELF_PARAM,
82 mode: BindingAnnotation::Unannotated, 84 mode: BindingAnnotation::Unannotated,
83 subpat: None, 85 subpat: None,
84 }, 86 },
@@ -458,15 +460,14 @@ where
458 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 460 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
459 ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 461 ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
460 ast::Expr::MacroCall(e) => { 462 ast::Expr::MacroCall(e) => {
461 let ast_id = self 463 let ast_id = AstId::new(
462 .db 464 self.current_file_id,
463 .ast_id_map(self.current_file_id) 465 self.db.ast_id_map(self.current_file_id).ast_id(&e),
464 .ast_id(&e) 466 );
465 .with_file_id(self.current_file_id);
466 467
467 if let Some(path) = e.path().and_then(|path| self.parse_path(path)) { 468 if let Some(path) = e.path().and_then(|path| self.parse_path(path)) {
468 if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) { 469 if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) {
469 let call_id = MacroCallLoc { def: def.id, ast_id }.id(self.db); 470 let call_id = self.db.intern_macro(MacroCallLoc { def: def.id, ast_id });
470 let file_id = call_id.as_file(MacroFileKind::Expr); 471 let file_id = call_id.as_file(MacroFileKind::Expr);
471 if let Some(node) = self.db.parse_or_expand(file_id) { 472 if let Some(node) = self.db.parse_or_expand(file_id) {
472 if let Some(expr) = ast::Expr::cast(node) { 473 if let Some(expr) = ast::Expr::cast(node) {
@@ -596,7 +597,8 @@ where
596 } 597 }
597 598
598 fn parse_path(&mut self, path: ast::Path) -> Option<Path> { 599 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
599 Path::from_src(Source { ast: path, file_id: self.current_file_id }, self.db) 600 let hygiene = Hygiene::new(self.db, self.current_file_id);
601 Path::from_src(path, &hygiene)
600 } 602 }
601} 603}
602 604
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs
index 1aa853c3e..c685edda1 100644
--- a/crates/ra_hir/src/expr/validation.rs
+++ b/crates/ra_hir/src/expr/validation.rs
@@ -2,6 +2,7 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::path::known;
5use ra_syntax::ast; 6use ra_syntax::ast;
6use rustc_hash::FxHashSet; 7use rustc_hash::FxHashSet;
7 8
@@ -9,7 +10,6 @@ use crate::{
9 db::HirDatabase, 10 db::HirDatabase,
10 diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr}, 11 diagnostics::{DiagnosticSink, MissingFields, MissingOkInTailExpr},
11 expr::AstPtr, 12 expr::AstPtr,
12 path::known,
13 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, 13 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor},
14 Adt, Function, Name, Path, 14 Adt, Function, Name, Path,
15}; 15};
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index f80d8eb5f..a9de01455 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -1,17 +1,12 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use ra_db::{FileId, FilePosition}; 3use hir_expand::name::AsName;
4use ra_syntax::{ 4use ra_syntax::ast::{self, AstNode, NameOwner};
5 algo::find_node_at_offset,
6 ast::{self, AstNode, NameOwner},
7 SyntaxNode,
8};
9 5
10use crate::{ 6use crate::{
11 db::{AstDatabase, DefDatabase, HirDatabase}, 7 db::{AstDatabase, DefDatabase, HirDatabase},
12 ids::{AstItemDef, LocationCtx}, 8 ids::{AstItemDef, LocationCtx},
13 name::AsName, 9 AstId, Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, Module,
14 Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, Module,
15 ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, 10 ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef,
16}; 11};
17 12
@@ -129,41 +124,6 @@ impl FromSource for StructField {
129 } 124 }
130} 125}
131 126
132// FIXME: simplify it
133impl ModuleSource {
134 pub fn from_position(
135 db: &(impl DefDatabase + AstDatabase),
136 position: FilePosition,
137 ) -> ModuleSource {
138 let parse = db.parse(position.file_id);
139 match &find_node_at_offset::<ast::Module>(parse.tree().syntax(), position.offset) {
140 Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()),
141 _ => {
142 let source_file = parse.tree();
143 ModuleSource::SourceFile(source_file)
144 }
145 }
146 }
147
148 pub fn from_child_node(
149 db: &(impl DefDatabase + AstDatabase),
150 file_id: FileId,
151 child: &SyntaxNode,
152 ) -> ModuleSource {
153 if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) {
154 ModuleSource::Module(m)
155 } else {
156 let source_file = db.parse(file_id).tree();
157 ModuleSource::SourceFile(source_file)
158 }
159 }
160
161 pub fn from_file_id(db: &(impl DefDatabase + AstDatabase), file_id: FileId) -> ModuleSource {
162 let source_file = db.parse(file_id).tree();
163 ModuleSource::SourceFile(source_file)
164 }
165}
166
167impl Module { 127impl Module {
168 pub fn from_declaration(db: &impl HirDatabase, src: Source<ast::Module>) -> Option<Self> { 128 pub fn from_declaration(db: &impl HirDatabase, src: Source<ast::Module>) -> Option<Self> {
169 let src_parent = Source { 129 let src_parent = Source {
@@ -183,7 +143,7 @@ impl Module {
183 ModuleSource::Module(ref module) => { 143 ModuleSource::Module(ref module) => {
184 assert!(!module.has_semi()); 144 assert!(!module.has_semi());
185 let ast_id_map = db.ast_id_map(src.file_id); 145 let ast_id_map = db.ast_id_map(src.file_id);
186 let item_id = ast_id_map.ast_id(module).with_file_id(src.file_id); 146 let item_id = AstId::new(src.file_id, ast_id_map.ast_id(module));
187 Some(item_id) 147 Some(item_id)
188 } 148 }
189 ModuleSource::SourceFile(_) => None, 149 ModuleSource::SourceFile(_) => None,
@@ -195,7 +155,7 @@ impl Module {
195 .find_map(|krate| { 155 .find_map(|krate| {
196 let def_map = db.crate_def_map(krate); 156 let def_map = db.crate_def_map(krate);
197 let module_id = def_map.find_module_by_source(src.file_id, decl_id)?; 157 let module_id = def_map.find_module_by_source(src.file_id, decl_id)?;
198 Some(Module { krate, module_id }) 158 Some(Module::new(krate, module_id))
199 }) 159 })
200 } 160 }
201} 161}
@@ -208,6 +168,6 @@ where
208 let module_src = 168 let module_src =
209 crate::ModuleSource::from_child_node(db, src.file_id.original_file(db), &src.ast.syntax()); 169 crate::ModuleSource::from_child_node(db, src.file_id.original_file(db), &src.ast.syntax());
210 let module = Module::from_definition(db, Source { file_id: src.file_id, ast: module_src })?; 170 let module = Module::from_definition(db, Source { file_id: src.file_id, ast: module_src })?;
211 let ctx = LocationCtx::new(db, module, src.file_id); 171 let ctx = LocationCtx::new(db, module.id, src.file_id);
212 Some(DEF::from_ast(ctx, &src.ast)) 172 Some(DEF::from_ast(ctx, &src.ast))
213} 173}
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index 4ce7551c3..52e1fbf29 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -5,15 +5,17 @@
5 5
6use std::sync::Arc; 6use std::sync::Arc;
7 7
8use hir_def::{
9 path::Path,
10 type_ref::{TypeBound, TypeRef},
11};
12use hir_expand::name::{self, AsName};
8use ra_syntax::ast::{self, DefaultTypeParamOwner, NameOwner, TypeBoundsOwner, TypeParamsOwner}; 13use ra_syntax::ast::{self, DefaultTypeParamOwner, NameOwner, TypeBoundsOwner, TypeParamsOwner};
9 14
10use crate::{ 15use crate::{
11 db::{AstDatabase, DefDatabase, HirDatabase}, 16 db::{AstDatabase, DefDatabase, HirDatabase},
12 name::SELF_TYPE, 17 Adt, Const, Container, Enum, EnumVariant, Function, HasSource, ImplBlock, Name, Struct, Trait,
13 path::Path, 18 TypeAlias, Union,
14 type_ref::{TypeBound, TypeRef},
15 Adt, AsName, Const, Container, Enum, EnumVariant, Function, HasSource, ImplBlock, Name, Struct,
16 Trait, TypeAlias, Union,
17}; 19};
18 20
19/// Data about a generic parameter (to a function, struct, impl, ...). 21/// Data about a generic parameter (to a function, struct, impl, ...).
@@ -94,11 +96,15 @@ impl GenericParams {
94 GenericDef::Adt(Adt::Enum(it)) => generics.fill(&it.source(db).ast, start), 96 GenericDef::Adt(Adt::Enum(it)) => generics.fill(&it.source(db).ast, start),
95 GenericDef::Trait(it) => { 97 GenericDef::Trait(it) => {
96 // traits get the Self type as an implicit first type parameter 98 // traits get the Self type as an implicit first type parameter
97 generics.params.push(GenericParam { idx: start, name: SELF_TYPE, default: None }); 99 generics.params.push(GenericParam {
100 idx: start,
101 name: name::SELF_TYPE,
102 default: None,
103 });
98 generics.fill(&it.source(db).ast, start + 1); 104 generics.fill(&it.source(db).ast, start + 1);
99 // add super traits as bounds on Self 105 // add super traits as bounds on Self
100 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 106 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
101 let self_param = TypeRef::Path(SELF_TYPE.into()); 107 let self_param = TypeRef::Path(name::SELF_TYPE.into());
102 generics.fill_bounds(&it.source(db).ast, self_param); 108 generics.fill_bounds(&it.source(db).ast, self_param);
103 } 109 }
104 GenericDef::TypeAlias(it) => generics.fill(&it.source(db).ast, start), 110 GenericDef::TypeAlias(it) => generics.fill(&it.source(db).ast, start),
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 499dcafea..fe083c0c6 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -1,168 +1,17 @@
1//! FIXME: write short doc here 1//! hir makes heavy use of ids: integer (u32) handlers to various things. You
2 2//! can think of id as a pointer (but without a lifetime) or a file descriptor
3use std::{ 3//! (but for hir objects).
4 hash::{Hash, Hasher}, 4//!
5 sync::Arc, 5//! This module defines a bunch of ids we are using. The most important ones are
6}; 6//! probably `HirFileId` and `DefId`.
7 7
8use mbe::MacroRules; 8use ra_db::salsa;
9use ra_db::{salsa, FileId}; 9
10use ra_prof::profile; 10pub use hir_def::{
11use ra_syntax::{ast, AstNode, Parse, SyntaxNode}; 11 AstItemDef, ConstId, EnumId, FunctionId, ItemLoc, LocationCtx, StaticId, StructId, TraitId,
12 12 TypeAliasId,
13use crate::{
14 db::{AstDatabase, DefDatabase, InternDatabase},
15 AstId, Crate, FileAstId, Module, Source,
16}; 13};
17 14pub use hir_expand::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, MacroFileKind};
18/// hir makes heavy use of ids: integer (u32) handlers to various things. You
19/// can think of id as a pointer (but without a lifetime) or a file descriptor
20/// (but for hir objects).
21///
22/// This module defines a bunch of ids we are using. The most important ones are
23/// probably `HirFileId` and `DefId`.
24
25/// Input to the analyzer is a set of files, where each file is identified by
26/// `FileId` and contains source code. However, another source of source code in
27/// Rust are macros: each macro can be thought of as producing a "temporary
28/// file". To assign an id to such a file, we use the id of the macro call that
29/// produced the file. So, a `HirFileId` is either a `FileId` (source code
30/// written by user), or a `MacroCallId` (source code produced by macro).
31///
32/// What is a `MacroCallId`? Simplifying, it's a `HirFileId` of a file
33/// containing the call plus the offset of the macro call in the file. Note that
34/// this is a recursive definition! However, the size_of of `HirFileId` is
35/// finite (because everything bottoms out at the real `FileId`) and small
36/// (`MacroCallId` uses the location interner).
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
38pub struct HirFileId(HirFileIdRepr);
39
40impl HirFileId {
41 /// For macro-expansion files, returns the file original source file the
42 /// expansion originated from.
43 pub fn original_file(self, db: &impl InternDatabase) -> FileId {
44 match self.0 {
45 HirFileIdRepr::File(file_id) => file_id,
46 HirFileIdRepr::Macro(macro_file) => {
47 let loc = macro_file.macro_call_id.loc(db);
48 loc.ast_id.file_id().original_file(db)
49 }
50 }
51 }
52
53 /// Get the crate which the macro lives in, if it is a macro file.
54 pub(crate) fn macro_crate(self, db: &impl AstDatabase) -> Option<Crate> {
55 match self.0 {
56 HirFileIdRepr::File(_) => None,
57 HirFileIdRepr::Macro(macro_file) => {
58 let loc = macro_file.macro_call_id.loc(db);
59 Some(loc.def.krate)
60 }
61 }
62 }
63
64 pub(crate) fn parse_or_expand_query(
65 db: &impl AstDatabase,
66 file_id: HirFileId,
67 ) -> Option<SyntaxNode> {
68 match file_id.0 {
69 HirFileIdRepr::File(file_id) => Some(db.parse(file_id).tree().syntax().clone()),
70 HirFileIdRepr::Macro(macro_file) => {
71 db.parse_macro(macro_file).map(|it| it.syntax_node())
72 }
73 }
74 }
75
76 pub(crate) fn parse_macro_query(
77 db: &impl AstDatabase,
78 macro_file: MacroFile,
79 ) -> Option<Parse<SyntaxNode>> {
80 let _p = profile("parse_macro_query");
81 let macro_call_id = macro_file.macro_call_id;
82 let tt = db
83 .macro_expand(macro_call_id)
84 .map_err(|err| {
85 // Note:
86 // The final goal we would like to make all parse_macro success,
87 // such that the following log will not call anyway.
88 log::warn!("fail on macro_parse: (reason: {})", err,);
89 })
90 .ok()?;
91 match macro_file.macro_file_kind {
92 MacroFileKind::Items => mbe::token_tree_to_items(&tt).ok().map(Parse::to_syntax),
93 MacroFileKind::Expr => mbe::token_tree_to_expr(&tt).ok().map(Parse::to_syntax),
94 }
95 }
96}
97
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
99enum HirFileIdRepr {
100 File(FileId),
101 Macro(MacroFile),
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
105pub struct MacroFile {
106 macro_call_id: MacroCallId,
107 macro_file_kind: MacroFileKind,
108}
109
110#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
111pub(crate) enum MacroFileKind {
112 Items,
113 Expr,
114}
115
116impl From<FileId> for HirFileId {
117 fn from(file_id: FileId) -> HirFileId {
118 HirFileId(HirFileIdRepr::File(file_id))
119 }
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
123pub struct MacroDefId {
124 pub(crate) ast_id: AstId<ast::MacroCall>,
125 pub(crate) krate: Crate,
126}
127
128pub(crate) fn macro_def_query(db: &impl AstDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> {
129 let macro_call = id.ast_id.to_node(db);
130 let arg = macro_call.token_tree()?;
131 let (tt, _) = mbe::ast_to_token_tree(&arg).or_else(|| {
132 log::warn!("fail on macro_def to token tree: {:#?}", arg);
133 None
134 })?;
135 let rules = MacroRules::parse(&tt).ok().or_else(|| {
136 log::warn!("fail on macro_def parse: {:#?}", tt);
137 None
138 })?;
139 Some(Arc::new(rules))
140}
141
142pub(crate) fn macro_arg_query(db: &impl AstDatabase, id: MacroCallId) -> Option<Arc<tt::Subtree>> {
143 let loc = id.loc(db);
144 let macro_call = loc.ast_id.to_node(db);
145 let arg = macro_call.token_tree()?;
146 let (tt, _) = mbe::ast_to_token_tree(&arg)?;
147 Some(Arc::new(tt))
148}
149
150pub(crate) fn macro_expand_query(
151 db: &impl AstDatabase,
152 id: MacroCallId,
153) -> Result<Arc<tt::Subtree>, String> {
154 let loc = id.loc(db);
155 let macro_arg = db.macro_arg(id).ok_or("Fail to args in to tt::TokenTree")?;
156
157 let macro_rules = db.macro_def(loc.def).ok_or("Fail to find macro definition")?;
158 let tt = macro_rules.expand(&macro_arg).map_err(|err| format!("{:?}", err))?;
159 // Set a hard limit for the expanded tt
160 let count = tt.count();
161 if count > 65536 {
162 return Err(format!("Total tokens count exceed limit : count = {}", count));
163 }
164 Ok(Arc::new(tt))
165}
166 15
167macro_rules! impl_intern_key { 16macro_rules! impl_intern_key {
168 ($name:ident) => { 17 ($name:ident) => {
@@ -177,192 +26,6 @@ macro_rules! impl_intern_key {
177 }; 26 };
178} 27}
179 28
180/// `MacroCallId` identifies a particular macro invocation, like
181/// `println!("Hello, {}", world)`.
182#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
183pub struct MacroCallId(salsa::InternId);
184impl_intern_key!(MacroCallId);
185
186#[derive(Debug, Clone, PartialEq, Eq, Hash)]
187pub struct MacroCallLoc {
188 pub(crate) def: MacroDefId,
189 pub(crate) ast_id: AstId<ast::MacroCall>,
190}
191
192impl MacroCallId {
193 pub(crate) fn loc(self, db: &impl InternDatabase) -> MacroCallLoc {
194 db.lookup_intern_macro(self)
195 }
196
197 pub(crate) fn as_file(self, kind: MacroFileKind) -> HirFileId {
198 let macro_file = MacroFile { macro_call_id: self, macro_file_kind: kind };
199 HirFileId(HirFileIdRepr::Macro(macro_file))
200 }
201}
202
203impl MacroCallLoc {
204 pub(crate) fn id(self, db: &impl InternDatabase) -> MacroCallId {
205 db.intern_macro(self)
206 }
207}
208
209#[derive(Debug)]
210pub struct ItemLoc<N: AstNode> {
211 pub(crate) module: Module,
212 ast_id: AstId<N>,
213}
214
215impl<N: AstNode> PartialEq for ItemLoc<N> {
216 fn eq(&self, other: &Self) -> bool {
217 self.module == other.module && self.ast_id == other.ast_id
218 }
219}
220impl<N: AstNode> Eq for ItemLoc<N> {}
221impl<N: AstNode> Hash for ItemLoc<N> {
222 fn hash<H: Hasher>(&self, hasher: &mut H) {
223 self.module.hash(hasher);
224 self.ast_id.hash(hasher);
225 }
226}
227
228impl<N: AstNode> Clone for ItemLoc<N> {
229 fn clone(&self) -> ItemLoc<N> {
230 ItemLoc { module: self.module, ast_id: self.ast_id }
231 }
232}
233
234#[derive(Clone, Copy)]
235pub(crate) struct LocationCtx<DB> {
236 db: DB,
237 module: Module,
238 file_id: HirFileId,
239}
240
241impl<'a, DB: DefDatabase> LocationCtx<&'a DB> {
242 pub(crate) fn new(db: &'a DB, module: Module, file_id: HirFileId) -> LocationCtx<&'a DB> {
243 LocationCtx { db, module, file_id }
244 }
245}
246
247impl<'a, DB: DefDatabase + AstDatabase> LocationCtx<&'a DB> {
248 pub(crate) fn to_def<N, DEF>(self, ast: &N) -> DEF
249 where
250 N: AstNode,
251 DEF: AstItemDef<N>,
252 {
253 DEF::from_ast(self, ast)
254 }
255}
256
257pub(crate) trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
258 fn intern(db: &impl DefDatabase, loc: ItemLoc<N>) -> Self;
259 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<N>;
260
261 fn from_ast(ctx: LocationCtx<&(impl AstDatabase + DefDatabase)>, ast: &N) -> Self {
262 let items = ctx.db.ast_id_map(ctx.file_id);
263 let item_id = items.ast_id(ast);
264 Self::from_ast_id(ctx, item_id)
265 }
266 fn from_ast_id(ctx: LocationCtx<&impl DefDatabase>, ast_id: FileAstId<N>) -> Self {
267 let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) };
268 Self::intern(ctx.db, loc)
269 }
270 fn source(self, db: &(impl AstDatabase + DefDatabase)) -> Source<N> {
271 let loc = self.lookup_intern(db);
272 let ast = loc.ast_id.to_node(db);
273 Source { file_id: loc.ast_id.file_id(), ast }
274 }
275 fn module(self, db: &impl DefDatabase) -> Module {
276 let loc = self.lookup_intern(db);
277 loc.module
278 }
279}
280
281#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
282pub struct FunctionId(salsa::InternId);
283impl_intern_key!(FunctionId);
284
285impl AstItemDef<ast::FnDef> for FunctionId {
286 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::FnDef>) -> Self {
287 db.intern_function(loc)
288 }
289 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::FnDef> {
290 db.lookup_intern_function(self)
291 }
292}
293
294#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
295pub struct StructId(salsa::InternId);
296impl_intern_key!(StructId);
297impl AstItemDef<ast::StructDef> for StructId {
298 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::StructDef>) -> Self {
299 db.intern_struct(loc)
300 }
301 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::StructDef> {
302 db.lookup_intern_struct(self)
303 }
304}
305
306#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
307pub struct EnumId(salsa::InternId);
308impl_intern_key!(EnumId);
309impl AstItemDef<ast::EnumDef> for EnumId {
310 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::EnumDef>) -> Self {
311 db.intern_enum(loc)
312 }
313 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::EnumDef> {
314 db.lookup_intern_enum(self)
315 }
316}
317
318#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
319pub struct ConstId(salsa::InternId);
320impl_intern_key!(ConstId);
321impl AstItemDef<ast::ConstDef> for ConstId {
322 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::ConstDef>) -> Self {
323 db.intern_const(loc)
324 }
325 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::ConstDef> {
326 db.lookup_intern_const(self)
327 }
328}
329
330#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
331pub struct StaticId(salsa::InternId);
332impl_intern_key!(StaticId);
333impl AstItemDef<ast::StaticDef> for StaticId {
334 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::StaticDef>) -> Self {
335 db.intern_static(loc)
336 }
337 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::StaticDef> {
338 db.lookup_intern_static(self)
339 }
340}
341
342#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
343pub struct TraitId(salsa::InternId);
344impl_intern_key!(TraitId);
345impl AstItemDef<ast::TraitDef> for TraitId {
346 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::TraitDef>) -> Self {
347 db.intern_trait(loc)
348 }
349 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::TraitDef> {
350 db.lookup_intern_trait(self)
351 }
352}
353
354#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
355pub struct TypeAliasId(salsa::InternId);
356impl_intern_key!(TypeAliasId);
357impl AstItemDef<ast::TypeAliasDef> for TypeAliasId {
358 fn intern(db: &impl DefDatabase, loc: ItemLoc<ast::TypeAliasDef>) -> Self {
359 db.intern_type_alias(loc)
360 }
361 fn lookup_intern(self, db: &impl DefDatabase) -> ItemLoc<ast::TypeAliasDef> {
362 db.lookup_intern_type_alias(self)
363 }
364}
365
366/// This exists just for Chalk, because Chalk just has a single `StructId` where 29/// This exists just for Chalk, because Chalk just has a single `StructId` where
367/// we have different kinds of ADTs, primitive types and special type 30/// we have different kinds of ADTs, primitive types and special type
368/// constructors like tuples and function pointers. 31/// constructors like tuples and function pointers.
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 33ef87563..b1a014074 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -3,6 +3,8 @@
3use rustc_hash::FxHashMap; 3use rustc_hash::FxHashMap;
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use hir_def::{attr::Attr, type_ref::TypeRef};
7use hir_expand::hygiene::Hygiene;
6use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 8use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
7use ra_cfg::CfgOptions; 9use ra_cfg::CfgOptions;
8use ra_syntax::{ 10use ra_syntax::{
@@ -11,7 +13,6 @@ use ra_syntax::{
11}; 13};
12 14
13use crate::{ 15use crate::{
14 attr::Attr,
15 code_model::{Module, ModuleSource}, 16 code_model::{Module, ModuleSource},
16 db::{AstDatabase, DefDatabase, HirDatabase}, 17 db::{AstDatabase, DefDatabase, HirDatabase},
17 generics::HasGenericParams, 18 generics::HasGenericParams,
@@ -19,8 +20,7 @@ use crate::{
19 ids::MacroCallLoc, 20 ids::MacroCallLoc,
20 resolve::Resolver, 21 resolve::Resolver,
21 ty::Ty, 22 ty::Ty,
22 type_ref::TypeRef, 23 AssocItem, AstId, Const, Function, HasSource, HirFileId, MacroFileKind, Path, Source, TraitRef,
23 AssocItem, Const, Function, HasSource, HirFileId, MacroFileKind, Path, Source, TraitRef,
24 TypeAlias, 24 TypeAlias,
25}; 25};
26 26
@@ -129,7 +129,7 @@ impl ImplData {
129 ) -> Self { 129 ) -> Self {
130 let target_trait = node.target_trait().map(TypeRef::from_ast); 130 let target_trait = node.target_trait().map(TypeRef::from_ast);
131 let target_type = TypeRef::from_ast_opt(node.target_type()); 131 let target_type = TypeRef::from_ast_opt(node.target_type());
132 let ctx = LocationCtx::new(db, module, file_id); 132 let ctx = LocationCtx::new(db, module.id, file_id);
133 let negative = node.is_negative(); 133 let negative = node.is_negative();
134 let items = if let Some(item_list) = node.item_list() { 134 let items = if let Some(item_list) = node.item_list() {
135 item_list 135 item_list
@@ -182,7 +182,7 @@ impl ModuleImplBlocks {
182 ) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) { 182 ) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) {
183 let mut source_map = ImplSourceMap::default(); 183 let mut source_map = ImplSourceMap::default();
184 let crate_graph = db.crate_graph(); 184 let crate_graph = db.crate_graph();
185 let cfg_options = crate_graph.cfg_options(module.krate.crate_id()); 185 let cfg_options = crate_graph.cfg_options(module.id.krate);
186 186
187 let result = ModuleImplBlocks::collect(db, cfg_options, module, &mut source_map); 187 let result = ModuleImplBlocks::collect(db, cfg_options, module, &mut source_map);
188 (Arc::new(result), Arc::new(source_map)) 188 (Arc::new(result), Arc::new(source_map))
@@ -228,10 +228,11 @@ impl ModuleImplBlocks {
228 owner: &dyn ast::ModuleItemOwner, 228 owner: &dyn ast::ModuleItemOwner,
229 file_id: HirFileId, 229 file_id: HirFileId,
230 ) { 230 ) {
231 let hygiene = Hygiene::new(db, file_id);
231 for item in owner.items_with_macros() { 232 for item in owner.items_with_macros() {
232 match item { 233 match item {
233 ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => { 234 ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => {
234 let attrs = Attr::from_attrs_owner(file_id, &impl_block_ast, db); 235 let attrs = Attr::from_attrs_owner(&impl_block_ast, &hygiene);
235 if attrs.map_or(false, |attrs| { 236 if attrs.map_or(false, |attrs| {
236 attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) 237 attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false))
237 }) { 238 }) {
@@ -248,7 +249,7 @@ impl ModuleImplBlocks {
248 } 249 }
249 ast::ItemOrMacro::Item(_) => (), 250 ast::ItemOrMacro::Item(_) => (),
250 ast::ItemOrMacro::Macro(macro_call) => { 251 ast::ItemOrMacro::Macro(macro_call) => {
251 let attrs = Attr::from_attrs_owner(file_id, &macro_call, db); 252 let attrs = Attr::from_attrs_owner(&macro_call, &hygiene);
252 if attrs.map_or(false, |attrs| { 253 if attrs.map_or(false, |attrs| {
253 attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false)) 254 attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false))
254 }) { 255 }) {
@@ -256,14 +257,13 @@ impl ModuleImplBlocks {
256 } 257 }
257 258
258 //FIXME: we should really cut down on the boilerplate required to process a macro 259 //FIXME: we should really cut down on the boilerplate required to process a macro
259 let ast_id = db.ast_id_map(file_id).ast_id(&macro_call).with_file_id(file_id); 260 let ast_id = AstId::new(file_id, db.ast_id_map(file_id).ast_id(&macro_call));
260 if let Some(path) = macro_call 261 if let Some(path) =
261 .path() 262 macro_call.path().and_then(|path| Path::from_src(path, &hygiene))
262 .and_then(|path| Path::from_src(Source { ast: path, file_id }, db))
263 { 263 {
264 if let Some(def) = self.module.resolver(db).resolve_path_as_macro(db, &path) 264 if let Some(def) = self.module.resolver(db).resolve_path_as_macro(db, &path)
265 { 265 {
266 let call_id = MacroCallLoc { def: def.id, ast_id }.id(db); 266 let call_id = db.intern_macro(MacroCallLoc { def: def.id, ast_id });
267 let file_id = call_id.as_file(MacroFileKind::Items); 267 let file_id = call_id.as_file(MacroFileKind::Items);
268 if let Some(item_list) = 268 if let Some(item_list) =
269 db.parse_or_expand(file_id).and_then(ast::MacroItems::cast) 269 db.parse_or_expand(file_id).and_then(ast::MacroItems::cast)
diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs
index 6c4e8ffbd..e1780ed38 100644
--- a/crates/ra_hir/src/lang_item.rs
+++ b/crates/ra_hir/src/lang_item.rs
@@ -22,14 +22,14 @@ pub enum LangItemTarget {
22 22
23impl LangItemTarget { 23impl LangItemTarget {
24 pub(crate) fn krate(&self, db: &impl HirDatabase) -> Option<Crate> { 24 pub(crate) fn krate(&self, db: &impl HirDatabase) -> Option<Crate> {
25 match self { 25 Some(match self {
26 LangItemTarget::Enum(e) => e.module(db).krate(db), 26 LangItemTarget::Enum(e) => e.module(db).krate(),
27 LangItemTarget::Function(f) => f.module(db).krate(db), 27 LangItemTarget::Function(f) => f.module(db).krate(),
28 LangItemTarget::ImplBlock(i) => i.module().krate(db), 28 LangItemTarget::ImplBlock(i) => i.module().krate(),
29 LangItemTarget::Static(s) => s.module(db).krate(db), 29 LangItemTarget::Static(s) => s.module(db).krate(),
30 LangItemTarget::Struct(s) => s.module(db).krate(db), 30 LangItemTarget::Struct(s) => s.module(db).krate(),
31 LangItemTarget::Trait(t) => t.module(db).krate(db), 31 LangItemTarget::Trait(t) => t.module(db).krate(),
32 } 32 })
33 } 33 }
34} 34}
35 35
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index ca261e8f5..40f5562b4 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -26,25 +26,19 @@ macro_rules! impl_froms {
26 } 26 }
27} 27}
28 28
29mod either;
30pub mod debug; 29pub mod debug;
31 30
32pub mod db; 31pub mod db;
33#[macro_use] 32#[macro_use]
34pub mod mock; 33pub mod mock;
35mod path;
36pub mod source_binder; 34pub mod source_binder;
37 35
38mod source_id;
39mod ids; 36mod ids;
40mod name;
41mod nameres; 37mod nameres;
42mod adt; 38mod adt;
43mod traits; 39mod traits;
44mod type_alias; 40mod type_alias;
45mod type_ref;
46mod ty; 41mod ty;
47mod attr;
48mod impl_block; 42mod impl_block;
49mod expr; 43mod expr;
50mod lang_item; 44mod lang_item;
@@ -60,37 +54,35 @@ pub mod from_source;
60#[cfg(test)] 54#[cfg(test)]
61mod marks; 55mod marks;
62 56
63use crate::{ 57use hir_expand::AstId;
64 ids::MacroFileKind, 58
65 name::AsName, 59use crate::{ids::MacroFileKind, resolve::Resolver};
66 resolve::Resolver,
67 source_id::{AstId, FileAstId},
68};
69 60
70pub use self::{ 61pub use crate::{
71 adt::VariantDef, 62 adt::VariantDef,
72 either::Either, 63 code_model::{
64 docs::{DocDef, Docs, Documentation},
65 src::{HasBodySource, HasSource, Source},
66 Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum,
67 EnumVariant, FieldSource, FnData, Function, HasBody, MacroDef, Module, ModuleDef,
68 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
69 },
73 expr::ExprScopes, 70 expr::ExprScopes,
74 from_source::FromSource, 71 from_source::FromSource,
75 generics::{GenericDef, GenericParam, GenericParams, HasGenericParams}, 72 generics::{GenericDef, GenericParam, GenericParams, HasGenericParams},
76 ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile}, 73 ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile},
77 impl_block::ImplBlock, 74 impl_block::ImplBlock,
78 name::Name,
79 nameres::{ImportId, Namespace, PerNs}, 75 nameres::{ImportId, Namespace, PerNs},
80 path::{Path, PathKind},
81 resolve::ScopeDef, 76 resolve::ScopeDef,
82 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, 77 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
83 source_id::{AstIdMap, ErasedFileAstId},
84 ty::{ 78 ty::{
85 display::HirDisplay, ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor, TypeWalk, 79 display::HirDisplay, ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
86 }, 80 },
87 type_ref::Mutability,
88}; 81};
89 82
90pub use self::code_model::{ 83pub use hir_def::{
91 docs::{DocDef, Docs, Documentation}, 84 builtin_type::BuiltinType,
92 src::{HasBodySource, HasSource, Source}, 85 path::{Path, PathKind},
93 Adt, AssocItem, BuiltinType, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, 86 type_ref::Mutability,
94 Enum, EnumVariant, FieldSource, FnData, Function, HasBody, MacroDef, Module, ModuleDef,
95 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
96}; 87};
88pub use hir_expand::{either::Either, name::Name};
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs
index 79af24b20..b423489a1 100644
--- a/crates/ra_hir/src/marks.rs
+++ b/crates/ra_hir/src/marks.rs
@@ -2,6 +2,7 @@
2 2
3test_utils::marks!( 3test_utils::marks!(
4 bogus_paths 4 bogus_paths
5 // FIXME: restore this mark once hir is split
5 name_res_works_for_broken_modules 6 name_res_works_for_broken_modules
6 can_import_enum_variant 7 can_import_enum_variant
7 type_var_cycles_resolve_completely 8 type_var_cycles_resolve_completely
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index 0b278deb3..35dfaf3ba 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -22,6 +22,7 @@ pub const WORKSPACE: SourceRootId = SourceRootId(0);
22 db::InternDatabaseStorage, 22 db::InternDatabaseStorage,
23 db::AstDatabaseStorage, 23 db::AstDatabaseStorage,
24 db::DefDatabaseStorage, 24 db::DefDatabaseStorage,
25 db::DefDatabase2Storage,
25 db::HirDatabaseStorage 26 db::HirDatabaseStorage
26)] 27)]
27#[derive(Debug)] 28#[derive(Debug)]
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
deleted file mode 100644
index 1e0b8c350..000000000
--- a/crates/ra_hir/src/name.rs
+++ /dev/null
@@ -1,142 +0,0 @@
1//! FIXME: write short doc here
2
3use std::fmt;
4
5use ra_syntax::{ast, SmolStr};
6
7/// `Name` is a wrapper around string, which is used in hir for both references
8/// and declarations. In theory, names should also carry hygiene info, but we are
9/// not there yet!
10#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
11pub struct Name(Repr);
12
13#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
14enum Repr {
15 Text(SmolStr),
16 TupleField(usize),
17}
18
19impl fmt::Display for Name {
20 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21 match &self.0 {
22 Repr::Text(text) => fmt::Display::fmt(&text, f),
23 Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
24 }
25 }
26}
27
28impl Name {
29 /// Note: this is private to make creating name from random string hard.
30 /// Hopefully, this should allow us to integrate hygiene cleaner in the
31 /// future, and to switch to interned representation of names.
32 const fn new_text(text: SmolStr) -> Name {
33 Name(Repr::Text(text))
34 }
35
36 pub(crate) fn new_tuple_field(idx: usize) -> Name {
37 Name(Repr::TupleField(idx))
38 }
39
40 /// Shortcut to create inline plain text name
41 const fn new_inline_ascii(len: usize, text: &[u8]) -> Name {
42 Name::new_text(SmolStr::new_inline_from_ascii(len, text))
43 }
44
45 /// Resolve a name from the text of token.
46 fn resolve(raw_text: &SmolStr) -> Name {
47 let raw_start = "r#";
48 if raw_text.as_str().starts_with(raw_start) {
49 Name::new_text(SmolStr::new(&raw_text[raw_start.len()..]))
50 } else {
51 Name::new_text(raw_text.clone())
52 }
53 }
54
55 pub(crate) fn missing() -> Name {
56 Name::new_text("[missing name]".into())
57 }
58
59 pub(crate) fn as_tuple_index(&self) -> Option<usize> {
60 match self.0 {
61 Repr::TupleField(idx) => Some(idx),
62 _ => None,
63 }
64 }
65}
66
67pub(crate) trait AsName {
68 fn as_name(&self) -> Name;
69}
70
71impl AsName for ast::NameRef {
72 fn as_name(&self) -> Name {
73 match self.as_tuple_field() {
74 Some(idx) => Name::new_tuple_field(idx),
75 None => Name::resolve(self.text()),
76 }
77 }
78}
79
80impl AsName for ast::Name {
81 fn as_name(&self) -> Name {
82 Name::resolve(self.text())
83 }
84}
85
86impl AsName for ast::FieldKind {
87 fn as_name(&self) -> Name {
88 match self {
89 ast::FieldKind::Name(nr) => nr.as_name(),
90 ast::FieldKind::Index(idx) => Name::new_tuple_field(idx.text().parse().unwrap()),
91 }
92 }
93}
94
95impl AsName for ra_db::Dependency {
96 fn as_name(&self) -> Name {
97 Name::new_text(self.name.clone())
98 }
99}
100
101// Primitives
102pub(crate) const ISIZE: Name = Name::new_inline_ascii(5, b"isize");
103pub(crate) const I8: Name = Name::new_inline_ascii(2, b"i8");
104pub(crate) const I16: Name = Name::new_inline_ascii(3, b"i16");
105pub(crate) const I32: Name = Name::new_inline_ascii(3, b"i32");
106pub(crate) const I64: Name = Name::new_inline_ascii(3, b"i64");
107pub(crate) const I128: Name = Name::new_inline_ascii(4, b"i128");
108pub(crate) const USIZE: Name = Name::new_inline_ascii(5, b"usize");
109pub(crate) const U8: Name = Name::new_inline_ascii(2, b"u8");
110pub(crate) const U16: Name = Name::new_inline_ascii(3, b"u16");
111pub(crate) const U32: Name = Name::new_inline_ascii(3, b"u32");
112pub(crate) const U64: Name = Name::new_inline_ascii(3, b"u64");
113pub(crate) const U128: Name = Name::new_inline_ascii(4, b"u128");
114pub(crate) const F32: Name = Name::new_inline_ascii(3, b"f32");
115pub(crate) const F64: Name = Name::new_inline_ascii(3, b"f64");
116pub(crate) const BOOL: Name = Name::new_inline_ascii(4, b"bool");
117pub(crate) const CHAR: Name = Name::new_inline_ascii(4, b"char");
118pub(crate) const STR: Name = Name::new_inline_ascii(3, b"str");
119
120// Special names
121pub(crate) const SELF_PARAM: Name = Name::new_inline_ascii(4, b"self");
122pub(crate) const SELF_TYPE: Name = Name::new_inline_ascii(4, b"Self");
123pub(crate) const MACRO_RULES: Name = Name::new_inline_ascii(11, b"macro_rules");
124
125// Components of known path (value or mod name)
126pub(crate) const STD: Name = Name::new_inline_ascii(3, b"std");
127pub(crate) const ITER: Name = Name::new_inline_ascii(4, b"iter");
128pub(crate) const OPS: Name = Name::new_inline_ascii(3, b"ops");
129pub(crate) const FUTURE: Name = Name::new_inline_ascii(6, b"future");
130pub(crate) const RESULT: Name = Name::new_inline_ascii(6, b"result");
131pub(crate) const BOXED: Name = Name::new_inline_ascii(5, b"boxed");
132
133// Components of known path (type name)
134pub(crate) const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(12, b"IntoIterator");
135pub(crate) const ITEM_TYPE: Name = Name::new_inline_ascii(4, b"Item");
136pub(crate) const TRY_TYPE: Name = Name::new_inline_ascii(3, b"Try");
137pub(crate) const OK_TYPE: Name = Name::new_inline_ascii(2, b"Ok");
138pub(crate) const FUTURE_TYPE: Name = Name::new_inline_ascii(6, b"Future");
139pub(crate) const RESULT_TYPE: Name = Name::new_inline_ascii(6, b"Result");
140pub(crate) const OUTPUT_TYPE: Name = Name::new_inline_ascii(6, b"Output");
141pub(crate) const TARGET_TYPE: Name = Name::new_inline_ascii(6, b"Target");
142pub(crate) const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box");
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 67adcfa28..7ba031827 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -48,16 +48,15 @@
48//! on the result 48//! on the result
49 49
50mod per_ns; 50mod per_ns;
51mod raw;
52mod collector; 51mod collector;
53mod mod_resolution;
54#[cfg(test)] 52#[cfg(test)]
55mod tests; 53mod tests;
56 54
57use std::sync::Arc; 55use std::sync::Arc;
58 56
57use hir_def::{builtin_type::BuiltinType, CrateModuleId};
59use once_cell::sync::Lazy; 58use once_cell::sync::Lazy;
60use ra_arena::{impl_arena_id, Arena, RawId}; 59use ra_arena::Arena;
61use ra_db::{Edition, FileId}; 60use ra_db::{Edition, FileId};
62use ra_prof::profile; 61use ra_prof::profile;
63use ra_syntax::ast; 62use ra_syntax::ast;
@@ -69,16 +68,12 @@ use crate::{
69 diagnostics::DiagnosticSink, 68 diagnostics::DiagnosticSink,
70 ids::MacroDefId, 69 ids::MacroDefId,
71 nameres::diagnostics::DefDiagnostic, 70 nameres::diagnostics::DefDiagnostic,
72 Adt, AstId, BuiltinType, Crate, HirFileId, MacroDef, Module, ModuleDef, Name, Path, PathKind, 71 Adt, AstId, Crate, HirFileId, MacroDef, Module, ModuleDef, Name, Path, PathKind, Trait,
73 Trait,
74}; 72};
75 73
76pub(crate) use self::raw::{ImportSourceMap, RawItems}; 74pub use self::per_ns::{Namespace, PerNs};
77 75
78pub use self::{ 76pub use hir_def::nameres::raw::ImportId;
79 per_ns::{Namespace, PerNs},
80 raw::ImportId,
81};
82 77
83/// Contains all top-level defs from a macro-expanded crate 78/// Contains all top-level defs from a macro-expanded crate
84#[derive(Debug, PartialEq, Eq)] 79#[derive(Debug, PartialEq, Eq)]
@@ -115,13 +110,8 @@ impl std::ops::Index<CrateModuleId> for CrateDefMap {
115 } 110 }
116} 111}
117 112
118/// An ID of a module, **local** to a specific crate
119#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
120pub(crate) struct CrateModuleId(RawId);
121impl_arena_id!(CrateModuleId);
122
123#[derive(Default, Debug, PartialEq, Eq)] 113#[derive(Default, Debug, PartialEq, Eq)]
124pub(crate) struct ModuleData { 114pub struct ModuleData {
125 pub(crate) parent: Option<CrateModuleId>, 115 pub(crate) parent: Option<CrateModuleId>,
126 pub(crate) children: FxHashMap<Name, CrateModuleId>, 116 pub(crate) children: FxHashMap<Name, CrateModuleId>,
127 pub(crate) scope: ModuleScope, 117 pub(crate) scope: ModuleScope,
@@ -332,10 +322,11 @@ impl CrateDefMap {
332 ) -> ResolvePathResult { 322 ) -> ResolvePathResult {
333 let mut segments = path.segments.iter().enumerate(); 323 let mut segments = path.segments.iter().enumerate();
334 let mut curr_per_ns: PerNs = match path.kind { 324 let mut curr_per_ns: PerNs = match path.kind {
335 PathKind::DollarCrate(krate) => { 325 PathKind::DollarCrate(crate_id) => {
326 let krate = Crate { crate_id };
336 if krate == self.krate { 327 if krate == self.krate {
337 tested_by!(macro_dollar_crate_self); 328 tested_by!(macro_dollar_crate_self);
338 PerNs::types(Module { krate: self.krate, module_id: self.root }.into()) 329 PerNs::types(Module::new(self.krate, self.root).into())
339 } else { 330 } else {
340 match krate.root_module(db) { 331 match krate.root_module(db) {
341 Some(module) => { 332 Some(module) => {
@@ -346,12 +337,8 @@ impl CrateDefMap {
346 } 337 }
347 } 338 }
348 } 339 }
349 PathKind::Crate => { 340 PathKind::Crate => PerNs::types(Module::new(self.krate, self.root).into()),
350 PerNs::types(Module { krate: self.krate, module_id: self.root }.into()) 341 PathKind::Self_ => PerNs::types(Module::new(self.krate, original_module).into()),
351 }
352 PathKind::Self_ => {
353 PerNs::types(Module { krate: self.krate, module_id: original_module }.into())
354 }
355 // plain import or absolute path in 2015: crate-relative with 342 // plain import or absolute path in 2015: crate-relative with
356 // fallback to extern prelude (with the simplification in 343 // fallback to extern prelude (with the simplification in
357 // rust-lang/rust#57745) 344 // rust-lang/rust#57745)
@@ -377,7 +364,7 @@ impl CrateDefMap {
377 } 364 }
378 PathKind::Super => { 365 PathKind::Super => {
379 if let Some(p) = self.modules[original_module].parent { 366 if let Some(p) = self.modules[original_module].parent {
380 PerNs::types(Module { krate: self.krate, module_id: p }.into()) 367 PerNs::types(Module::new(self.krate, p).into())
381 } else { 368 } else {
382 log::debug!("super path in root module"); 369 log::debug!("super path in root module");
383 return ResolvePathResult::empty(ReachedFixedPoint::Yes); 370 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
@@ -419,12 +406,12 @@ impl CrateDefMap {
419 406
420 curr_per_ns = match curr { 407 curr_per_ns = match curr {
421 ModuleDef::Module(module) => { 408 ModuleDef::Module(module) => {
422 if module.krate != self.krate { 409 if module.krate() != self.krate {
423 let path = 410 let path =
424 Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ }; 411 Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ };
425 log::debug!("resolving {:?} in other crate", path); 412 log::debug!("resolving {:?} in other crate", path);
426 let defp_map = db.crate_def_map(module.krate); 413 let defp_map = db.crate_def_map(module.krate());
427 let (def, s) = defp_map.resolve_path(db, module.module_id, &path); 414 let (def, s) = defp_map.resolve_path(db, module.id.module_id, &path);
428 return ResolvePathResult::with( 415 return ResolvePathResult::with(
429 def, 416 def,
430 ReachedFixedPoint::Yes, 417 ReachedFixedPoint::Yes,
@@ -433,7 +420,7 @@ impl CrateDefMap {
433 } 420 }
434 421
435 // Since it is a qualified path here, it should not contains legacy macros 422 // Since it is a qualified path here, it should not contains legacy macros
436 match self[module.module_id].scope.get(&segment.name) { 423 match self[module.id.module_id].scope.get(&segment.name) {
437 Some(res) => res.def, 424 Some(res) => res.def,
438 _ => { 425 _ => {
439 log::debug!("path segment {:?} not found", segment.name); 426 log::debug!("path segment {:?} not found", segment.name);
@@ -511,14 +498,14 @@ impl CrateDefMap {
511 fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs { 498 fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs {
512 if let Some(prelude) = self.prelude { 499 if let Some(prelude) = self.prelude {
513 let keep; 500 let keep;
514 let def_map = if prelude.krate == self.krate { 501 let def_map = if prelude.krate() == self.krate {
515 self 502 self
516 } else { 503 } else {
517 // Extend lifetime 504 // Extend lifetime
518 keep = db.crate_def_map(prelude.krate); 505 keep = db.crate_def_map(prelude.krate());
519 &keep 506 &keep
520 }; 507 };
521 def_map[prelude.module_id].scope.get(name).map_or_else(PerNs::none, |res| res.def) 508 def_map[prelude.id.module_id].scope.get(name).map_or_else(PerNs::none, |res| res.def)
522 } else { 509 } else {
523 PerNs::none() 510 PerNs::none()
524 } 511 }
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index b5fe16bfa..ee0a4c99f 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -1,5 +1,10 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir_def::{
4 attr::Attr,
5 nameres::{mod_resolution::ModDir, raw},
6};
7use hir_expand::name;
3use ra_cfg::CfgOptions; 8use ra_cfg::CfgOptions;
4use ra_db::FileId; 9use ra_db::FileId;
5use ra_syntax::{ast, SmolStr}; 10use ra_syntax::{ast, SmolStr};
@@ -7,13 +12,11 @@ use rustc_hash::FxHashMap;
7use test_utils::tested_by; 12use test_utils::tested_by;
8 13
9use crate::{ 14use crate::{
10 attr::Attr,
11 db::DefDatabase, 15 db::DefDatabase,
12 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind}, 16 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind},
13 name::MACRO_RULES,
14 nameres::{ 17 nameres::{
15 diagnostics::DefDiagnostic, mod_resolution::ModDir, raw, Crate, CrateDefMap, CrateModuleId, 18 diagnostics::DefDiagnostic, Crate, CrateDefMap, CrateModuleId, ModuleData, ModuleDef,
16 ModuleData, ModuleDef, PerNs, ReachedFixedPoint, Resolution, ResolveMode, 19 PerNs, ReachedFixedPoint, Resolution, ResolveMode,
17 }, 20 },
18 Adt, AstId, Const, Enum, Function, HirFileId, MacroDef, Module, Name, Path, PathKind, Static, 21 Adt, AstId, Const, Enum, Function, HirFileId, MacroDef, Module, Name, Path, PathKind, Static,
19 Struct, Trait, TypeAlias, Union, 22 Struct, Trait, TypeAlias, Union,
@@ -212,7 +215,7 @@ where
212 215
213 if let Some(ModuleDef::Module(m)) = res.take_types() { 216 if let Some(ModuleDef::Module(m)) = res.take_types() {
214 tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use); 217 tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use);
215 self.import_all_macros_exported(current_module_id, m.krate); 218 self.import_all_macros_exported(current_module_id, m.krate());
216 } 219 }
217 } 220 }
218 221
@@ -289,11 +292,11 @@ where
289 if import.is_prelude { 292 if import.is_prelude {
290 tested_by!(std_prelude); 293 tested_by!(std_prelude);
291 self.def_map.prelude = Some(m); 294 self.def_map.prelude = Some(m);
292 } else if m.krate != self.def_map.krate { 295 } else if m.krate() != self.def_map.krate {
293 tested_by!(glob_across_crates); 296 tested_by!(glob_across_crates);
294 // glob import from other crate => we can just import everything once 297 // glob import from other crate => we can just import everything once
295 let item_map = self.db.crate_def_map(m.krate); 298 let item_map = self.db.crate_def_map(m.krate());
296 let scope = &item_map[m.module_id].scope; 299 let scope = &item_map[m.id.module_id].scope;
297 300
298 // Module scoped macros is included 301 // Module scoped macros is included
299 let items = scope 302 let items = scope
@@ -307,7 +310,7 @@ where
307 // glob import from same crate => we do an initial 310 // glob import from same crate => we do an initial
308 // import, and then need to propagate any further 311 // import, and then need to propagate any further
309 // additions 312 // additions
310 let scope = &self.def_map[m.module_id].scope; 313 let scope = &self.def_map[m.id.module_id].scope;
311 314
312 // Module scoped macros is included 315 // Module scoped macros is included
313 let items = scope 316 let items = scope
@@ -319,7 +322,7 @@ where
319 self.update(module_id, Some(import_id), &items); 322 self.update(module_id, Some(import_id), &items);
320 // record the glob import in case we add further items 323 // record the glob import in case we add further items
321 self.glob_imports 324 self.glob_imports
322 .entry(m.module_id) 325 .entry(m.id.module_id)
323 .or_default() 326 .or_default()
324 .push((module_id, import_id)); 327 .push((module_id, import_id));
325 } 328 }
@@ -448,7 +451,7 @@ where
448 ); 451 );
449 452
450 if let Some(def) = resolved_res.resolved_def.get_macros() { 453 if let Some(def) = resolved_res.resolved_def.get_macros() {
451 let call_id = MacroCallLoc { def: def.id, ast_id: *ast_id }.id(self.db); 454 let call_id = self.db.intern_macro(MacroCallLoc { def: def.id, ast_id: *ast_id });
452 resolved.push((*module_id, call_id, def.id)); 455 resolved.push((*module_id, call_id, def.id));
453 res = ReachedFixedPoint::No; 456 res = ReachedFixedPoint::No;
454 return false; 457 return false;
@@ -523,9 +526,10 @@ where
523 526
524 // Prelude module is always considered to be `#[macro_use]`. 527 // Prelude module is always considered to be `#[macro_use]`.
525 if let Some(prelude_module) = self.def_collector.def_map.prelude { 528 if let Some(prelude_module) = self.def_collector.def_map.prelude {
526 if prelude_module.krate != self.def_collector.def_map.krate { 529 if prelude_module.krate() != self.def_collector.def_map.krate {
527 tested_by!(prelude_is_macro_use); 530 tested_by!(prelude_is_macro_use);
528 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate); 531 self.def_collector
532 .import_all_macros_exported(self.module_id, prelude_module.krate());
529 } 533 }
530 } 534 }
531 535
@@ -567,7 +571,7 @@ where
567 // inline module, just recurse 571 // inline module, just recurse
568 raw::ModuleData::Definition { name, items, ast_id } => { 572 raw::ModuleData::Definition { name, items, ast_id } => {
569 let module_id = 573 let module_id =
570 self.push_child_module(name.clone(), ast_id.with_file_id(self.file_id), None); 574 self.push_child_module(name.clone(), AstId::new(self.file_id, *ast_id), None);
571 575
572 ModCollector { 576 ModCollector {
573 def_collector: &mut *self.def_collector, 577 def_collector: &mut *self.def_collector,
@@ -583,7 +587,7 @@ where
583 } 587 }
584 // out of line module, resolve, parse and recurse 588 // out of line module, resolve, parse and recurse
585 raw::ModuleData::Declaration { name, ast_id } => { 589 raw::ModuleData::Declaration { name, ast_id } => {
586 let ast_id = ast_id.with_file_id(self.file_id); 590 let ast_id = AstId::new(self.file_id, *ast_id);
587 match self.mod_dir.resolve_declaration( 591 match self.mod_dir.resolve_declaration(
588 self.def_collector.db, 592 self.def_collector.db,
589 self.file_id, 593 self.file_id,
@@ -631,9 +635,7 @@ where
631 modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone(); 635 modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone();
632 modules[self.module_id].children.insert(name.clone(), res); 636 modules[self.module_id].children.insert(name.clone(), res);
633 let resolution = Resolution { 637 let resolution = Resolution {
634 def: PerNs::types( 638 def: PerNs::types(Module::new(self.def_collector.def_map.krate, res).into()),
635 Module { krate: self.def_collector.def_map.krate, module_id: res }.into(),
636 ),
637 import: None, 639 import: None,
638 }; 640 };
639 self.def_collector.update(self.module_id, None, &[(name, resolution)]); 641 self.def_collector.update(self.module_id, None, &[(name, resolution)]);
@@ -641,8 +643,8 @@ where
641 } 643 }
642 644
643 fn define_def(&mut self, def: &raw::DefData) { 645 fn define_def(&mut self, def: &raw::DefData) {
644 let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id }; 646 let module = Module::new(self.def_collector.def_map.krate, self.module_id);
645 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id); 647 let ctx = LocationCtx::new(self.def_collector.db, module.id, self.file_id);
646 648
647 macro_rules! def { 649 macro_rules! def {
648 ($kind:ident, $ast_id:ident) => { 650 ($kind:ident, $ast_id:ident) => {
@@ -671,28 +673,26 @@ where
671 } 673 }
672 674
673 fn collect_macro(&mut self, mac: &raw::MacroData) { 675 fn collect_macro(&mut self, mac: &raw::MacroData) {
676 let ast_id = AstId::new(self.file_id, mac.ast_id);
677
674 // Case 1: macro rules, define a macro in crate-global mutable scope 678 // Case 1: macro rules, define a macro in crate-global mutable scope
675 if is_macro_rules(&mac.path) { 679 if is_macro_rules(&mac.path) {
676 if let Some(name) = &mac.name { 680 if let Some(name) = &mac.name {
677 let macro_id = MacroDefId { 681 let macro_id =
678 ast_id: mac.ast_id.with_file_id(self.file_id), 682 MacroDefId { ast_id, krate: self.def_collector.def_map.krate.crate_id };
679 krate: self.def_collector.def_map.krate,
680 };
681 let macro_ = MacroDef { id: macro_id }; 683 let macro_ = MacroDef { id: macro_id };
682 self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export); 684 self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export);
683 } 685 }
684 return; 686 return;
685 } 687 }
686 688
687 let ast_id = mac.ast_id.with_file_id(self.file_id);
688
689 // Case 2: try to resolve in legacy scope and expand macro_rules, triggering 689 // Case 2: try to resolve in legacy scope and expand macro_rules, triggering
690 // recursive item collection. 690 // recursive item collection.
691 if let Some(macro_def) = mac.path.as_ident().and_then(|name| { 691 if let Some(macro_def) = mac.path.as_ident().and_then(|name| {
692 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) 692 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
693 }) { 693 }) {
694 let def = macro_def.id; 694 let def = macro_def.id;
695 let macro_call_id = MacroCallLoc { def, ast_id }.id(self.def_collector.db); 695 let macro_call_id = self.def_collector.db.intern_macro(MacroCallLoc { def, ast_id });
696 696
697 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, def); 697 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, def);
698 return; 698 return;
@@ -728,7 +728,7 @@ where
728} 728}
729 729
730fn is_macro_rules(path: &Path) -> bool { 730fn is_macro_rules(path: &Path) -> bool {
731 path.as_ident() == Some(&MACRO_RULES) 731 path.as_ident() == Some(&name::MACRO_RULES)
732} 732}
733 733
734#[cfg(test)] 734#[cfg(test)]
diff --git a/crates/ra_hir/src/nameres/mod_resolution.rs b/crates/ra_hir/src/nameres/mod_resolution.rs
deleted file mode 100644
index e8b808514..000000000
--- a/crates/ra_hir/src/nameres/mod_resolution.rs
+++ /dev/null
@@ -1,87 +0,0 @@
1//! This module resolves `mod foo;` declaration to file.
2use ra_db::FileId;
3use ra_syntax::SmolStr;
4use relative_path::RelativePathBuf;
5
6use crate::{db::DefDatabase, HirFileId, Name};
7
8#[derive(Clone, Debug)]
9pub(super) struct ModDir {
10 /// `.` for `mod.rs`, `lib.rs`
11 /// `./foo` for `foo.rs`
12 /// `./foo/bar` for `mod bar { mod x; }` nested in `foo.rs`
13 path: RelativePathBuf,
14 /// inside `./foo.rs`, mods with `#[path]` should *not* be relative to `./foo/`
15 root_non_dir_owner: bool,
16}
17
18impl ModDir {
19 pub(super) fn root() -> ModDir {
20 ModDir { path: RelativePathBuf::default(), root_non_dir_owner: false }
21 }
22
23 pub(super) fn descend_into_definition(
24 &self,
25 name: &Name,
26 attr_path: Option<&SmolStr>,
27 ) -> ModDir {
28 let mut path = self.path.clone();
29 match attr_to_path(attr_path) {
30 None => path.push(&name.to_string()),
31 Some(attr_path) => {
32 if self.root_non_dir_owner {
33 // Workaround for relative path API: turn `lib.rs` into ``.
34 if !path.pop() {
35 path = RelativePathBuf::default();
36 }
37 }
38 path.push(attr_path);
39 }
40 }
41 ModDir { path, root_non_dir_owner: false }
42 }
43
44 pub(super) fn resolve_declaration(
45 &self,
46 db: &impl DefDatabase,
47 file_id: HirFileId,
48 name: &Name,
49 attr_path: Option<&SmolStr>,
50 ) -> Result<(FileId, ModDir), RelativePathBuf> {
51 let empty_path = RelativePathBuf::default();
52 let file_id = file_id.original_file(db);
53
54 let mut candidate_files = Vec::new();
55 match attr_to_path(attr_path) {
56 Some(attr_path) => {
57 let base = if self.root_non_dir_owner {
58 self.path.parent().unwrap_or(&empty_path)
59 } else {
60 &self.path
61 };
62 candidate_files.push(base.join(attr_path))
63 }
64 None => {
65 candidate_files.push(self.path.join(&format!("{}.rs", name)));
66 candidate_files.push(self.path.join(&format!("{}/mod.rs", name)));
67 }
68 };
69
70 for candidate in candidate_files.iter() {
71 if let Some(file_id) = db.resolve_relative_path(file_id, candidate) {
72 let mut root_non_dir_owner = false;
73 let mut mod_path = RelativePathBuf::new();
74 if !(candidate.ends_with("mod.rs") || attr_path.is_some()) {
75 root_non_dir_owner = true;
76 mod_path.push(&name.to_string());
77 }
78 return Ok((file_id, ModDir { path: mod_path, root_non_dir_owner }));
79 }
80 }
81 Err(candidate_files.remove(0))
82 }
83}
84
85fn attr_to_path(attr: Option<&SmolStr>) -> Option<RelativePathBuf> {
86 attr.and_then(|it| RelativePathBuf::from_path(&it.replace("\\", "/")).ok())
87}
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
deleted file mode 100644
index 57f2929c3..000000000
--- a/crates/ra_hir/src/nameres/raw.rs
+++ /dev/null
@@ -1,403 +0,0 @@
1//! FIXME: write short doc here
2
3use std::{ops::Index, sync::Arc};
4
5use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
6use ra_syntax::{
7 ast::{self, AttrsOwner, NameOwner},
8 AstNode, AstPtr, SourceFile,
9};
10use test_utils::tested_by;
11
12use crate::{
13 attr::Attr,
14 db::{AstDatabase, DefDatabase},
15 AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, Source,
16};
17
18/// `RawItems` is a set of top-level items in a file (except for impls).
19///
20/// It is the input to name resolution algorithm. `RawItems` are not invalidated
21/// on most edits.
22#[derive(Debug, Default, PartialEq, Eq)]
23pub struct RawItems {
24 modules: Arena<Module, ModuleData>,
25 imports: Arena<ImportId, ImportData>,
26 defs: Arena<Def, DefData>,
27 macros: Arena<Macro, MacroData>,
28 /// items for top-level module
29 items: Vec<RawItem>,
30}
31
32#[derive(Debug, Default, PartialEq, Eq)]
33pub struct ImportSourceMap {
34 map: ArenaMap<ImportId, ImportSourcePtr>,
35}
36
37type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
38type ImportSource = Either<ast::UseTree, ast::ExternCrateItem>;
39
40impl ImportSourcePtr {
41 fn to_node(self, file: &SourceFile) -> ImportSource {
42 self.map(|ptr| ptr.to_node(file.syntax()), |ptr| ptr.to_node(file.syntax()))
43 }
44}
45
46impl ImportSourceMap {
47 fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) {
48 self.map.insert(import, ptr)
49 }
50
51 pub(crate) fn get(&self, source: &ModuleSource, import: ImportId) -> ImportSource {
52 let file = match source {
53 ModuleSource::SourceFile(file) => file.clone(),
54 ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
55 };
56
57 self.map[import].to_node(&file)
58 }
59}
60
61impl RawItems {
62 pub(crate) fn raw_items_query(
63 db: &(impl DefDatabase + AstDatabase),
64 file_id: HirFileId,
65 ) -> Arc<RawItems> {
66 db.raw_items_with_source_map(file_id).0
67 }
68
69 pub(crate) fn raw_items_with_source_map_query(
70 db: &(impl DefDatabase + AstDatabase),
71 file_id: HirFileId,
72 ) -> (Arc<RawItems>, Arc<ImportSourceMap>) {
73 let mut collector = RawItemsCollector {
74 raw_items: RawItems::default(),
75 source_ast_id_map: db.ast_id_map(file_id),
76 source_map: ImportSourceMap::default(),
77 file_id,
78 db,
79 };
80 if let Some(node) = db.parse_or_expand(file_id) {
81 if let Some(source_file) = ast::SourceFile::cast(node.clone()) {
82 collector.process_module(None, source_file);
83 } else if let Some(item_list) = ast::MacroItems::cast(node) {
84 collector.process_module(None, item_list);
85 }
86 }
87 (Arc::new(collector.raw_items), Arc::new(collector.source_map))
88 }
89
90 pub(super) fn items(&self) -> &[RawItem] {
91 &self.items
92 }
93}
94
95impl Index<Module> for RawItems {
96 type Output = ModuleData;
97 fn index(&self, idx: Module) -> &ModuleData {
98 &self.modules[idx]
99 }
100}
101
102impl Index<ImportId> for RawItems {
103 type Output = ImportData;
104 fn index(&self, idx: ImportId) -> &ImportData {
105 &self.imports[idx]
106 }
107}
108
109impl Index<Def> for RawItems {
110 type Output = DefData;
111 fn index(&self, idx: Def) -> &DefData {
112 &self.defs[idx]
113 }
114}
115
116impl Index<Macro> for RawItems {
117 type Output = MacroData;
118 fn index(&self, idx: Macro) -> &MacroData {
119 &self.macros[idx]
120 }
121}
122
123// Avoid heap allocation on items without attributes.
124type Attrs = Option<Arc<[Attr]>>;
125
126#[derive(Debug, PartialEq, Eq, Clone)]
127pub(super) struct RawItem {
128 attrs: Attrs,
129 pub(super) kind: RawItemKind,
130}
131
132impl RawItem {
133 pub(super) fn attrs(&self) -> &[Attr] {
134 self.attrs.as_ref().map_or(&[], |it| &*it)
135 }
136}
137
138#[derive(Debug, PartialEq, Eq, Clone, Copy)]
139pub(super) enum RawItemKind {
140 Module(Module),
141 Import(ImportId),
142 Def(Def),
143 Macro(Macro),
144}
145
146#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
147pub(super) struct Module(RawId);
148impl_arena_id!(Module);
149
150#[derive(Debug, PartialEq, Eq)]
151pub(super) enum ModuleData {
152 Declaration { name: Name, ast_id: FileAstId<ast::Module> },
153 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> },
154}
155
156#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
157pub struct ImportId(RawId);
158impl_arena_id!(ImportId);
159
160#[derive(Debug, Clone, PartialEq, Eq)]
161pub struct ImportData {
162 pub(super) path: Path,
163 pub(super) alias: Option<Name>,
164 pub(super) is_glob: bool,
165 pub(super) is_prelude: bool,
166 pub(super) is_extern_crate: bool,
167 pub(super) is_macro_use: bool,
168}
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
171pub(super) struct Def(RawId);
172impl_arena_id!(Def);
173
174#[derive(Debug, PartialEq, Eq)]
175pub(super) struct DefData {
176 pub(super) name: Name,
177 pub(super) kind: DefKind,
178}
179
180#[derive(Debug, PartialEq, Eq, Clone, Copy)]
181pub(super) enum DefKind {
182 Function(FileAstId<ast::FnDef>),
183 Struct(FileAstId<ast::StructDef>),
184 Union(FileAstId<ast::StructDef>),
185 Enum(FileAstId<ast::EnumDef>),
186 Const(FileAstId<ast::ConstDef>),
187 Static(FileAstId<ast::StaticDef>),
188 Trait(FileAstId<ast::TraitDef>),
189 TypeAlias(FileAstId<ast::TypeAliasDef>),
190}
191
192#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
193pub(super) struct Macro(RawId);
194impl_arena_id!(Macro);
195
196#[derive(Debug, PartialEq, Eq)]
197pub(super) struct MacroData {
198 pub(super) ast_id: FileAstId<ast::MacroCall>,
199 pub(super) path: Path,
200 pub(super) name: Option<Name>,
201 pub(super) export: bool,
202}
203
204struct RawItemsCollector<DB> {
205 raw_items: RawItems,
206 source_ast_id_map: Arc<AstIdMap>,
207 source_map: ImportSourceMap,
208 file_id: HirFileId,
209 db: DB,
210}
211
212impl<DB: AstDatabase> RawItemsCollector<&DB> {
213 fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) {
214 for item_or_macro in body.items_with_macros() {
215 match item_or_macro {
216 ast::ItemOrMacro::Macro(m) => self.add_macro(current_module, m),
217 ast::ItemOrMacro::Item(item) => self.add_item(current_module, item),
218 }
219 }
220 }
221
222 fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) {
223 let attrs = self.parse_attrs(&item);
224 let (kind, name) = match item {
225 ast::ModuleItem::Module(module) => {
226 self.add_module(current_module, module);
227 return;
228 }
229 ast::ModuleItem::UseItem(use_item) => {
230 self.add_use_item(current_module, use_item);
231 return;
232 }
233 ast::ModuleItem::ExternCrateItem(extern_crate) => {
234 self.add_extern_crate_item(current_module, extern_crate);
235 return;
236 }
237 ast::ModuleItem::ImplBlock(_) => {
238 // impls don't participate in name resolution
239 return;
240 }
241 ast::ModuleItem::StructDef(it) => {
242 let id = self.source_ast_id_map.ast_id(&it);
243 let name = it.name();
244 if it.is_union() {
245 (DefKind::Union(id), name)
246 } else {
247 (DefKind::Struct(id), name)
248 }
249 }
250 ast::ModuleItem::EnumDef(it) => {
251 (DefKind::Enum(self.source_ast_id_map.ast_id(&it)), it.name())
252 }
253 ast::ModuleItem::FnDef(it) => {
254 (DefKind::Function(self.source_ast_id_map.ast_id(&it)), it.name())
255 }
256 ast::ModuleItem::TraitDef(it) => {
257 (DefKind::Trait(self.source_ast_id_map.ast_id(&it)), it.name())
258 }
259 ast::ModuleItem::TypeAliasDef(it) => {
260 (DefKind::TypeAlias(self.source_ast_id_map.ast_id(&it)), it.name())
261 }
262 ast::ModuleItem::ConstDef(it) => {
263 (DefKind::Const(self.source_ast_id_map.ast_id(&it)), it.name())
264 }
265 ast::ModuleItem::StaticDef(it) => {
266 (DefKind::Static(self.source_ast_id_map.ast_id(&it)), it.name())
267 }
268 };
269 if let Some(name) = name {
270 let name = name.as_name();
271 let def = self.raw_items.defs.alloc(DefData { name, kind });
272 self.push_item(current_module, attrs, RawItemKind::Def(def));
273 }
274 }
275
276 fn add_module(&mut self, current_module: Option<Module>, module: ast::Module) {
277 let name = match module.name() {
278 Some(it) => it.as_name(),
279 None => return,
280 };
281 let attrs = self.parse_attrs(&module);
282
283 let ast_id = self.source_ast_id_map.ast_id(&module);
284 if module.has_semi() {
285 let item = self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id });
286 self.push_item(current_module, attrs, RawItemKind::Module(item));
287 return;
288 }
289
290 if let Some(item_list) = module.item_list() {
291 let item = self.raw_items.modules.alloc(ModuleData::Definition {
292 name,
293 ast_id,
294 items: Vec::new(),
295 });
296 self.process_module(Some(item), item_list);
297 self.push_item(current_module, attrs, RawItemKind::Module(item));
298 return;
299 }
300 tested_by!(name_res_works_for_broken_modules);
301 }
302
303 fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) {
304 // FIXME: cfg_attr
305 let is_prelude = use_item.has_atom_attr("prelude_import");
306 let attrs = self.parse_attrs(&use_item);
307
308 Path::expand_use_item(
309 Source { ast: use_item, file_id: self.file_id },
310 self.db,
311 |path, use_tree, is_glob, alias| {
312 let import_data = ImportData {
313 path,
314 alias,
315 is_glob,
316 is_prelude,
317 is_extern_crate: false,
318 is_macro_use: false,
319 };
320 self.push_import(
321 current_module,
322 attrs.clone(),
323 import_data,
324 Either::A(AstPtr::new(use_tree)),
325 );
326 },
327 )
328 }
329
330 fn add_extern_crate_item(
331 &mut self,
332 current_module: Option<Module>,
333 extern_crate: ast::ExternCrateItem,
334 ) {
335 if let Some(name_ref) = extern_crate.name_ref() {
336 let path = Path::from_name_ref(&name_ref);
337 let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name());
338 let attrs = self.parse_attrs(&extern_crate);
339 // FIXME: cfg_attr
340 let is_macro_use = extern_crate.has_atom_attr("macro_use");
341 let import_data = ImportData {
342 path,
343 alias,
344 is_glob: false,
345 is_prelude: false,
346 is_extern_crate: true,
347 is_macro_use,
348 };
349 self.push_import(
350 current_module,
351 attrs,
352 import_data,
353 Either::B(AstPtr::new(&extern_crate)),
354 );
355 }
356 }
357
358 fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) {
359 let attrs = self.parse_attrs(&m);
360 let path = match m
361 .path()
362 .and_then(|path| Path::from_src(Source { ast: path, file_id: self.file_id }, self.db))
363 {
364 Some(it) => it,
365 _ => return,
366 };
367
368 let name = m.name().map(|it| it.as_name());
369 let ast_id = self.source_ast_id_map.ast_id(&m);
370 // FIXME: cfg_attr
371 let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export");
372
373 let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export });
374 self.push_item(current_module, attrs, RawItemKind::Macro(m));
375 }
376
377 fn push_import(
378 &mut self,
379 current_module: Option<Module>,
380 attrs: Attrs,
381 data: ImportData,
382 source: ImportSourcePtr,
383 ) {
384 let import = self.raw_items.imports.alloc(data);
385 self.source_map.insert(import, source);
386 self.push_item(current_module, attrs, RawItemKind::Import(import))
387 }
388
389 fn push_item(&mut self, current_module: Option<Module>, attrs: Attrs, kind: RawItemKind) {
390 match current_module {
391 Some(module) => match &mut self.raw_items.modules[module] {
392 ModuleData::Definition { items, .. } => items,
393 ModuleData::Declaration { .. } => unreachable!(),
394 },
395 None => &mut self.raw_items.items,
396 }
397 .push(RawItem { attrs, kind })
398 }
399
400 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
401 Attr::from_attrs_owner(self.file_id, item, self.db)
402 }
403}
diff --git a/crates/ra_hir/src/nameres/tests/mod_resolution.rs b/crates/ra_hir/src/nameres/tests/mod_resolution.rs
index f569aacdc..abfe8b1c3 100644
--- a/crates/ra_hir/src/nameres/tests/mod_resolution.rs
+++ b/crates/ra_hir/src/nameres/tests/mod_resolution.rs
@@ -2,7 +2,7 @@ use super::*;
2 2
3#[test] 3#[test]
4fn name_res_works_for_broken_modules() { 4fn name_res_works_for_broken_modules() {
5 covers!(name_res_works_for_broken_modules); 5 // covers!(name_res_works_for_broken_modules);
6 let map = def_map( 6 let map = def_map(
7 " 7 "
8 //- /lib.rs 8 //- /lib.rs
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
deleted file mode 100644
index 394617e1a..000000000
--- a/crates/ra_hir/src/path.rs
+++ /dev/null
@@ -1,417 +0,0 @@
1//! FIXME: write short doc here
2
3use std::{iter, sync::Arc};
4
5use ra_syntax::{
6 ast::{self, NameOwner, TypeAscriptionOwner},
7 AstNode,
8};
9
10use crate::{db::AstDatabase, name, type_ref::TypeRef, AsName, Crate, Name, Source};
11
12#[derive(Debug, Clone, PartialEq, Eq, Hash)]
13pub struct Path {
14 pub kind: PathKind,
15 pub segments: Vec<PathSegment>,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq, Hash)]
19pub struct PathSegment {
20 pub name: Name,
21 pub args_and_bindings: Option<Arc<GenericArgs>>,
22}
23
24/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
25/// can (in the future) also include bindings of associated types, like in
26/// `Iterator<Item = Foo>`.
27#[derive(Debug, Clone, PartialEq, Eq, Hash)]
28pub struct GenericArgs {
29 pub args: Vec<GenericArg>,
30 /// This specifies whether the args contain a Self type as the first
31 /// element. This is the case for path segments like `<T as Trait>`, where
32 /// `T` is actually a type parameter for the path `Trait` specifying the
33 /// Self type. Otherwise, when we have a path `Trait<X, Y>`, the Self type
34 /// is left out.
35 pub has_self_type: bool,
36 /// Associated type bindings like in `Iterator<Item = T>`.
37 pub bindings: Vec<(Name, TypeRef)>,
38}
39
40/// A single generic argument.
41#[derive(Debug, Clone, PartialEq, Eq, Hash)]
42pub enum GenericArg {
43 Type(TypeRef),
44 // or lifetime...
45}
46
47#[derive(Debug, Clone, PartialEq, Eq, Hash)]
48pub enum PathKind {
49 Plain,
50 Self_,
51 Super,
52 Crate,
53 // Absolute path
54 Abs,
55 // Type based path like `<T>::foo`
56 Type(Box<TypeRef>),
57 // `$crate` from macro expansion
58 DollarCrate(Crate),
59}
60
61impl Path {
62 /// Calls `cb` with all paths, represented by this use item.
63 pub fn expand_use_item(
64 item_src: Source<ast::UseItem>,
65 db: &impl AstDatabase,
66 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
67 ) {
68 if let Some(tree) = item_src.ast.use_tree() {
69 expand_use_tree(None, tree, &|| item_src.file_id.macro_crate(db), &mut cb);
70 }
71 }
72
73 pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> Path {
74 Path {
75 kind,
76 segments: segments
77 .into_iter()
78 .map(|name| PathSegment { name, args_and_bindings: None })
79 .collect(),
80 }
81 }
82
83 /// Converts an `ast::Path` to `Path`. Works with use trees.
84 /// DEPRECATED: It does not handle `$crate` from macro call.
85 pub fn from_ast(path: ast::Path) -> Option<Path> {
86 Path::parse(path, &|| None)
87 }
88
89 /// Converts an `ast::Path` to `Path`. Works with use trees.
90 /// It correctly handles `$crate` based path from macro call.
91 pub fn from_src(source: Source<ast::Path>, db: &impl AstDatabase) -> Option<Path> {
92 let file_id = source.file_id;
93 Path::parse(source.ast, &|| file_id.macro_crate(db))
94 }
95
96 fn parse(mut path: ast::Path, macro_crate: &impl Fn() -> Option<Crate>) -> Option<Path> {
97 let mut kind = PathKind::Plain;
98 let mut segments = Vec::new();
99 loop {
100 let segment = path.segment()?;
101
102 if segment.has_colon_colon() {
103 kind = PathKind::Abs;
104 }
105
106 match segment.kind()? {
107 ast::PathSegmentKind::Name(name) => {
108 if name.text() == "$crate" {
109 if let Some(macro_crate) = macro_crate() {
110 kind = PathKind::DollarCrate(macro_crate);
111 break;
112 }
113 }
114
115 let args = segment
116 .type_arg_list()
117 .and_then(GenericArgs::from_ast)
118 .or_else(|| {
119 GenericArgs::from_fn_like_path_ast(
120 segment.param_list(),
121 segment.ret_type(),
122 )
123 })
124 .map(Arc::new);
125 let segment = PathSegment { name: name.as_name(), args_and_bindings: args };
126 segments.push(segment);
127 }
128 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
129 assert!(path.qualifier().is_none()); // this can only occur at the first segment
130
131 let self_type = TypeRef::from_ast(type_ref?);
132
133 match trait_ref {
134 // <T>::foo
135 None => {
136 kind = PathKind::Type(Box::new(self_type));
137 }
138 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
139 Some(trait_ref) => {
140 let path = Path::parse(trait_ref.path()?, macro_crate)?;
141 kind = path.kind;
142 let mut prefix_segments = path.segments;
143 prefix_segments.reverse();
144 segments.extend(prefix_segments);
145 // Insert the type reference (T in the above example) as Self parameter for the trait
146 let mut last_segment = segments.last_mut()?;
147 if last_segment.args_and_bindings.is_none() {
148 last_segment.args_and_bindings =
149 Some(Arc::new(GenericArgs::empty()));
150 };
151 let args = last_segment.args_and_bindings.as_mut().unwrap();
152 let mut args_inner = Arc::make_mut(args);
153 args_inner.has_self_type = true;
154 args_inner.args.insert(0, GenericArg::Type(self_type));
155 }
156 }
157 }
158 ast::PathSegmentKind::CrateKw => {
159 kind = PathKind::Crate;
160 break;
161 }
162 ast::PathSegmentKind::SelfKw => {
163 kind = PathKind::Self_;
164 break;
165 }
166 ast::PathSegmentKind::SuperKw => {
167 kind = PathKind::Super;
168 break;
169 }
170 }
171 path = match qualifier(&path) {
172 Some(it) => it,
173 None => break,
174 };
175 }
176 segments.reverse();
177 return Some(Path { kind, segments });
178
179 fn qualifier(path: &ast::Path) -> Option<ast::Path> {
180 if let Some(q) = path.qualifier() {
181 return Some(q);
182 }
183 // FIXME: this bottom up traversal is not too precise.
184 // Should we handle do a top-down analysis, recording results?
185 let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
186 let use_tree = use_tree_list.parent_use_tree();
187 use_tree.path()
188 }
189 }
190
191 /// Converts an `ast::NameRef` into a single-identifier `Path`.
192 pub fn from_name_ref(name_ref: &ast::NameRef) -> Path {
193 name_ref.as_name().into()
194 }
195
196 /// `true` is this path is a single identifier, like `foo`
197 pub fn is_ident(&self) -> bool {
198 self.kind == PathKind::Plain && self.segments.len() == 1
199 }
200
201 /// `true` if this path is just a standalone `self`
202 pub fn is_self(&self) -> bool {
203 self.kind == PathKind::Self_ && self.segments.is_empty()
204 }
205
206 /// If this path is a single identifier, like `foo`, return its name.
207 pub fn as_ident(&self) -> Option<&Name> {
208 if self.kind != PathKind::Plain || self.segments.len() > 1 {
209 return None;
210 }
211 self.segments.first().map(|s| &s.name)
212 }
213
214 pub fn expand_macro_expr(&self) -> Option<Name> {
215 self.as_ident().and_then(|name| Some(name.clone()))
216 }
217
218 pub fn is_type_relative(&self) -> bool {
219 match self.kind {
220 PathKind::Type(_) => true,
221 _ => false,
222 }
223 }
224}
225
226impl GenericArgs {
227 pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> {
228 let mut args = Vec::new();
229 for type_arg in node.type_args() {
230 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref());
231 args.push(GenericArg::Type(type_ref));
232 }
233 // lifetimes ignored for now
234 let mut bindings = Vec::new();
235 for assoc_type_arg in node.assoc_type_args() {
236 if let Some(name_ref) = assoc_type_arg.name_ref() {
237 let name = name_ref.as_name();
238 let type_ref = TypeRef::from_ast_opt(assoc_type_arg.type_ref());
239 bindings.push((name, type_ref));
240 }
241 }
242 if args.is_empty() && bindings.is_empty() {
243 None
244 } else {
245 Some(GenericArgs { args, has_self_type: false, bindings })
246 }
247 }
248
249 /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
250 /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
251 pub(crate) fn from_fn_like_path_ast(
252 params: Option<ast::ParamList>,
253 ret_type: Option<ast::RetType>,
254 ) -> Option<GenericArgs> {
255 let mut args = Vec::new();
256 let mut bindings = Vec::new();
257 if let Some(params) = params {
258 let mut param_types = Vec::new();
259 for param in params.params() {
260 let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
261 param_types.push(type_ref);
262 }
263 let arg = GenericArg::Type(TypeRef::Tuple(param_types));
264 args.push(arg);
265 }
266 if let Some(ret_type) = ret_type {
267 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
268 bindings.push((name::OUTPUT_TYPE, type_ref))
269 }
270 if args.is_empty() && bindings.is_empty() {
271 None
272 } else {
273 Some(GenericArgs { args, has_self_type: false, bindings })
274 }
275 }
276
277 pub(crate) fn empty() -> GenericArgs {
278 GenericArgs { args: Vec::new(), has_self_type: false, bindings: Vec::new() }
279 }
280}
281
282impl From<Name> for Path {
283 fn from(name: Name) -> Path {
284 Path::from_simple_segments(PathKind::Plain, iter::once(name))
285 }
286}
287
288fn expand_use_tree(
289 prefix: Option<Path>,
290 tree: ast::UseTree,
291 macro_crate: &impl Fn() -> Option<Crate>,
292 cb: &mut impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
293) {
294 if let Some(use_tree_list) = tree.use_tree_list() {
295 let prefix = match tree.path() {
296 // E.g. use something::{{{inner}}};
297 None => prefix,
298 // E.g. `use something::{inner}` (prefix is `None`, path is `something`)
299 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
300 Some(path) => match convert_path(prefix, path, macro_crate) {
301 Some(it) => Some(it),
302 None => return, // FIXME: report errors somewhere
303 },
304 };
305 for child_tree in use_tree_list.use_trees() {
306 expand_use_tree(prefix.clone(), child_tree, macro_crate, cb);
307 }
308 } else {
309 let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name());
310 if let Some(ast_path) = tree.path() {
311 // Handle self in a path.
312 // E.g. `use something::{self, <...>}`
313 if ast_path.qualifier().is_none() {
314 if let Some(segment) = ast_path.segment() {
315 if segment.kind() == Some(ast::PathSegmentKind::SelfKw) {
316 if let Some(prefix) = prefix {
317 cb(prefix, &tree, false, alias);
318 return;
319 }
320 }
321 }
322 }
323 if let Some(path) = convert_path(prefix, ast_path, macro_crate) {
324 let is_glob = tree.has_star();
325 cb(path, &tree, is_glob, alias)
326 }
327 // FIXME: report errors somewhere
328 // We get here if we do
329 }
330 }
331}
332
333fn convert_path(
334 prefix: Option<Path>,
335 path: ast::Path,
336 macro_crate: &impl Fn() -> Option<Crate>,
337) -> Option<Path> {
338 let prefix = if let Some(qual) = path.qualifier() {
339 Some(convert_path(prefix, qual, macro_crate)?)
340 } else {
341 prefix
342 };
343
344 let segment = path.segment()?;
345 let res = match segment.kind()? {
346 ast::PathSegmentKind::Name(name) => {
347 if name.text() == "$crate" {
348 if let Some(krate) = macro_crate() {
349 return Some(Path::from_simple_segments(
350 PathKind::DollarCrate(krate),
351 iter::empty(),
352 ));
353 }
354 }
355
356 // no type args in use
357 let mut res = prefix
358 .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) });
359 res.segments.push(PathSegment {
360 name: name.as_name(),
361 args_and_bindings: None, // no type args in use
362 });
363 res
364 }
365 ast::PathSegmentKind::CrateKw => {
366 if prefix.is_some() {
367 return None;
368 }
369 Path::from_simple_segments(PathKind::Crate, iter::empty())
370 }
371 ast::PathSegmentKind::SelfKw => {
372 if prefix.is_some() {
373 return None;
374 }
375 Path::from_simple_segments(PathKind::Self_, iter::empty())
376 }
377 ast::PathSegmentKind::SuperKw => {
378 if prefix.is_some() {
379 return None;
380 }
381 Path::from_simple_segments(PathKind::Super, iter::empty())
382 }
383 ast::PathSegmentKind::Type { .. } => {
384 // not allowed in imports
385 return None;
386 }
387 };
388 Some(res)
389}
390
391pub mod known {
392 use super::{Path, PathKind};
393 use crate::name;
394
395 pub fn std_iter_into_iterator() -> Path {
396 Path::from_simple_segments(
397 PathKind::Abs,
398 vec![name::STD, name::ITER, name::INTO_ITERATOR_TYPE],
399 )
400 }
401
402 pub fn std_ops_try() -> Path {
403 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE])
404 }
405
406 pub fn std_result_result() -> Path {
407 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE])
408 }
409
410 pub fn std_future_future() -> Path {
411 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::FUTURE, name::FUTURE_TYPE])
412 }
413
414 pub fn std_boxed_box() -> Path {
415 Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::BOXED, name::BOX_TYPE])
416 }
417}
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 3c797c0c3..75b24d386 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -1,6 +1,12 @@
1//! Name resolution. 1//! Name resolution.
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use hir_def::{
5 builtin_type::BuiltinType,
6 path::{Path, PathKind},
7 CrateModuleId,
8};
9use hir_expand::name::{self, Name};
4use rustc_hash::FxHashSet; 10use rustc_hash::FxHashSet;
5 11
6use crate::{ 12use crate::{
@@ -12,11 +18,8 @@ use crate::{
12 },