aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
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/src
parent49562d36b97ddde34cf7585a8c2e8f232519b657 (diff)
parentd067afb064a7fa67b172abf561b7d80740cd6f18 (diff)
Merge branch 'master' into feature/themes
Diffstat (limited to 'crates/ra_hir/src')
-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
42 files changed, 426 insertions, 2451 deletions
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 }, 18 },
13 generics::GenericParams, 19 generics::GenericParams,
14 impl_block::ImplBlock, 20 impl_block::ImplBlock,
15 name::{Name, SELF_PARAM, SELF_TYPE}, 21 nameres::{CrateDefMap, PerNs},
16 nameres::{CrateDefMap, CrateModuleId, PerNs}, 22 Adt, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, Static, Struct, Trait, TypeAlias,
17 path::{Path, PathKind},
18 Adt, BuiltinType, Const, Enum, EnumVariant, Function, MacroDef, ModuleDef, Static, Struct,
19 Trait, TypeAlias,
20}; 23};
21 24
22#[derive(Debug, Clone, Default)] 25#[derive(Debug, Clone, Default)]
@@ -149,13 +152,13 @@ impl Resolver {
149 } 152 }
150 } 153 }
151 Scope::ImplBlockScope(impl_) => { 154 Scope::ImplBlockScope(impl_) => {
152 if first_name == &SELF_TYPE { 155 if first_name == &name::SELF_TYPE {
153 let idx = if path.segments.len() == 1 { None } else { Some(1) }; 156 let idx = if path.segments.len() == 1 { None } else { Some(1) };
154 return Some((TypeNs::SelfType(*impl_), idx)); 157 return Some((TypeNs::SelfType(*impl_), idx));
155 } 158 }
156 } 159 }
157 Scope::AdtScope(adt) => { 160 Scope::AdtScope(adt) => {
158 if first_name == &SELF_TYPE { 161 if first_name == &name::SELF_TYPE {
159 let idx = if path.segments.len() == 1 { None } else { Some(1) }; 162 let idx = if path.segments.len() == 1 { None } else { Some(1) };
160 return Some((TypeNs::AdtSelfType(*adt), idx)); 163 return Some((TypeNs::AdtSelfType(*adt), idx));
161 } 164 }
@@ -204,7 +207,7 @@ impl Resolver {
204 return None; 207 return None;
205 } 208 }
206 let n_segments = path.segments.len(); 209 let n_segments = path.segments.len();
207 let tmp = SELF_PARAM; 210 let tmp = name::SELF_PARAM;
208 let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name }; 211 let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name };
209 let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); 212 let skip_to_mod = path.kind != PathKind::Plain && !path.is_self();
210 for scope in self.scopes.iter().rev() { 213 for scope in self.scopes.iter().rev() {
@@ -240,13 +243,13 @@ impl Resolver {
240 Scope::GenericParams(_) => continue, 243 Scope::GenericParams(_) => continue,
241 244
242 Scope::ImplBlockScope(impl_) if n_segments > 1 => { 245 Scope::ImplBlockScope(impl_) if n_segments > 1 => {
243 if first_name == &SELF_TYPE { 246 if first_name == &name::SELF_TYPE {
244 let ty = TypeNs::SelfType(*impl_); 247 let ty = TypeNs::SelfType(*impl_);
245 return Some(ResolveValueResult::Partial(ty, 1)); 248 return Some(ResolveValueResult::Partial(ty, 1));
246 } 249 }
247 } 250 }
248 Scope::AdtScope(adt) if n_segments > 1 => { 251 Scope::AdtScope(adt) if n_segments > 1 => {
249 if first_name == &SELF_TYPE { 252 if first_name == &name::SELF_TYPE {
250 let ty = TypeNs::AdtSelfType(*adt); 253 let ty = TypeNs::AdtSelfType(*adt);
251 return Some(ResolveValueResult::Partial(ty, 1)); 254 return Some(ResolveValueResult::Partial(ty, 1));
252 } 255 }
@@ -330,8 +333,8 @@ impl Resolver {
330 for scope in &self.scopes { 333 for scope in &self.scopes {
331 if let Scope::ModuleScope(m) = scope { 334 if let Scope::ModuleScope(m) = scope {
332 if let Some(prelude) = m.crate_def_map.prelude() { 335 if let Some(prelude) = m.crate_def_map.prelude() {
333 let prelude_def_map = db.crate_def_map(prelude.krate); 336 let prelude_def_map = db.crate_def_map(prelude.krate());
334 traits.extend(prelude_def_map[prelude.module_id].scope.traits()); 337 traits.extend(prelude_def_map[prelude.id.module_id].scope.traits());
335 } 338 }
336 traits.extend(m.crate_def_map[m.module_id].scope.traits()); 339 traits.extend(m.crate_def_map[m.module_id].scope.traits());
337 } 340 }
@@ -444,10 +447,12 @@ impl Scope {
444 f(name.clone(), ScopeDef::ModuleDef(*def)); 447 f(name.clone(), ScopeDef::ModuleDef(*def));
445 }); 448 });
446 if let Some(prelude) = m.crate_def_map.prelude() { 449 if let Some(prelude) = m.crate_def_map.prelude() {
447 let prelude_def_map = db.crate_def_map(prelude.krate); 450 let prelude_def_map = db.crate_def_map(prelude.krate());
448 prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| { 451 prelude_def_map[prelude.id.module_id].scope.entries().for_each(
449 f(name.clone(), res.def.into()); 452 |(name, res)| {
450 }); 453 f(name.clone(), res.def.into());
454 },
455 );
451 } 456 }
452 } 457 }
453 Scope::GenericParams(gp) => { 458 Scope::GenericParams(gp) => {
@@ -456,10 +461,10 @@ impl Scope {
456 } 461 }
457 } 462 }
458 Scope::ImplBlockScope(i) => { 463 Scope::ImplBlockScope(i) => {
459 f(SELF_TYPE, ScopeDef::ImplSelfType(*i)); 464 f(name::SELF_TYPE, ScopeDef::ImplSelfType(*i));
460 } 465 }
461 Scope::AdtScope(i) => { 466 Scope::AdtScope(i) => {
462 f(SELF_TYPE, ScopeDef::AdtSelfType(*i)); 467 f(name::SELF_TYPE, ScopeDef::AdtSelfType(*i));
463 } 468 }
464 Scope::ExprScope(e) => { 469 Scope::ExprScope(e) => {
465 e.expr_scopes.entries(e.scope_id).iter().for_each(|e| { 470 e.expr_scopes.entries(e.scope_id).iter().for_each(|e| {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index a907d6a9f..152bc71bd 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -7,10 +7,12 @@
7//! purely for "IDE needs". 7//! purely for "IDE needs".
8use std::sync::Arc; 8use std::sync::Arc;
9 9
10use hir_def::path::known;
11use hir_expand::name::AsName;
10use ra_db::FileId; 12use ra_db::FileId;
11use ra_syntax::{ 13use ra_syntax::{
12 ast::{self, AstNode}, 14 ast::{self, AstNode},
13 AstPtr, 15 match_ast, AstPtr,
14 SyntaxKind::*, 16 SyntaxKind::*,
15 SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, 17 SyntaxNode, SyntaxNodePtr, TextRange, TextUnit,
16}; 18};
@@ -24,11 +26,10 @@ use crate::{
24 BodySourceMap, 26 BodySourceMap,
25 }, 27 },
26 ids::LocationCtx, 28 ids::LocationCtx,
27 path::known,
28 resolve::{ScopeDef, TypeNs, ValueNs}, 29 resolve::{ScopeDef, TypeNs, ValueNs},
29 ty::method_resolution::implements_trait, 30 ty::method_resolution::implements_trait,
30 AsName, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, MacroDef, 31 Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, MacroDef, Module,
31 Module, Name, Path, Resolver, Static, Struct, Ty, 32 Name, Path, Resolver, Static, Struct, Ty,
32}; 33};
33 34
34fn try_get_resolver_for_node( 35fn try_get_resolver_for_node(
@@ -36,24 +37,34 @@ fn try_get_resolver_for_node(
36 file_id: FileId, 37 file_id: FileId,
37 node: &SyntaxNode, 38 node: &SyntaxNode,
38) -> Option<Resolver> { 39) -> Option<Resolver> {
39 if let Some(module) = ast::Module::cast(node.clone()) { 40 match_ast! {
40 let src = crate::Source { file_id: file_id.into(), ast: module }; 41 match node {
41 Some(crate::Module::from_declaration(db, src)?.resolver(db)) 42 ast::Module(it) => {
42 } else if let Some(file) = ast::SourceFile::cast(node.clone()) { 43 let src = crate::Source { file_id: file_id.into(), ast: it };
43 let src = 44 Some(crate::Module::from_declaration(db, src)?.resolver(db))
44 crate::Source { file_id: file_id.into(), ast: crate::ModuleSource::SourceFile(file) }; 45 },
45 Some(crate::Module::from_definition(db, src)?.resolver(db)) 46 ast::SourceFile(it) => {
46 } else if let Some(s) = ast::StructDef::cast(node.clone()) { 47 let src =
47 let src = crate::Source { file_id: file_id.into(), ast: s }; 48 crate::Source { file_id: file_id.into(), ast: crate::ModuleSource::SourceFile(it) };
48 Some(Struct::from_source(db, src)?.resolver(db)) 49 Some(crate::Module::from_definition(db, src)?.resolver(db))
49 } else if let Some(e) = ast::EnumDef::cast(node.clone()) { 50 },
50 let src = crate::Source { file_id: file_id.into(), ast: e }; 51 ast::StructDef(it) => {
51 Some(Enum::from_source(db, src)?.resolver(db)) 52 let src = crate::Source { file_id: file_id.into(), ast: it };
52 } else if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { 53 Some(Struct::from_source(db, src)?.resolver(db))
53 Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db)) 54 },
54 } else { 55 ast::EnumDef(it) => {
55 // FIXME add missing cases 56 let src = crate::Source { file_id: file_id.into(), ast: it };
56 None 57 Some(Enum::from_source(db, src)?.resolver(db))
58 },
59 _ => {
60 if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF {
61 Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db))
62 } else {
63 // FIXME add missing cases
64 None
65 }
66 },
67 }
57 } 68 }
58} 69}
59 70
@@ -64,19 +75,17 @@ fn def_with_body_from_child_node(
64) -> Option<DefWithBody> { 75) -> Option<DefWithBody> {
65 let src = crate::ModuleSource::from_child_node(db, file_id, node); 76 let src = crate::ModuleSource::from_child_node(db, file_id, node);
66 let module = Module::from_definition(db, crate::Source { file_id: file_id.into(), ast: src })?; 77 let module = Module::from_definition(db, crate::Source { file_id: file_id.into(), ast: src })?;
67 let ctx = LocationCtx::new(db, module, file_id.into()); 78 let ctx = LocationCtx::new(db, module.id, file_id.into());
68 79
69 node.ancestors().find_map(|node| { 80 node.ancestors().find_map(|node| {
70 if let Some(def) = ast::FnDef::cast(node.clone()) { 81 match_ast! {
71 return Some(Function { id: ctx.to_def(&def) }.into()); 82 match node {
72 } 83 ast::FnDef(def) => { Some(Function {id: ctx.to_def(&def) }.into()) },
73 if let Some(def) = ast::ConstDef::cast(node.clone()) { 84 ast::ConstDef(def) => { Some(Const { id: ctx.to_def(&def) }.into()) },
74 return Some(Const { id: ctx.to_def(&def) }.into()); 85 ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) },
75 } 86 _ => { None },
76 if let Some(def) = ast::StaticDef::cast(node) { 87 }
77 return Some(Static { id: ctx.to_def(&def) }.into());
78 } 88 }
79 None
80 }) 89 })
81} 90}
82 91
diff --git a/crates/ra_hir/src/source_id.rs b/crates/ra_hir/src/source_id.rs
deleted file mode 100644
index a4dd99598..000000000
--- a/crates/ra_hir/src/source_id.rs
+++ /dev/null
@@ -1,161 +0,0 @@
1//! FIXME: write short doc here
2
3use std::{
4 hash::{Hash, Hasher},
5 marker::PhantomData,
6 sync::Arc,
7};
8
9use ra_arena::{impl_arena_id, Arena, RawId};
10use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxNodePtr};
11
12use crate::{db::AstDatabase, HirFileId};
13
14/// `AstId` points to an AST node in any file.
15///
16/// It is stable across reparses, and can be used as salsa key/value.
17#[derive(Debug)]
18pub(crate) struct AstId<N: AstNode> {
19 file_id: HirFileId,
20 file_ast_id: FileAstId<N>,
21}
22
23impl<N: AstNode> Clone for AstId<N> {
24 fn clone(&self) -> AstId<N> {
25 *self
26 }
27}
28impl<N: AstNode> Copy for AstId<N> {}
29
30impl<N: AstNode> PartialEq for AstId<N> {
31 fn eq(&self, other: &Self) -> bool {
32 (self.file_id, self.file_ast_id) == (other.file_id, other.file_ast_id)
33 }
34}
35impl<N: AstNode> Eq for AstId<N> {}
36impl<N: AstNode> Hash for AstId<N> {
37 fn hash<H: Hasher>(&self, hasher: &mut H) {
38 (self.file_id, self.file_ast_id).hash(hasher);
39 }
40}
41
42impl<N: AstNode> AstId<N> {
43 pub(crate) fn file_id(&self) -> HirFileId {
44 self.file_id
45 }
46
47 pub(crate) fn to_node(&self, db: &impl AstDatabase) -> N {
48 let syntax_node = db.ast_id_to_node(self.file_id, self.file_ast_id.raw);
49 N::cast(syntax_node).unwrap()
50 }
51}
52
53/// `AstId` points to an AST node in a specific file.
54#[derive(Debug)]
55pub(crate) struct FileAstId<N: AstNode> {
56 raw: ErasedFileAstId,
57 _ty: PhantomData<fn() -> N>,
58}
59
60impl<N: AstNode> Clone for FileAstId<N> {
61 fn clone(&self) -> FileAstId<N> {
62 *self
63 }
64}
65impl<N: AstNode> Copy for FileAstId<N> {}
66
67impl<N: AstNode> PartialEq for FileAstId<N> {
68 fn eq(&self, other: &Self) -> bool {
69 self.raw == other.raw
70 }
71}
72impl<N: AstNode> Eq for FileAstId<N> {}
73impl<N: AstNode> Hash for FileAstId<N> {
74 fn hash<H: Hasher>(&self, hasher: &mut H) {
75 self.raw.hash(hasher);
76 }
77}
78
79impl<N: AstNode> FileAstId<N> {
80 pub(crate) fn with_file_id(self, file_id: HirFileId) -> AstId<N> {
81 AstId { file_id, file_ast_id: self }
82 }
83}
84
85#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
86pub struct ErasedFileAstId(RawId);
87impl_arena_id!(ErasedFileAstId);
88
89/// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.
90#[derive(Debug, PartialEq, Eq, Default)]
91pub struct AstIdMap {
92 arena: Arena<ErasedFileAstId, SyntaxNodePtr>,
93}
94
95impl AstIdMap {
96 pub(crate) fn ast_id_map_query(db: &impl AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
97 let map = if let Some(node) = db.parse_or_expand(file_id) {
98 AstIdMap::from_source(&node)
99 } else {
100 AstIdMap::default()
101 };
102 Arc::new(map)
103 }
104
105 pub(crate) fn file_item_query(
106 db: &impl AstDatabase,
107 file_id: HirFileId,
108 ast_id: ErasedFileAstId,
109 ) -> SyntaxNode {
110 let node = db.parse_or_expand(file_id).unwrap();
111 db.ast_id_map(file_id).arena[ast_id].to_node(&node)
112 }
113
114 pub(crate) fn ast_id<N: AstNode>(&self, item: &N) -> FileAstId<N> {
115 let ptr = SyntaxNodePtr::new(item.syntax());
116 let raw = match self.arena.iter().find(|(_id, i)| **i == ptr) {
117 Some((it, _)) => it,
118 None => panic!(
119 "Can't find {:?} in AstIdMap:\n{:?}",
120 item.syntax(),
121 self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
122 ),
123 };
124
125 FileAstId { raw, _ty: PhantomData }
126 }
127
128 fn from_source(node: &SyntaxNode) -> AstIdMap {
129 assert!(node.parent().is_none());
130 let mut res = AstIdMap { arena: Arena::default() };
131 // By walking the tree in bread-first order we make sure that parents
132 // get lower ids then children. That is, adding a new child does not
133 // change parent's id. This means that, say, adding a new function to a
134 // trait does not change ids of top-level items, which helps caching.
135 bfs(node, |it| {
136 if let Some(module_item) = ast::ModuleItem::cast(it.clone()) {
137 res.alloc(module_item.syntax());
138 } else if let Some(macro_call) = ast::MacroCall::cast(it) {
139 res.alloc(macro_call.syntax());
140 }
141 });
142 res
143 }
144
145 fn alloc(&mut self, item: &SyntaxNode) -> ErasedFileAstId {
146 self.arena.alloc(SyntaxNodePtr::new(item))
147 }
148}
149
150/// Walks the subtree in bfs order, calling `f` for each node.
151fn bfs(node: &SyntaxNode, mut f: impl FnMut(SyntaxNode)) {
152 let mut curr_layer = vec![node.clone()];
153 let mut next_layer = vec![];
154 while !curr_layer.is_empty() {
155 curr_layer.drain(..).for_each(|node| {
156 next_layer.extend(node.children());
157 f(node);
158 });
159 std::mem::swap(&mut curr_layer, &mut next_layer);
160 }
161}
diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs
index e39511518..1a45dacba 100644
--- a/crates/ra_hir/src/traits.rs
+++ b/crates/ra_hir/src/traits.rs
@@ -1,14 +1,15 @@
1//! HIR for trait definitions. 1//! HIR for trait definitions.
2 2
3use rustc_hash::FxHashMap;
4use std::sync::Arc; 3use std::sync::Arc;
5 4
5use hir_expand::name::AsName;
6
6use ra_syntax::ast::{self, NameOwner}; 7use ra_syntax::ast::{self, NameOwner};
8use rustc_hash::FxHashMap;
7 9
8use crate::{ 10use crate::{
9 db::{AstDatabase, DefDatabase}, 11 db::{AstDatabase, DefDatabase},
10 ids::LocationCtx, 12 ids::LocationCtx,
11 name::AsName,
12 AssocItem, Const, Function, HasSource, Module, Name, Trait, TypeAlias, 13 AssocItem, Const, Function, HasSource, Module, Name, Trait, TypeAlias,
13}; 14};
14 15
@@ -27,7 +28,7 @@ impl TraitData {
27 let src = tr.source(db); 28 let src = tr.source(db);
28 let name = src.ast.name().map(|n| n.as_name()); 29 let name = src.ast.name().map(|n| n.as_name());
29 let module = tr.module(db); 30 let module = tr.module(db);
30 let ctx = LocationCtx::new(db, module, src.file_id); 31 let ctx = LocationCtx::new(db, module.id, src.file_id);
31 let auto = src.ast.is_auto(); 32 let auto = src.ast.is_auto();
32 let items = if let Some(item_list) = src.ast.item_list() { 33 let items = if let Some(item_list) = src.ast.item_list() {
33 item_list 34 item_list
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index cc9746f6d..d2bfcdc7d 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -17,8 +17,8 @@ use std::sync::Arc;
17use std::{fmt, iter, mem}; 17use std::{fmt, iter, mem};
18 18
19use crate::{ 19use crate::{
20 db::HirDatabase, expr::ExprId, type_ref::Mutability, util::make_mut_slice, Adt, Crate, 20 db::HirDatabase, expr::ExprId, util::make_mut_slice, Adt, Crate, DefWithBody, GenericParams,
21 DefWithBody, GenericParams, HasGenericParams, Name, Trait, TypeAlias, 21 HasGenericParams, Mutability, Name, Trait, TypeAlias,
22}; 22};
23use display::{HirDisplay, HirFormatter}; 23use display::{HirDisplay, HirFormatter};
24 24
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs
index 02492ca14..3645ee831 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir/src/ty/autoderef.rs
@@ -5,10 +5,11 @@
5 5
6use std::iter::successors; 6use std::iter::successors;
7 7
8use hir_expand::name;
8use log::{info, warn}; 9use log::{info, warn};
9 10
10use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; 11use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk};
11use crate::{db::HirDatabase, name, HasGenericParams, Resolver}; 12use crate::{db::HirDatabase, HasGenericParams, Resolver};
12 13
13const AUTODEREF_RECURSION_LIMIT: usize = 10; 14const AUTODEREF_RECURSION_LIMIT: usize = 10;
14 15
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index ebaff998e..6694467a3 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -21,6 +21,11 @@ use std::sync::Arc;
21use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 21use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
22use rustc_hash::FxHashMap; 22use rustc_hash::FxHashMap;
23 23
24use hir_def::{
25 path::known,
26 type_ref::{Mutability, TypeRef},
27};
28use hir_expand::name;
24use ra_arena::map::ArenaMap; 29use ra_arena::map::ArenaMap;
25use ra_prof::profile; 30use ra_prof::profile;
26use test_utils::tested_by; 31use test_utils::tested_by;
@@ -37,11 +42,8 @@ use crate::{
37 db::HirDatabase, 42 db::HirDatabase,
38 diagnostics::DiagnosticSink, 43 diagnostics::DiagnosticSink,
39 expr::{BindingAnnotation, Body, ExprId, PatId}, 44 expr::{BindingAnnotation, Body, ExprId, PatId},
40 name,
41 path::known,
42 resolve::{Resolver, TypeNs}, 45 resolve::{Resolver, TypeNs},
43 ty::infer::diagnostics::InferenceDiagnostic, 46 ty::infer::diagnostics::InferenceDiagnostic,
44 type_ref::{Mutability, TypeRef},
45 Adt, AssocItem, ConstData, DefWithBody, FnData, Function, HasBody, Path, StructField, 47 Adt, AssocItem, ConstData, DefWithBody, FnData, Function, HasBody, Path, StructField,
46}; 48};
47 49
diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir/src/ty/infer/coerce.rs
index 0429a9866..6ea135126 100644
--- a/crates/ra_hir/src/ty/infer/coerce.rs
+++ b/crates/ra_hir/src/ty/infer/coerce.rs
@@ -14,8 +14,7 @@ use crate::{
14 lang_item::LangItemTarget, 14 lang_item::LangItemTarget,
15 resolve::Resolver, 15 resolve::Resolver,
16 ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk}, 16 ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk},
17 type_ref::Mutability, 17 Adt, Mutability,
18 Adt,
19}; 18};
20 19
21impl<'a, D: HirDatabase> InferenceContext<'a, D> { 20impl<'a, D: HirDatabase> InferenceContext<'a, D> {
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs
index f8807c742..fed52df39 100644
--- a/crates/ra_hir/src/ty/infer/expr.rs
+++ b/crates/ra_hir/src/ty/infer/expr.rs
@@ -3,14 +3,15 @@
3use std::iter::{repeat, repeat_with}; 3use std::iter::{repeat, repeat_with};
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use hir_def::path::{GenericArg, GenericArgs};
7use hir_expand::name;
8
6use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; 9use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch};
7use crate::{ 10use crate::{
8 db::HirDatabase, 11 db::HirDatabase,
9 expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 12 expr::{self, Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
10 generics::{GenericParams, HasGenericParams}, 13 generics::{GenericParams, HasGenericParams},
11 name,
12 nameres::Namespace, 14 nameres::Namespace,
13 path::{GenericArg, GenericArgs},
14 ty::{ 15 ty::{
15 autoderef, method_resolution, op, primitive, CallableDef, InferTy, Mutability, Obligation, 16 autoderef, method_resolution, op, primitive, CallableDef, InferTy, Mutability, Obligation,
16 ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, 17 ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index db979353a..77aa35ce1 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -1,5 +1,7 @@
1//! Path expression resolution. 1//! Path expression resolution.
2 2
3use hir_def::path::PathSegment;
4
3use super::{ExprOrPatId, InferenceContext, TraitRef}; 5use super::{ExprOrPatId, InferenceContext, TraitRef};
4use crate::{ 6use crate::{
5 db::HirDatabase, 7 db::HirDatabase,
@@ -131,7 +133,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
131 fn resolve_trait_assoc_item( 133 fn resolve_trait_assoc_item(
132 &mut self, 134 &mut self,
133 trait_ref: TraitRef, 135 trait_ref: TraitRef,
134 segment: &crate::path::PathSegment, 136 segment: &PathSegment,
135 id: ExprOrPatId, 137 id: ExprOrPatId,
136 ) -> Option<(ValueNs, Option<Substs>)> { 138 ) -> Option<(ValueNs, Option<Substs>)> {
137 let trait_ = trait_ref.trait_; 139 let trait_ = trait_ref.trait_;
@@ -170,7 +172,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
170 fn resolve_ty_assoc_item( 172 fn resolve_ty_assoc_item(
171 &mut self, 173 &mut self,
172 ty: Ty, 174 ty: Ty,
173 segment: &crate::path::PathSegment, 175 segment: &PathSegment,
174 id: ExprOrPatId, 176 id: ExprOrPatId,
175 ) -> Option<(ValueNs, Option<Substs>)> { 177 ) -> Option<(ValueNs, Option<Substs>)> {
176 if let Ty::Unknown = ty { 178 if let Ty::Unknown = ty {
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 366556134..dd7cd979f 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -8,6 +8,12 @@
8use std::iter; 8use std::iter;
9use std::sync::Arc; 9use std::sync::Arc;
10 10
11use hir_def::{
12 builtin_type::BuiltinType,
13 path::{GenericArg, PathSegment},
14 type_ref::{TypeBound, TypeRef},
15};
16
11use super::{ 17use super::{
12 FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, 18 FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
13 TypeWalk, 19 TypeWalk,
@@ -18,13 +24,14 @@ use crate::{
18 generics::HasGenericParams, 24 generics::HasGenericParams,
19 generics::{GenericDef, WherePredicate}, 25 generics::{GenericDef, WherePredicate},
20 nameres::Namespace, 26 nameres::Namespace,
21 path::{GenericArg, PathSegment},
22 resolve::{Resolver, TypeNs}, 27 resolve::{Resolver, TypeNs},
23 ty::Adt, 28 ty::{
24 type_ref::{TypeBound, TypeRef}, 29 primitive::{FloatTy, IntTy},
30 Adt,
31 },
25 util::make_mut_slice, 32 util::make_mut_slice,
26 BuiltinType, Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, 33 Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, Trait,
27 Trait, TypeAlias, Union, 34 TypeAlias, Union,
28}; 35};
29 36
30impl Ty { 37impl Ty {
@@ -640,8 +647,10 @@ fn type_for_builtin(def: BuiltinType) -> Ty {
640 BuiltinType::Char => TypeCtor::Char, 647 BuiltinType::Char => TypeCtor::Char,
641 BuiltinType::Bool => TypeCtor::Bool, 648 BuiltinType::Bool => TypeCtor::Bool,
642 BuiltinType::Str => TypeCtor::Str, 649 BuiltinType::Str => TypeCtor::Str,
643 BuiltinType::Int(ty) => TypeCtor::Int(ty.into()), 650 BuiltinType::Int { signedness, bitness } => {
644 BuiltinType::Float(ty) => TypeCtor::Float(ty.into()), 651 TypeCtor::Int(IntTy { signedness, bitness }.into())
652 }
653 BuiltinType::Float { bitness } => TypeCtor::Float(FloatTy { bitness }.into()),
645 }) 654 })
646} 655}
647 656
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index ad2ab560d..eb69344f6 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -5,18 +5,17 @@
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::CrateModuleId;
8use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
9 10
10use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; 11use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef};
11use crate::{ 12use crate::{
12 db::HirDatabase, 13 db::HirDatabase,
13 impl_block::{ImplBlock, ImplId}, 14 impl_block::{ImplBlock, ImplId},
14 nameres::CrateModuleId,
15 resolve::Resolver, 15 resolve::Resolver,
16 ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy}, 16 ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy},
17 ty::{Ty, TypeCtor}, 17 ty::{Ty, TypeCtor},
18 type_ref::Mutability, 18 AssocItem, Crate, Function, Module, Mutability, Name, Trait,
19 AssocItem, Crate, Function, Module, Name, Trait,
20}; 19};
21 20
22/// This is used as a key for indexing impls. 21/// This is used as a key for indexing impls.
@@ -50,7 +49,7 @@ impl CrateImplBlocks {
50 let fingerprint = TyFingerprint::for_impl(ty); 49 let fingerprint = TyFingerprint::for_impl(ty);
51 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flat_map(|i| i.iter()).map( 50 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flat_map(|i| i.iter()).map(
52 move |(module_id, impl_id)| { 51 move |(module_id, impl_id)| {
53 let module = Module { krate: self.krate, module_id: *module_id }; 52 let module = Module::new(self.krate, *module_id);
54 ImplBlock::from_id(module, *impl_id) 53 ImplBlock::from_id(module, *impl_id)
55 }, 54 },
56 ) 55 )
@@ -62,7 +61,7 @@ impl CrateImplBlocks {
62 ) -> impl Iterator<Item = ImplBlock> + 'a { 61 ) -> impl Iterator<Item = ImplBlock> + 'a {
63 self.impls_by_trait.get(&tr).into_iter().flat_map(|i| i.iter()).map( 62 self.impls_by_trait.get(&tr).into_iter().flat_map(|i| i.iter()).map(
64 move |(module_id, impl_id)| { 63 move |(module_id, impl_id)| {
65 let module = Module { krate: self.krate, module_id: *module_id }; 64 let module = Module::new(self.krate, *module_id);
66 ImplBlock::from_id(module, *impl_id) 65 ImplBlock::from_id(module, *impl_id)
67 }, 66 },
68 ) 67 )
@@ -71,7 +70,7 @@ impl CrateImplBlocks {
71 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplBlock> + 'a { 70 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplBlock> + 'a {
72 self.impls.values().chain(self.impls_by_trait.values()).flat_map(|i| i.iter()).map( 71 self.impls.values().chain(self.impls_by_trait.values()).flat_map(|i| i.iter()).map(
73 move |(module_id, impl_id)| { 72 move |(module_id, impl_id)| {
74 let module = Module { krate: self.krate, module_id: *module_id }; 73 let module = Module::new(self.krate, *module_id);
75 ImplBlock::from_id(module, *impl_id) 74 ImplBlock::from_id(module, *impl_id)
76 }, 75 },
77 ) 76 )
@@ -90,14 +89,14 @@ impl CrateImplBlocks {
90 self.impls_by_trait 89 self.impls_by_trait
91 .entry(tr.trait_) 90 .entry(tr.trait_)
92 .or_insert_with(Vec::new) 91 .or_insert_with(Vec::new)
93 .push((module.module_id, impl_id)); 92 .push((module.id.module_id, impl_id));
94 } 93 }
95 } else { 94 } else {
96 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { 95 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
97 self.impls 96 self.impls
98 .entry(target_ty_fp) 97 .entry(target_ty_fp)
99 .or_insert_with(Vec::new) 98 .or_insert_with(Vec::new)
100 .push((module.module_id, impl_id)); 99 .push((module.id.module_id, impl_id));
101 } 100 }
102 } 101 }
103 } 102 }
diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs
index 8966f9d1d..1749752f1 100644
--- a/crates/ra_hir/src/ty/primitive.rs
+++ b/crates/ra_hir/src/ty/primitive.rs
@@ -2,27 +2,7 @@
2 2
3use std::fmt; 3use std::fmt;
4 4
5#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 5pub use hir_def::builtin_type::{FloatBitness, IntBitness, Signedness};
6pub enum Signedness {
7 Signed,
8 Unsigned,
9}
10
11#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
12pub enum IntBitness {
13 Xsize,
14 X8,
15 X16,
16 X32,
17 X64,
18 X128,
19}
20
21#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
22pub enum FloatBitness {
23 X32,
24 X64,
25}
26 6
27#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 7#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
28pub enum UncertainIntTy { 8pub enum UncertainIntTy {
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 0cb5c3798..4f1eab150 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -1,7 +1,7 @@
1//! Trait solving using Chalk. 1//! Trait solving using Chalk.
2use std::sync::{Arc, Mutex}; 2use std::sync::{Arc, Mutex};
3 3
4use chalk_ir::cast::Cast; 4use chalk_ir::{cast::Cast, family::ChalkIr};
5use log::debug; 5use log::debug;
6use ra_db::salsa; 6use ra_db::salsa;
7use ra_prof::profile; 7use ra_prof::profile;
@@ -33,7 +33,7 @@ impl TraitSolver {
33 fn solve( 33 fn solve(
34 &self, 34 &self,
35 db: &impl HirDatabase, 35 db: &impl HirDatabase,
36 goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal>>, 36 goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<ChalkIr>>>,
37 ) -> Option<chalk_solve::Solution> { 37 ) -> Option<chalk_solve::Solution> {
38 let context = ChalkContext { db, krate: self.krate }; 38 let context = ChalkContext { db, krate: self.krate };
39 debug!("solve goal: {:?}", goal); 39 debug!("solve goal: {:?}", goal);
@@ -196,7 +196,7 @@ pub(crate) fn trait_solve_query(
196} 196}
197 197
198fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) -> Solution { 198fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) -> Solution {
199 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution>| { 199 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<ChalkIr>>| {
200 let value = subst 200 let value = subst
201 .value 201 .value
202 .parameters 202 .parameters
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 00aaf65d9..39ef92182 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -4,11 +4,13 @@ use std::sync::Arc;
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{ 6use chalk_ir::{
7 cast::Cast, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId, TypeKindId, TypeName, 7 cast::Cast, family::ChalkIr, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId,
8 UniverseIndex, 8 TypeKindId, TypeName, UniverseIndex,
9}; 9};
10use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; 10use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum};
11 11
12use hir_expand::name;
13
12use ra_db::salsa::{InternId, InternKey}; 14use ra_db::salsa::{InternId, InternKey};
13 15
14use super::{Canonical, ChalkContext, Impl, Obligation}; 16use super::{Canonical, ChalkContext, Impl, Obligation};
@@ -38,8 +40,8 @@ where
38} 40}
39 41
40impl ToChalk for Ty { 42impl ToChalk for Ty {
41 type Chalk = chalk_ir::Ty; 43 type Chalk = chalk_ir::Ty<ChalkIr>;
42 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty { 44 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty<ChalkIr> {
43 match self { 45 match self {
44 Ty::Apply(apply_ty) => { 46 Ty::Apply(apply_ty) => {
45 let name = match apply_ty.ctor { 47 let name = match apply_ty.ctor {
@@ -62,21 +64,19 @@ impl ToChalk for Ty {
62 chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast() 64 chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast()
63 } 65 }
64 Ty::Param { idx, .. } => { 66 Ty::Param { idx, .. } => {
65 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty() 67 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::<ChalkIr>()
66 } 68 }
67 Ty::Bound(idx) => chalk_ir::Ty::BoundVar(idx as usize), 69 Ty::Bound(idx) => chalk_ir::Ty::BoundVar(idx as usize),
68 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), 70 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
69 // FIXME this is clearly incorrect, but probably not too incorrect 71 // FIXME use Chalk's Dyn/Opaque once the bugs with that are fixed
70 // and I'm not sure what to actually do with Ty::Unknown
71 // maybe an alternative would be `for<T> T`? (meaningless in rust, but expressible in chalk's Ty)
72 //
73 // FIXME also dyn and impl Trait are currently handled like Unknown because Chalk doesn't have them yet
74 Ty::Unknown | Ty::Dyn(_) | Ty::Opaque(_) => { 72 Ty::Unknown | Ty::Dyn(_) | Ty::Opaque(_) => {
75 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::max_value() }.to_ty() 73 let parameters = Vec::new();
74 let name = TypeName::Error;
75 chalk_ir::ApplicationTy { name, parameters }.cast()
76 } 76 }
77 } 77 }
78 } 78 }
79 fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { 79 fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self {
80 match chalk { 80 match chalk {
81 chalk_ir::Ty::Apply(apply_ty) => { 81 chalk_ir::Ty::Apply(apply_ty) => {
82 // FIXME this is kind of hacky due to the fact that 82 // FIXME this is kind of hacky due to the fact that
@@ -92,6 +92,7 @@ impl ToChalk for Ty {
92 let parameters = from_chalk(db, apply_ty.parameters); 92 let parameters = from_chalk(db, apply_ty.parameters);
93 Ty::Apply(ApplicationTy { ctor, parameters }) 93 Ty::Apply(ApplicationTy { ctor, parameters })
94 } 94 }
95 TypeName::Error => Ty::Unknown,
95 // FIXME handle TypeKindId::Trait/Type here 96 // FIXME handle TypeKindId::Trait/Type here
96 TypeName::TypeKindId(_) => unimplemented!(), 97 TypeName::TypeKindId(_) => unimplemented!(),
97 TypeName::Placeholder(idx) => { 98 TypeName::Placeholder(idx) => {
@@ -108,18 +109,30 @@ impl ToChalk for Ty {
108 chalk_ir::Ty::ForAll(_) => unimplemented!(), 109 chalk_ir::Ty::ForAll(_) => unimplemented!(),
109 chalk_ir::Ty::BoundVar(idx) => Ty::Bound(idx as u32), 110 chalk_ir::Ty::BoundVar(idx) => Ty::Bound(idx as u32),
110 chalk_ir::Ty::InferenceVar(_iv) => Ty::Unknown, 111 chalk_ir::Ty::InferenceVar(_iv) => Ty::Unknown,
112 chalk_ir::Ty::Dyn(where_clauses) => {
113 assert_eq!(where_clauses.binders.len(), 1);
114 let predicates =
115 where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect();
116 Ty::Dyn(predicates)
117 }
118 chalk_ir::Ty::Opaque(where_clauses) => {
119 assert_eq!(where_clauses.binders.len(), 1);
120 let predicates =
121 where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect();
122 Ty::Opaque(predicates)
123 }
111 } 124 }
112 } 125 }
113} 126}
114 127
115impl ToChalk for Substs { 128impl ToChalk for Substs {
116 type Chalk = Vec<chalk_ir::Parameter>; 129 type Chalk = Vec<chalk_ir::Parameter<ChalkIr>>;
117 130
118 fn to_chalk(self, db: &impl HirDatabase) -> Vec<Parameter> { 131 fn to_chalk(self, db: &impl HirDatabase) -> Vec<Parameter<ChalkIr>> {
119 self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect() 132 self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect()
120 } 133 }
121 134
122 fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter>) -> Substs { 135 fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter<ChalkIr>>) -> Substs {
123 let tys = parameters 136 let tys = parameters
124 .into_iter() 137 .into_iter()
125 .map(|p| match p { 138 .map(|p| match p {
@@ -132,15 +145,15 @@ impl ToChalk for Substs {
132} 145}
133 146
134impl ToChalk for TraitRef { 147impl ToChalk for TraitRef {
135 type Chalk = chalk_ir::TraitRef; 148 type Chalk = chalk_ir::TraitRef<ChalkIr>;
136 149
137 fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef { 150 fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef<ChalkIr> {
138 let trait_id = self.trait_.to_chalk(db); 151 let trait_id = self.trait_.to_chalk(db);
139 let parameters = self.substs.to_chalk(db); 152 let parameters = self.substs.to_chalk(db);
140 chalk_ir::TraitRef { trait_id, parameters } 153 chalk_ir::TraitRef { trait_id, parameters }
141 } 154 }
142 155
143 fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef) -> Self { 156 fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef<ChalkIr>) -> Self {
144 let trait_ = from_chalk(db, trait_ref.trait_id); 157 let trait_ = from_chalk(db, trait_ref.trait_id);
145 let substs = from_chalk(db, trait_ref.parameters); 158 let substs = from_chalk(db, trait_ref.parameters);
146 TraitRef { trait_, substs } 159 TraitRef { trait_, substs }
@@ -151,11 +164,11 @@ impl ToChalk for Trait {
151 type Chalk = chalk_ir::TraitId; 164 type Chalk = chalk_ir::TraitId;
152 165
153 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TraitId { 166 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TraitId {
154 self.id.into() 167 chalk_ir::TraitId(id_to_chalk(self.id))
155 } 168 }
156 169
157 fn from_chalk(_db: &impl HirDatabase, trait_id: chalk_ir::TraitId) -> Trait { 170 fn from_chalk(_db: &impl HirDatabase, trait_id: chalk_ir::TraitId) -> Trait {
158 Trait { id: trait_id.into() } 171 Trait { id: id_from_chalk(trait_id.0) }
159 } 172 }
160} 173}
161 174
@@ -187,18 +200,18 @@ impl ToChalk for TypeAlias {
187 type Chalk = chalk_ir::TypeId; 200 type Chalk = chalk_ir::TypeId;
188 201
189 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TypeId { 202 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TypeId {
190 self.id.into() 203 chalk_ir::TypeId(id_to_chalk(self.id))
191 } 204 }
192 205
193 fn from_chalk(_db: &impl HirDatabase, impl_id: chalk_ir::TypeId) -> TypeAlias { 206 fn from_chalk(_db: &impl HirDatabase, type_alias_id: chalk_ir::TypeId) -> TypeAlias {
194 TypeAlias { id: impl_id.into() } 207 TypeAlias { id: id_from_chalk(type_alias_id.0) }
195 } 208 }
196} 209}
197 210
198impl ToChalk for GenericPredicate { 211impl ToChalk for GenericPredicate {
199 type Chalk = chalk_ir::QuantifiedWhereClause; 212 type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>;
200 213
201 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause { 214 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause<ChalkIr> {
202 match self { 215 match self {
203 GenericPredicate::Implemented(trait_ref) => { 216 GenericPredicate::Implemented(trait_ref) => {
204 make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) 217 make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0)
@@ -221,25 +234,40 @@ impl ToChalk for GenericPredicate {
221 } 234 }
222 235
223 fn from_chalk( 236 fn from_chalk(
224 _db: &impl HirDatabase, 237 db: &impl HirDatabase,
225 _where_clause: chalk_ir::QuantifiedWhereClause, 238 where_clause: chalk_ir::QuantifiedWhereClause<ChalkIr>,
226 ) -> GenericPredicate { 239 ) -> GenericPredicate {
227 // This should never need to be called 240 match where_clause.value {
228 unimplemented!() 241 chalk_ir::WhereClause::Implemented(tr) => {
242 if tr.trait_id == UNKNOWN_TRAIT {
243 // FIXME we need an Error enum on the Chalk side to avoid this
244 return GenericPredicate::Error;
245 }
246 GenericPredicate::Implemented(from_chalk(db, tr))
247 }
248 chalk_ir::WhereClause::ProjectionEq(projection_eq) => {
249 let projection_ty = from_chalk(db, projection_eq.projection);
250 let ty = from_chalk(db, projection_eq.ty);
251 GenericPredicate::Projection(super::ProjectionPredicate { projection_ty, ty })
252 }
253 }
229 } 254 }
230} 255}
231 256
232impl ToChalk for ProjectionTy { 257impl ToChalk for ProjectionTy {
233 type Chalk = chalk_ir::ProjectionTy; 258 type Chalk = chalk_ir::ProjectionTy<ChalkIr>;
234 259
235 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy { 260 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy<ChalkIr> {
236 chalk_ir::ProjectionTy { 261 chalk_ir::ProjectionTy {
237 associated_ty_id: self.associated_ty.to_chalk(db), 262 associated_ty_id: self.associated_ty.to_chalk(db),
238 parameters: self.parameters.to_chalk(db), 263 parameters: self.parameters.to_chalk(db),
239 } 264 }
240 } 265 }
241 266
242 fn from_chalk(db: &impl HirDatabase, projection_ty: chalk_ir::ProjectionTy) -> ProjectionTy { 267 fn from_chalk(
268 db: &impl HirDatabase,
269 projection_ty: chalk_ir::ProjectionTy<ChalkIr>,
270 ) -> ProjectionTy {
243 ProjectionTy { 271 ProjectionTy {
244 associated_ty: from_chalk(db, projection_ty.associated_ty_id), 272 associated_ty: from_chalk(db, projection_ty.associated_ty_id),
245 parameters: from_chalk(db, projection_ty.parameters), 273 parameters: from_chalk(db, projection_ty.parameters),
@@ -248,31 +276,31 @@ impl ToChalk for ProjectionTy {
248} 276}
249 277
250impl ToChalk for super::ProjectionPredicate { 278impl ToChalk for super::ProjectionPredicate {
251 type Chalk = chalk_ir::Normalize; 279 type Chalk = chalk_ir::Normalize<ChalkIr>;
252 280
253 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize { 281 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize<ChalkIr> {
254 chalk_ir::Normalize { 282 chalk_ir::Normalize {
255 projection: self.projection_ty.to_chalk(db), 283 projection: self.projection_ty.to_chalk(db),
256 ty: self.ty.to_chalk(db), 284 ty: self.ty.to_chalk(db),
257 } 285 }
258 } 286 }
259 287
260 fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize) -> Self { 288 fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize<ChalkIr>) -> Self {
261 unimplemented!() 289 unimplemented!()
262 } 290 }
263} 291}
264 292
265impl ToChalk for Obligation { 293impl ToChalk for Obligation {
266 type Chalk = chalk_ir::DomainGoal; 294 type Chalk = chalk_ir::DomainGoal<ChalkIr>;
267 295
268 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal { 296 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal<ChalkIr> {
269 match self { 297 match self {
270 Obligation::Trait(tr) => tr.to_chalk(db).cast(), 298 Obligation::Trait(tr) => tr.to_chalk(db).cast(),
271 Obligation::Projection(pr) => pr.to_chalk(db).cast(), 299 Obligation::Projection(pr) => pr.to_chalk(db).cast(),
272 } 300 }
273 } 301 }
274 302
275 fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal) -> Self { 303 fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal<ChalkIr>) -> Self {
276 unimplemented!() 304 unimplemented!()
277 } 305 }
278} 306}
@@ -296,16 +324,16 @@ where
296} 324}
297 325
298impl ToChalk for Arc<super::TraitEnvironment> { 326impl ToChalk for Arc<super::TraitEnvironment> {
299 type Chalk = Arc<chalk_ir::Environment>; 327 type Chalk = chalk_ir::Environment<ChalkIr>;
300 328
301 fn to_chalk(self, db: &impl HirDatabase) -> Arc<chalk_ir::Environment> { 329 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Environment<ChalkIr> {
302 let mut clauses = Vec::new(); 330 let mut clauses = Vec::new();
303 for pred in &self.predicates { 331 for pred in &self.predicates {
304 if pred.is_error() { 332 if pred.is_error() {
305 // for env, we just ignore errors 333 // for env, we just ignore errors
306 continue; 334 continue;
307 } 335 }
308 let program_clause: chalk_ir::ProgramClause = pred.clone().to_chalk(db).cast(); 336 let program_clause: chalk_ir::ProgramClause<ChalkIr> = pred.clone().to_chalk(db).cast();
309 clauses.push(program_clause.into_from_env_clause()); 337 clauses.push(program_clause.into_from_env_clause());
310 } 338 }
311 chalk_ir::Environment::new().add_clauses(clauses) 339 chalk_ir::Environment::new().add_clauses(clauses)
@@ -313,13 +341,16 @@ impl ToChalk for Arc<super::TraitEnvironment> {
313 341
314 fn from_chalk( 342 fn from_chalk(
315 _db: &impl HirDatabase, 343 _db: &impl HirDatabase,
316 _env: Arc<chalk_ir::Environment>, 344 _env: chalk_ir::Environment<ChalkIr>,
317 ) -> Arc<super::TraitEnvironment> { 345 ) -> Arc<super::TraitEnvironment> {
318 unimplemented!() 346 unimplemented!()
319 } 347 }
320} 348}
321 349
322impl<T: ToChalk> ToChalk for super::InEnvironment<T> { 350impl<T: ToChalk> ToChalk for super::InEnvironment<T>
351where
352 T::Chalk: chalk_ir::family::HasTypeFamily<TypeFamily = ChalkIr>,
353{
323 type Chalk = chalk_ir::InEnvironment<T::Chalk>; 354 type Chalk = chalk_ir::InEnvironment<T::Chalk>;
324 355
325 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { 356 fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> {
@@ -351,7 +382,7 @@ fn convert_where_clauses(
351 db: &impl HirDatabase, 382 db: &impl HirDatabase,
352 def: GenericDef, 383 def: GenericDef,
353 substs: &Substs, 384 substs: &Substs,
354) -> Vec<chalk_ir::QuantifiedWhereClause> { 385) -> Vec<chalk_ir::QuantifiedWhereClause<ChalkIr>> {
355 let generic_predicates = db.generic_predicates(def); 386 let generic_predicates = db.generic_predicates(def);
356 let mut result = Vec::with_capacity(generic_predicates.len()); 387 let mut result = Vec::with_capacity(generic_predicates.len());
357 for pred in generic_predicates.iter() { 388 for pred in generic_predicates.iter() {
@@ -384,7 +415,7 @@ where
384 fn impls_for_trait( 415 fn impls_for_trait(
385 &self, 416 &self,
386 trait_id: chalk_ir::TraitId, 417 trait_id: chalk_ir::TraitId,
387 parameters: &[Parameter], 418 parameters: &[Parameter<ChalkIr>],
388 ) -> Vec<ImplId> { 419 ) -> Vec<ImplId> {
389 debug!("impls_for_trait {:?}", trait_id); 420 debug!("impls_for_trait {:?}", trait_id);
390 if trait_id == UNKNOWN_TRAIT { 421 if trait_id == UNKNOWN_TRAIT {
@@ -430,13 +461,13 @@ where
430 } 461 }
431 fn split_projection<'p>( 462 fn split_projection<'p>(
432 &self, 463 &self,
433 projection: &'p chalk_ir::ProjectionTy, 464 projection: &'p chalk_ir::ProjectionTy<ChalkIr>,
434 ) -> (Arc<AssociatedTyDatum>, &'p [Parameter], &'p [Parameter]) { 465 ) -> (Arc<AssociatedTyDatum>, &'p [Parameter<ChalkIr>], &'p [Parameter<ChalkIr>]) {
435 debug!("split_projection {:?}", projection); 466 debug!("split_projection {:?}", projection);
436 // we don't support GATs, so I think this should always be correct currently 467 // we don't support GATs, so I think this should always be correct currently
437 (self.db.associated_ty_data(projection.associated_ty_id), &projection.parameters, &[]) 468 (self.db.associated_ty_data(projection.associated_ty_id), &projection.parameters, &[])
438 } 469 }
439 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause> { 470 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> {
440 vec![] 471 vec![]
441 } 472 }
442 fn local_impls_to_coherence_check( 473 fn local_impls_to_coherence_check(
@@ -508,7 +539,7 @@ pub(crate) fn trait_datum_query(
508 let trait_ref = trait_.trait_ref(db).subst(&bound_vars).to_chalk(db); 539 let trait_ref = trait_.trait_ref(db).subst(&bound_vars).to_chalk(db);
509 let flags = chalk_rust_ir::TraitFlags { 540 let flags = chalk_rust_ir::TraitFlags {
510 auto: trait_.is_auto(db), 541 auto: trait_.is_auto(db),
511 upstream: trait_.module(db).krate(db) != Some(krate), 542 upstream: trait_.module(db).krate() != krate,
512 non_enumerable: true, 543 non_enumerable: true,
513 // FIXME set these flags correctly 544 // FIXME set these flags correctly
514 marker: false, 545 marker: false,
@@ -596,7 +627,7 @@ fn impl_block_datum(
596 .target_trait_ref(db) 627 .target_trait_ref(db)
597 .expect("FIXME handle unresolved impl block trait ref") 628 .expect("FIXME handle unresolved impl block trait ref")
598 .subst(&bound_vars); 629 .subst(&bound_vars);
599 let impl_type = if impl_block.module().krate(db) == Some(krate) { 630 let impl_type = if impl_block.module().krate() == krate {
600 chalk_rust_ir::ImplType::Local 631 chalk_rust_ir::ImplType::Local
601 } else { 632 } else {
602 chalk_rust_ir::ImplType::External 633 chalk_rust_ir::ImplType::External
@@ -705,7 +736,7 @@ fn closure_fn_trait_impl_datum(
705 substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), 736 substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(),
706 }; 737 };
707 738
708 let output_ty_id = fn_once_trait.associated_type_by_name(db, &crate::name::OUTPUT_TYPE)?; 739 let output_ty_id = fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?;
709 740
710 let output_ty_value = chalk_rust_ir::AssociatedTyValue { 741 let output_ty_value = chalk_rust_ir::AssociatedTyValue {
711 associated_ty_id: output_ty_id.to_chalk(db), 742 associated_ty_id: output_ty_id.to_chalk(db),
@@ -746,30 +777,6 @@ fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId {
746 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() } 777 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() }
747} 778}
748 779
749impl From<chalk_ir::TraitId> for crate::ids::TraitId {
750 fn from(trait_id: chalk_ir::TraitId) -> Self {
751 id_from_chalk(trait_id.0)
752 }
753}
754
755impl From<crate::ids::TraitId> for chalk_ir::TraitId {
756 fn from(trait_id: crate::ids::TraitId) -> Self {
757 chalk_ir::TraitId(id_to_chalk(trait_id))
758 }
759}
760
761impl From<chalk_ir::TypeId> for crate::ids::TypeAliasId {
762 fn from(type_id: chalk_ir::TypeId) -> Self {
763 id_from_chalk(type_id.0)
764 }
765}
766
767impl From<crate::ids::TypeAliasId> for chalk_ir::TypeId {
768 fn from(type_id: crate::ids::TypeAliasId) -> Self {
769 chalk_ir::TypeId(id_to_chalk(type_id))
770 }
771}
772
773impl From<chalk_ir::StructId> for crate::ids::TypeCtorId { 780impl From<chalk_ir::StructId> for crate::ids::TypeCtorId {
774 fn from(struct_id: chalk_ir::StructId) -> Self { 781 fn from(struct_id: chalk_ir::StructId) -> Self {
775 id_from_chalk(struct_id.0) 782 id_from_chalk(struct_id.0)
diff --git a/crates/ra_hir/src/type_alias.rs b/crates/ra_hir/src/type_alias.rs
index 674a46102..078e6295e 100644
--- a/crates/ra_hir/src/type_alias.rs
+++ b/crates/ra_hir/src/type_alias.rs
@@ -2,12 +2,13 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::type_ref::TypeRef;
6use hir_expand::name::{AsName, Name};
7
5use ra_syntax::ast::NameOwner; 8use ra_syntax::ast::NameOwner;
6 9
7use crate::{ 10use crate::{
8 db::{AstDatabase, DefDatabase}, 11 db::{AstDatabase, DefDatabase},
9 name::{AsName, Name},
10 type_ref::TypeRef,
11 HasSource, TypeAlias, 12 HasSource, TypeAlias,
12}; 13};
13 14
diff --git a/crates/ra_hir/src/type_ref.rs b/crates/ra_hir/src/type_ref.rs
deleted file mode 100644
index 2cf06b250..000000000
--- a/crates/ra_hir/src/type_ref.rs
+++ /dev/null
@@ -1,162 +0,0 @@
1//! HIR for references to types. Paths in these are not yet resolved. They can
2//! be directly created from an ast::TypeRef, without further queries.
3
4use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner};
5
6use crate::Path;
7
8#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
9pub enum Mutability {
10 Shared,
11 Mut,
12}
13
14impl Mutability {
15 pub fn from_mutable(mutable: bool) -> Mutability {
16 if mutable {
17 Mutability::Mut
18 } else {
19 Mutability::Shared
20 }
21 }
22
23 pub fn as_keyword_for_ref(self) -> &'static str {
24 match self {
25 Mutability::Shared => "",
26 Mutability::Mut => "mut ",
27 }
28 }
29
30 pub fn as_keyword_for_ptr(self) -> &'static str {
31 match self {
32 Mutability::Shared => "const ",
33 Mutability::Mut => "mut ",
34 }
35 }
36}
37
38/// Compare ty::Ty
39#[derive(Clone, PartialEq, Eq, Hash, Debug)]
40pub enum TypeRef {
41 Never,
42 Placeholder,
43 Tuple(Vec<TypeRef>),
44 Path(Path),
45 RawPtr(Box<TypeRef>, Mutability),
46 Reference(Box<TypeRef>, Mutability),
47 Array(Box<TypeRef> /*, Expr*/),
48 Slice(Box<TypeRef>),
49 /// A fn pointer. Last element of the vector is the return type.
50 Fn(Vec<TypeRef>),
51 // For
52 ImplTrait(Vec<TypeBound>),
53 DynTrait(Vec<TypeBound>),
54 Error,
55}
56
57#[derive(Clone, PartialEq, Eq, Hash, Debug)]
58pub enum TypeBound {
59 Path(Path),
60 // also for<> bounds
61 // also Lifetimes
62 Error,
63}
64
65impl TypeRef {
66 /// Converts an `ast::TypeRef` to a `hir::TypeRef`.
67 pub(crate) fn from_ast(node: ast::TypeRef) -> Self {
68 match node {
69 ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(inner.type_ref()),
70 ast::TypeRef::TupleType(inner) => {
71 TypeRef::Tuple(inner.fields().map(TypeRef::from_ast).collect())
72 }
73 ast::TypeRef::NeverType(..) => TypeRef::Never,
74 ast::TypeRef::PathType(inner) => {
75 // FIXME: Use `Path::from_src`
76 inner.path().and_then(Path::from_ast).map(TypeRef::Path).unwrap_or(TypeRef::Error)
77 }
78 ast::TypeRef::PointerType(inner) => {
79 let inner_ty = TypeRef::from_ast_opt(inner.type_ref());
80 let mutability = Mutability::from_mutable(inner.is_mut());
81 TypeRef::RawPtr(Box::new(inner_ty), mutability)
82 }
83 ast::TypeRef::ArrayType(inner) => {
84 TypeRef::Array(Box::new(TypeRef::from_ast_opt(inner.type_ref())))
85 }
86 ast::TypeRef::SliceType(inner) => {
87 TypeRef::Slice(Box::new(TypeRef::from_ast_opt(inner.type_ref())))
88 }
89 ast::TypeRef::ReferenceType(inner) => {
90 let inner_ty = TypeRef::from_ast_opt(inner.type_ref());
91 let mutability = Mutability::from_mutable(inner.is_mut());
92 TypeRef::Reference(Box::new(inner_ty), mutability)
93 }
94 ast::TypeRef::PlaceholderType(_inner) => TypeRef::Placeholder,
95 ast::TypeRef::FnPointerType(inner) => {
96 let ret_ty = TypeRef::from_ast_opt(inner.ret_type().and_then(|rt| rt.type_ref()));
97 let mut params = if let Some(pl) = inner.param_list() {
98 pl.params().map(|p| p.ascribed_type()).map(TypeRef::from_ast_opt).collect()
99 } else {
100 Vec::new()
101 };
102 params.push(ret_ty);
103 TypeRef::Fn(params)
104 }
105 // for types are close enough for our purposes to the inner type for now...
106 ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(inner.type_ref()),
107 ast::TypeRef::ImplTraitType(inner) => {
108 TypeRef::ImplTrait(type_bounds_from_ast(inner.type_bound_list()))
109 }
110 ast::TypeRef::DynTraitType(inner) => {
111 TypeRef::DynTrait(type_bounds_from_ast(inner.type_bound_list()))
112 }
113 }
114 }
115
116 pub(crate) fn from_ast_opt(node: Option<ast::TypeRef>) -> Self {
117 if let Some(node) = node {
118 TypeRef::from_ast(node)
119 } else {
120 TypeRef::Error
121 }
122 }
123
124 pub fn unit() -> TypeRef {
125 TypeRef::Tuple(Vec::new())
126 }
127}
128
129pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> {
130 if let Some(type_bounds) = type_bounds_opt {
131 type_bounds.bounds().map(TypeBound::from_ast).collect()
132 } else {
133 vec![]
134 }
135}
136
137impl TypeBound {
138 pub(crate) fn from_ast(node: ast::TypeBound) -> Self {
139 match node.kind() {
140 ast::TypeBoundKind::PathType(path_type) => {
141 let path = match path_type.path() {
142 Some(p) => p,
143 None => return TypeBound::Error,
144 };
145 // FIXME: Use `Path::from_src`
146 let path = match Path::from_ast(path) {
147 Some(p) => p,
148 None => return TypeBound::Error,
149 };
150 TypeBound::Path(path)
151 }
152 ast::TypeBoundKind::ForType(_) | ast::TypeBoundKind::Lifetime(_) => TypeBound::Error,
153 }
154 }
155
156 pub fn as_path(&self) -> Option<&Path> {
157 match self {
158 TypeBound::Path(p) => Some(p),
159 _ => None,
160 }
161 }
162}