aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/adt.rs26
-rw-r--r--crates/ra_hir/src/code_model_api.rs128
-rw-r--r--crates/ra_hir/src/code_model_impl/function.rs7
-rw-r--r--crates/ra_hir/src/code_model_impl/krate.rs10
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs118
-rw-r--r--crates/ra_hir/src/db.rs32
-rw-r--r--crates/ra_hir/src/expr.rs80
-rw-r--r--crates/ra_hir/src/ids.rs23
-rw-r--r--crates/ra_hir/src/impl_block.rs16
-rw-r--r--crates/ra_hir/src/lib.rs9
-rw-r--r--crates/ra_hir/src/module_tree.rs35
-rw-r--r--crates/ra_hir/src/name.rs2
-rw-r--r--crates/ra_hir/src/nameres.rs48
-rw-r--r--crates/ra_hir/src/nameres/tests.rs28
-rw-r--r--crates/ra_hir/src/query_definitions.rs32
-rw-r--r--crates/ra_hir/src/source_binder.rs64
-rw-r--r--crates/ra_hir/src/ty.rs427
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs53
-rw-r--r--crates/ra_hir/src/ty/primitive.rs50
-rw-r--r--crates/ra_hir/src/ty/tests.rs69
-rw-r--r--crates/ra_hir/src/ty/tests/data/basics.txt8
-rw-r--r--crates/ra_hir/src/ty/tests/data/binary_op.txt86
-rw-r--r--crates/ra_hir/src/ty/tests/data/let.txt4
-rw-r--r--crates/ra_hir/src/ty/tests/data/literals.txt12
-rw-r--r--crates/ra_hir/src/ty/tests/data/struct.txt4
-rw-r--r--crates/ra_hir/src/ty/tests/data/tuple.txt18
-rw-r--r--crates/ra_hir/src/ty/tests/data/unary_op.txt28
27 files changed, 780 insertions, 637 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index bcb705c24..d87fe7049 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -1,6 +1,5 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_db::Cancelable;
4use ra_syntax::{ 3use ra_syntax::{
5 SyntaxNode, 4 SyntaxNode,
6 ast::{self, NameOwner, StructFlavor, AstNode} 5 ast::{self, NameOwner, StructFlavor, AstNode}
@@ -18,8 +17,8 @@ impl Struct {
18 Struct { def_id } 17 Struct { def_id }
19 } 18 }
20 19
21 pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<VariantData>> { 20 pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> {
22 Ok(db.struct_data(self.def_id)?.variant_data.clone()) 21 db.struct_data(self.def_id).variant_data.clone()
23 } 22 }
24} 23}
25 24
@@ -37,16 +36,13 @@ impl StructData {
37 StructData { name, variant_data } 36 StructData { name, variant_data }
38 } 37 }
39 38
40 pub(crate) fn struct_data_query( 39 pub(crate) fn struct_data_query(db: &impl HirDatabase, def_id: DefId) -> Arc<StructData> {
41 db: &impl HirDatabase,
42 def_id: DefId,
43 ) -> Cancelable<Arc<StructData>> {
44 let def_loc = def_id.loc(db); 40 let def_loc = def_id.loc(db);
45 assert!(def_loc.kind == DefKind::Struct); 41 assert!(def_loc.kind == DefKind::Struct);
46 let syntax = db.file_item(def_loc.source_item_id); 42 let syntax = db.file_item(def_loc.source_item_id);
47 let struct_def = 43 let struct_def =
48 ast::StructDef::cast(&syntax).expect("struct def should point to StructDef node"); 44 ast::StructDef::cast(&syntax).expect("struct def should point to StructDef node");
49 Ok(Arc::new(StructData::new(struct_def))) 45 Arc::new(StructData::new(struct_def))
50 } 46 }
51} 47}
52 48
@@ -84,10 +80,7 @@ impl EnumData {
84 EnumData { name, variants } 80 EnumData { name, variants }
85 } 81 }
86 82
87 pub(crate) fn enum_data_query( 83 pub(crate) fn enum_data_query(db: &impl HirDatabase, def_id: DefId) -> Arc<EnumData> {
88 db: &impl HirDatabase,
89 def_id: DefId,
90 ) -> Cancelable<Arc<EnumData>> {
91 let def_loc = def_id.loc(db); 84 let def_loc = def_id.loc(db);
92 assert!(def_loc.kind == DefKind::Enum); 85 assert!(def_loc.kind == DefKind::Enum);
93 let syntax = db.file_item(def_loc.source_item_id); 86 let syntax = db.file_item(def_loc.source_item_id);
@@ -107,7 +100,7 @@ impl EnumData {
107 } else { 100 } else {
108 Vec::new() 101 Vec::new()
109 }; 102 };
110 Ok(Arc::new(EnumData::new(enum_def, variants))) 103 Arc::new(EnumData::new(enum_def, variants))
111 } 104 }
112} 105}
113 106
@@ -133,7 +126,7 @@ impl EnumVariantData {
133 pub(crate) fn enum_variant_data_query( 126 pub(crate) fn enum_variant_data_query(
134 db: &impl HirDatabase, 127 db: &impl HirDatabase,
135 def_id: DefId, 128 def_id: DefId,
136 ) -> Cancelable<Arc<EnumVariantData>> { 129 ) -> Arc<EnumVariantData> {
137 let def_loc = def_id.loc(db); 130 let def_loc = def_id.loc(db);
138 assert!(def_loc.kind == DefKind::EnumVariant); 131 assert!(def_loc.kind == DefKind::EnumVariant);
139 let syntax = db.file_item(def_loc.source_item_id); 132 let syntax = db.file_item(def_loc.source_item_id);
@@ -146,10 +139,7 @@ impl EnumVariantData {
146 .expect("enum variant list should have enum ancestor"); 139 .expect("enum variant list should have enum ancestor");
147 let enum_def_id = get_def_id(db, &def_loc, enum_node, DefKind::Enum); 140 let enum_def_id = get_def_id(db, &def_loc, enum_node, DefKind::Enum);
148 141
149 Ok(Arc::new(EnumVariantData::new( 142 Arc::new(EnumVariantData::new(variant_def, Enum::new(enum_def_id)))
150 variant_def,
151 Enum::new(enum_def_id),
152 )))
153 } 143 }
154} 144}
155 145
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs
index 91b235594..0cf7deac9 100644
--- a/crates/ra_hir/src/code_model_api.rs
+++ b/crates/ra_hir/src/code_model_api.rs
@@ -1,7 +1,7 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use relative_path::RelativePathBuf; 3use relative_path::RelativePathBuf;
4use ra_db::{CrateId, Cancelable, FileId}; 4use ra_db::{CrateId, FileId};
5use ra_syntax::{ast, TreeArc, SyntaxNode}; 5use ra_syntax::{ast, TreeArc, SyntaxNode};
6 6
7use crate::{ 7use crate::{
@@ -33,10 +33,10 @@ impl Crate {
33 pub fn crate_id(&self) -> CrateId { 33 pub fn crate_id(&self) -> CrateId {
34 self.crate_id 34 self.crate_id
35 } 35 }
36 pub fn dependencies(&self, db: &impl HirDatabase) -> Cancelable<Vec<CrateDependency>> { 36 pub fn dependencies(&self, db: &impl HirDatabase) -> Vec<CrateDependency> {
37 Ok(self.dependencies_impl(db)) 37 self.dependencies_impl(db)
38 } 38 }
39 pub fn root_module(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { 39 pub fn root_module(&self, db: &impl HirDatabase) -> Option<Module> {
40 self.root_module_impl(db) 40 self.root_module_impl(db)
41 } 41 }
42} 42}
@@ -78,12 +78,12 @@ pub enum Problem {
78 78
79impl Module { 79impl Module {
80 /// Name of this module. 80 /// Name of this module.
81 pub fn name(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> { 81 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
82 self.name_impl(db) 82 self.name_impl(db)
83 } 83 }
84 84
85 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. 85 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
86 pub fn definition_source(&self, db: &impl HirDatabase) -> Cancelable<(FileId, ModuleSource)> { 86 pub fn definition_source(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) {
87 self.definition_source_impl(db) 87 self.definition_source_impl(db)
88 } 88 }
89 89
@@ -92,60 +92,57 @@ impl Module {
92 pub fn declaration_source( 92 pub fn declaration_source(
93 &self, 93 &self,
94 db: &impl HirDatabase, 94 db: &impl HirDatabase,
95 ) -> Cancelable<Option<(FileId, TreeArc<ast::Module>)>> { 95 ) -> Option<(FileId, TreeArc<ast::Module>)> {
96 self.declaration_source_impl(db) 96 self.declaration_source_impl(db)
97 } 97 }
98 98
99 /// Returns the crate this module is part of. 99 /// Returns the crate this module is part of.
100 pub fn krate(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> { 100 pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> {
101 self.krate_impl(db) 101 self.krate_impl(db)
102 } 102 }
103 103
104 /// Topmost parent of this module. Every module has a `crate_root`, but some 104 /// Topmost parent of this module. Every module has a `crate_root`, but some
105 /// might be missing `krate`. This can happen if a module's file is not included 105 /// might be missing `krate`. This can happen if a module's file is not included
106 /// in the module tree of any target in Cargo.toml. 106 /// in the module tree of any target in Cargo.toml.
107 pub fn crate_root(&self, db: &impl HirDatabase) -> Cancelable<Module> { 107 pub fn crate_root(&self, db: &impl HirDatabase) -> Module {
108 self.crate_root_impl(db) 108 self.crate_root_impl(db)
109 } 109 }
110 110
111 /// Finds a child module with the specified name. 111 /// Finds a child module with the specified name.
112 pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { 112 pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> {
113 self.child_impl(db, name) 113 self.child_impl(db, name)
114 } 114 }
115 115
116 /// Iterates over all child modules. 116 /// Iterates over all child modules.
117 pub fn children(&self, db: &impl HirDatabase) -> Cancelable<impl Iterator<Item = Module>> { 117 pub fn children(&self, db: &impl HirDatabase) -> impl Iterator<Item = Module> {
118 self.children_impl(db) 118 self.children_impl(db)
119 } 119 }
120 120
121 /// Finds a parent module. 121 /// Finds a parent module.
122 pub fn parent(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { 122 pub fn parent(&self, db: &impl HirDatabase) -> Option<Module> {
123 self.parent_impl(db) 123 self.parent_impl(db)
124 } 124 }
125 125
126 pub fn path_to_root(&self, db: &impl HirDatabase) -> Cancelable<Vec<Module>> { 126 pub fn path_to_root(&self, db: &impl HirDatabase) -> Vec<Module> {
127 let mut res = vec![self.clone()]; 127 let mut res = vec![self.clone()];
128 let mut curr = self.clone(); 128 let mut curr = self.clone();
129 while let Some(next) = curr.parent(db)? { 129 while let Some(next) = curr.parent(db) {
130 res.push(next.clone()); 130 res.push(next.clone());
131 curr = next 131 curr = next
132 } 132 }
133 Ok(res) 133 res
134 } 134 }
135 135
136 /// Returns a `ModuleScope`: a set of items, visible in this module. 136 /// Returns a `ModuleScope`: a set of items, visible in this module.
137 pub fn scope(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> { 137 pub fn scope(&self, db: &impl HirDatabase) -> ModuleScope {
138 self.scope_impl(db) 138 self.scope_impl(db)
139 } 139 }
140 140
141 pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> Cancelable<PerNs<DefId>> { 141 pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<DefId> {
142 self.resolve_path_impl(db, path) 142 self.resolve_path_impl(db, path)
143 } 143 }
144 144
145 pub fn problems( 145 pub fn problems(&self, db: &impl HirDatabase) -> Vec<(TreeArc<SyntaxNode>, Problem)> {
146 &self,
147 db: &impl HirDatabase,
148 ) -> Cancelable<Vec<(TreeArc<SyntaxNode>, Problem)>> {
149 self.problems_impl(db) 146 self.problems_impl(db)
150 } 147 }
151} 148}
@@ -160,7 +157,7 @@ impl StructField {
160 pub fn name(&self) -> &Name { 157 pub fn name(&self) -> &Name {
161 &self.name 158 &self.name
162 } 159 }
163 pub fn ty(&self, db: &impl HirDatabase) -> Cancelable<Option<Ty>> { 160 pub fn ty(&self, db: &impl HirDatabase) -> Option<Ty> {
164 db.type_for_field(self.struct_.def_id, self.name.clone()) 161 db.type_for_field(self.struct_.def_id, self.name.clone())
165 } 162 }
166} 163}
@@ -175,13 +172,12 @@ impl Struct {
175 self.def_id 172 self.def_id
176 } 173 }
177 174
178 pub fn name(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> { 175 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
179 Ok(db.struct_data(self.def_id)?.name.clone()) 176 db.struct_data(self.def_id).name.clone()
180 } 177 }
181 178
182 pub fn fields(&self, db: &impl HirDatabase) -> Cancelable<Vec<StructField>> { 179 pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> {
183 let res = db 180 db.struct_data(self.def_id)
184 .struct_data(self.def_id)?
185 .variant_data 181 .variant_data
186 .fields() 182 .fields()
187 .iter() 183 .iter()
@@ -189,15 +185,11 @@ impl Struct {
189 struct_: self.clone(), 185 struct_: self.clone(),
190 name: it.name.clone(), 186 name: it.name.clone(),
191 }) 187 })
192 .collect(); 188 .collect()
193 Ok(res)
194 } 189 }
195 190
196 pub fn source( 191 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) {
197 &self, 192 def_id_to_ast(db, self.def_id)
198 db: &impl HirDatabase,
199 ) -> Cancelable<(HirFileId, TreeArc<ast::StructDef>)> {
200 Ok(def_id_to_ast(db, self.def_id))
201 } 193 }
202} 194}
203 195
@@ -215,16 +207,16 @@ impl Enum {
215 self.def_id 207 self.def_id
216 } 208 }
217 209
218 pub fn name(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> { 210 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
219 Ok(db.enum_data(self.def_id)?.name.clone()) 211 db.enum_data(self.def_id).name.clone()
220 } 212 }
221 213
222 pub fn variants(&self, db: &impl HirDatabase) -> Cancelable<Vec<(Name, EnumVariant)>> { 214 pub fn variants(&self, db: &impl HirDatabase) -> Vec<(Name, EnumVariant)> {
223 Ok(db.enum_data(self.def_id)?.variants.clone()) 215 db.enum_data(self.def_id).variants.clone()
224 } 216 }
225 217
226 pub fn source(&self, db: &impl HirDatabase) -> Cancelable<(HirFileId, TreeArc<ast::EnumDef>)> { 218 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) {
227 Ok(def_id_to_ast(db, self.def_id)) 219 def_id_to_ast(db, self.def_id)
228 } 220 }
229} 221}
230 222
@@ -242,23 +234,20 @@ impl EnumVariant {
242 self.def_id 234 self.def_id
243 } 235 }
244 236
245 pub fn parent_enum(&self, db: &impl HirDatabase) -> Cancelable<Enum> { 237 pub fn parent_enum(&self, db: &impl HirDatabase) -> Enum {
246 Ok(db.enum_variant_data(self.def_id)?.parent_enum.clone()) 238 db.enum_variant_data(self.def_id).parent_enum.clone()
247 } 239 }
248 240
249 pub fn name(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> { 241 pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
250 Ok(db.enum_variant_data(self.def_id)?.name.clone()) 242 db.enum_variant_data(self.def_id).name.clone()
251 } 243 }
252 244
253 pub fn variant_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<VariantData>> { 245 pub fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> {
254 Ok(db.enum_variant_data(self.def_id)?.variant_data.clone()) 246 db.enum_variant_data(self.def_id).variant_data.clone()
255 } 247 }
256 248
257 pub fn source( 249 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumVariant>) {
258 &self, 250 def_id_to_ast(db, self.def_id)
259 db: &impl HirDatabase,
260 ) -> Cancelable<(HirFileId, TreeArc<ast::EnumVariant>)> {
261 Ok(def_id_to_ast(db, self.def_id))
262 } 251 }
263} 252}
264 253
@@ -305,28 +294,28 @@ impl Function {
305 self.def_id 294 self.def_id
306 } 295 }
307 296
308 pub fn source(&self, db: &impl HirDatabase) -> Cancelable<(HirFileId, TreeArc<ast::FnDef>)> { 297 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::FnDef>) {
309 Ok(def_id_to_ast(db, self.def_id)) 298 def_id_to_ast(db, self.def_id)
310 } 299 }
311 300
312 pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Cancelable<Arc<BodySyntaxMapping>> { 301 pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> {
313 db.body_syntax_mapping(self.def_id) 302 db.body_syntax_mapping(self.def_id)
314 } 303 }
315 304
316 pub fn scopes(&self, db: &impl HirDatabase) -> Cancelable<ScopesWithSyntaxMapping> { 305 pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping {
317 let scopes = db.fn_scopes(self.def_id)?; 306 let scopes = db.fn_scopes(self.def_id);
318 let syntax_mapping = db.body_syntax_mapping(self.def_id)?; 307 let syntax_mapping = db.body_syntax_mapping(self.def_id);
319 Ok(ScopesWithSyntaxMapping { 308 ScopesWithSyntaxMapping {
320 scopes, 309 scopes,
321 syntax_mapping, 310 syntax_mapping,
322 }) 311 }
323 } 312 }
324 313
325 pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> { 314 pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> {
326 db.fn_signature(self.def_id) 315 db.fn_signature(self.def_id)
327 } 316 }
328 317
329 pub fn infer(&self, db: &impl HirDatabase) -> Cancelable<Arc<InferenceResult>> { 318 pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
330 db.infer(self.def_id) 319 db.infer(self.def_id)
331 } 320 }
332} 321}
@@ -341,8 +330,8 @@ impl Const {
341 Const { def_id } 330 Const { def_id }
342 } 331 }
343 332
344 pub fn source(&self, db: &impl HirDatabase) -> Cancelable<(HirFileId, TreeArc<ast::ConstDef>)> { 333 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::ConstDef>) {
345 Ok(def_id_to_ast(db, self.def_id)) 334 def_id_to_ast(db, self.def_id)
346 } 335 }
347} 336}
348 337
@@ -356,11 +345,8 @@ impl Static {
356 Static { def_id } 345 Static { def_id }
357 } 346 }
358 347
359 pub fn source( 348 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StaticDef>) {
360 &self, 349 def_id_to_ast(db, self.def_id)
361 db: &impl HirDatabase,
362 ) -> Cancelable<(HirFileId, TreeArc<ast::StaticDef>)> {
363 Ok(def_id_to_ast(db, self.def_id))
364 } 350 }
365} 351}
366 352
@@ -374,8 +360,8 @@ impl Trait {
374 Trait { def_id } 360 Trait { def_id }
375 } 361 }
376 362
377 pub fn source(&self, db: &impl HirDatabase) -> Cancelable<(HirFileId, TreeArc<ast::TraitDef>)> { 363 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TraitDef>) {
378 Ok(def_id_to_ast(db, self.def_id)) 364 def_id_to_ast(db, self.def_id)
379 } 365 }
380} 366}
381 367
@@ -389,7 +375,7 @@ impl Type {
389 Type { def_id } 375 Type { def_id }
390 } 376 }
391 377
392 pub fn source(&self, db: &impl HirDatabase) -> Cancelable<(HirFileId, TreeArc<ast::TypeDef>)> { 378 pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TypeDef>) {
393 Ok(def_id_to_ast(db, self.def_id)) 379 def_id_to_ast(db, self.def_id)
394 } 380 }
395} 381}
diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs
index 8d6b7fc19..66d7e1713 100644
--- a/crates/ra_hir/src/code_model_impl/function.rs
+++ b/crates/ra_hir/src/code_model_impl/function.rs
@@ -2,7 +2,6 @@ mod scope;
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use ra_db::Cancelable;
6use ra_syntax::{TreeArc, ast::{self, NameOwner}}; 5use ra_syntax::{TreeArc, ast::{self, NameOwner}};
7 6
8use crate::{ 7use crate::{
@@ -20,16 +19,16 @@ impl Function {
20 Function { def_id } 19 Function { def_id }
21 } 20 }
22 21
23 pub(crate) fn body(&self, db: &impl HirDatabase) -> Cancelable<Arc<Body>> { 22 pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
24 db.body_hir(self.def_id) 23 db.body_hir(self.def_id)
25 } 24 }
26 25
27 pub(crate) fn module(&self, db: &impl HirDatabase) -> Cancelable<Module> { 26 pub(crate) fn module(&self, db: &impl HirDatabase) -> Module {
28 self.def_id.module(db) 27 self.def_id.module(db)
29 } 28 }
30 29
31 /// The containing impl block, if this is a method. 30 /// The containing impl block, if this is a method.
32 pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Cancelable<Option<ImplBlock>> { 31 pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option<ImplBlock> {
33 self.def_id.impl_block(db) 32 self.def_id.impl_block(db)
34 } 33 }
35} 34}
diff --git a/crates/ra_hir/src/code_model_impl/krate.rs b/crates/ra_hir/src/code_model_impl/krate.rs
index 3275eafed..8c6e34873 100644
--- a/crates/ra_hir/src/code_model_impl/krate.rs
+++ b/crates/ra_hir/src/code_model_impl/krate.rs
@@ -1,4 +1,4 @@
1use ra_db::{CrateId, Cancelable}; 1use ra_db::CrateId;
2 2
3use crate::{ 3use crate::{
4 HirFileId, Crate, CrateDependency, AsName, DefLoc, DefKind, Module, SourceItemId, 4 HirFileId, Crate, CrateDependency, AsName, DefLoc, DefKind, Module, SourceItemId,
@@ -20,18 +20,18 @@ impl Crate {
20 }) 20 })
21 .collect() 21 .collect()
22 } 22 }
23 pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { 23 pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Option<Module> {
24 let crate_graph = db.crate_graph(); 24 let crate_graph = db.crate_graph();
25 let file_id = crate_graph.crate_root(self.crate_id); 25 let file_id = crate_graph.crate_root(self.crate_id);
26 let source_root_id = db.file_source_root(file_id); 26 let source_root_id = db.file_source_root(file_id);
27 let file_id = HirFileId::from(file_id); 27 let file_id = HirFileId::from(file_id);
28 let module_tree = db.module_tree(source_root_id)?; 28 let module_tree = db.module_tree(source_root_id);
29 // FIXME: teach module tree about crate roots instead of guessing 29 // FIXME: teach module tree about crate roots instead of guessing
30 let source = SourceItemId { 30 let source = SourceItemId {
31 file_id, 31 file_id,
32 item_id: None, 32 item_id: None,
33 }; 33 };
34 let module_id = ctry!(module_tree.find_module_by_source(source)); 34 let module_id = module_tree.find_module_by_source(source)?;
35 35
36 let def_loc = DefLoc { 36 let def_loc = DefLoc {
37 kind: DefKind::Module, 37 kind: DefKind::Module,
@@ -42,6 +42,6 @@ impl Crate {
42 let def_id = def_loc.id(db); 42 let def_id = def_loc.id(db);
43 43
44 let module = Module::new(def_id); 44 let module = Module::new(def_id);
45 Ok(Some(module)) 45 Some(module)
46 } 46 }
47} 47}
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index 775dd6709..a5c032d69 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -1,4 +1,4 @@
1use ra_db::{Cancelable, SourceRootId, FileId}; 1use ra_db::{SourceRootId, FileId};
2use ra_syntax::{ast, SyntaxNode, AstNode, TreeArc}; 2use ra_syntax::{ast, SyntaxNode, AstNode, TreeArc};
3 3
4use crate::{ 4use crate::{
@@ -18,8 +18,8 @@ impl Module {
18 db: &impl HirDatabase, 18 db: &impl HirDatabase,
19 source_root_id: SourceRootId, 19 source_root_id: SourceRootId,
20 module_id: ModuleId, 20 module_id: ModuleId,
21 ) -> Cancelable<Self> { 21 ) -> Self {
22 let module_tree = db.module_tree(source_root_id)?; 22 let module_tree = db.module_tree(source_root_id);
23 let def_loc = DefLoc { 23 let def_loc = DefLoc {
24 kind: DefKind::Module, 24 kind: DefKind::Module,
25 source_root_id, 25 source_root_id,
@@ -27,21 +27,17 @@ impl Module {
27 source_item_id: module_id.source(&module_tree), 27 source_item_id: module_id.source(&module_tree),
28 }; 28 };
29 let def_id = def_loc.id(db); 29 let def_id = def_loc.id(db);
30 let module = Module::new(def_id); 30 Module::new(def_id)
31 Ok(module)
32 } 31 }
33 32
34 pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Name>> { 33 pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Option<Name> {
35 let loc = self.def_id.loc(db); 34 let loc = self.def_id.loc(db);
36 let module_tree = db.module_tree(loc.source_root_id)?; 35 let module_tree = db.module_tree(loc.source_root_id);
37 let link = ctry!(loc.module_id.parent_link(&module_tree)); 36 let link = loc.module_id.parent_link(&module_tree)?;
38 Ok(Some(link.name(&module_tree).clone())) 37 Some(link.name(&module_tree).clone())
39 } 38 }
40 39
41 pub fn definition_source_impl( 40 pub fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) {
42 &self,
43 db: &impl HirDatabase,
44 ) -> Cancelable<(FileId, ModuleSource)> {
45 let loc = self.def_id.loc(db); 41 let loc = self.def_id.loc(db);
46 let file_id = loc.source_item_id.file_id.as_original_file(); 42 let file_id = loc.source_item_id.file_id.as_original_file();
47 let syntax_node = db.file_item(loc.source_item_id); 43 let syntax_node = db.file_item(loc.source_item_id);
@@ -51,94 +47,89 @@ impl Module {
51 let module = ast::Module::cast(&syntax_node).unwrap(); 47 let module = ast::Module::cast(&syntax_node).unwrap();
52 ModuleSource::Module(module.to_owned()) 48 ModuleSource::Module(module.to_owned())
53 }; 49 };
54 Ok((file_id, module_source)) 50 (file_id, module_source)
55 } 51 }
56 52
57 pub fn declaration_source_impl( 53 pub fn declaration_source_impl(
58 &self, 54 &self,
59 db: &impl HirDatabase, 55 db: &impl HirDatabase,
60 ) -> Cancelable<Option<(FileId, TreeArc<ast::Module>)>> { 56 ) -> Option<(FileId, TreeArc<ast::Module>)> {
61 let loc = self.def_id.loc(db); 57 let loc = self.def_id.loc(db);
62 let module_tree = db.module_tree(loc.source_root_id)?; 58 let module_tree = db.module_tree(loc.source_root_id);
63 let link = ctry!(loc.module_id.parent_link(&module_tree)); 59 let link = loc.module_id.parent_link(&module_tree)?;
64 let file_id = link 60 let file_id = link
65 .owner(&module_tree) 61 .owner(&module_tree)
66 .source(&module_tree) 62 .source(&module_tree)
67 .file_id 63 .file_id
68 .as_original_file(); 64 .as_original_file();
69 let src = link.source(&module_tree, db); 65 let src = link.source(&module_tree, db);
70 Ok(Some((file_id, src))) 66 Some((file_id, src))
71 } 67 }
72 68
73 pub(crate) fn krate_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> { 69 pub(crate) fn krate_impl(&self, db: &impl HirDatabase) -> Option<Crate> {
74 let root = self.crate_root(db)?; 70 let root = self.crate_root(db);
75 let loc = root.def_id.loc(db); 71 let loc = root.def_id.loc(db);
76 let file_id = loc.source_item_id.file_id.as_original_file(); 72 let file_id = loc.source_item_id.file_id.as_original_file();
77 73
78 let crate_graph = db.crate_graph(); 74 let crate_graph = db.crate_graph();
79 let crate_id = ctry!(crate_graph.crate_id_for_crate_root(file_id)); 75 let crate_id = crate_graph.crate_id_for_crate_root(file_id)?;
80 Ok(Some(Crate::new(crate_id))) 76 Some(Crate::new(crate_id))
81 } 77 }
82 78
83 pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Cancelable<Module> { 79 pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Module {
84 let loc = self.def_id.loc(db); 80 let loc = self.def_id.loc(db);
85 let module_tree = db.module_tree(loc.source_root_id)?; 81 let module_tree = db.module_tree(loc.source_root_id);
86 let module_id = loc.module_id.crate_root(&module_tree); 82 let module_id = loc.module_id.crate_root(&module_tree);
87 Module::from_module_id(db, loc.source_root_id, module_id) 83 Module::from_module_id(db, loc.source_root_id, module_id)
88 } 84 }
89 85
90 /// Finds a child module with the specified name. 86 /// Finds a child module with the specified name.
91 pub fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { 87 pub fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> {
92 let loc = self.def_id.loc(db); 88 let loc = self.def_id.loc(db);
93 let module_tree = db.module_tree(loc.source_root_id)?; 89 let module_tree = db.module_tree(loc.source_root_id);
94 let child_id = ctry!(loc.module_id.child(&module_tree, name)); 90 let child_id = loc.module_id.child(&module_tree, name)?;
95 Module::from_module_id(db, loc.source_root_id, child_id).map(Some) 91 Some(Module::from_module_id(db, loc.source_root_id, child_id))
96 } 92 }
97 93
98 /// Iterates over all child modules. 94 /// Iterates over all child modules.
99 pub fn children_impl(&self, db: &impl HirDatabase) -> Cancelable<impl Iterator<Item = Module>> { 95 pub fn children_impl(&self, db: &impl HirDatabase) -> impl Iterator<Item = Module> {
100 // FIXME this should be implementable without collecting into a vec, but 96 // FIXME this should be implementable without collecting into a vec, but
101 // it's kind of hard since the iterator needs to keep a reference to the 97 // it's kind of hard since the iterator needs to keep a reference to the
102 // module tree. 98 // module tree.
103 let loc = self.def_id.loc(db); 99 let loc = self.def_id.loc(db);
104 let module_tree = db.module_tree(loc.source_root_id)?; 100 let module_tree = db.module_tree(loc.source_root_id);
105 let children = loc 101 let children = loc
106 .module_id 102 .module_id
107 .children(&module_tree) 103 .children(&module_tree)
108 .map(|(_, module_id)| Module::from_module_id(db, loc.source_root_id, module_id)) 104 .map(|(_, module_id)| Module::from_module_id(db, loc.source_root_id, module_id))
109 .collect::<Cancelable<Vec<_>>>()?; 105 .collect::<Vec<_>>();
110 Ok(children.into_iter()) 106 children.into_iter()
111 } 107 }
112 108
113 pub fn parent_impl(&self, db: &impl HirDatabase) -> Cancelable<Option<Module>> { 109 pub fn parent_impl(&self, db: &impl HirDatabase) -> Option<Module> {
114 let loc = self.def_id.loc(db); 110 let loc = self.def_id.loc(db);
115 let module_tree = db.module_tree(loc.source_root_id)?; 111 let module_tree = db.module_tree(loc.source_root_id);
116 let parent_id = ctry!(loc.module_id.parent(&module_tree)); 112 let parent_id = loc.module_id.parent(&module_tree)?;
117 Module::from_module_id(db, loc.source_root_id, parent_id).map(Some) 113 Some(Module::from_module_id(db, loc.source_root_id, parent_id))
118 } 114 }
119 115
120 /// Returns a `ModuleScope`: a set of items, visible in this module. 116 /// Returns a `ModuleScope`: a set of items, visible in this module.
121 pub fn scope_impl(&self, db: &impl HirDatabase) -> Cancelable<ModuleScope> { 117 pub fn scope_impl(&self, db: &impl HirDatabase) -> ModuleScope {
122 let loc = self.def_id.loc(db); 118 let loc = self.def_id.loc(db);
123 let item_map = db.item_map(loc.source_root_id)?; 119 let item_map = db.item_map(loc.source_root_id);
124 let res = item_map.per_module[&loc.module_id].clone(); 120 item_map.per_module[&loc.module_id].clone()
125 Ok(res)
126 } 121 }
127 122
128 pub fn resolve_path_impl( 123 pub fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs<DefId> {
129 &self,
130 db: &impl HirDatabase,
131 path: &Path,
132 ) -> Cancelable<PerNs<DefId>> {
133 let mut curr_per_ns = PerNs::types( 124 let mut curr_per_ns = PerNs::types(
134 match path.kind { 125 match path.kind {
135 PathKind::Crate => self.crate_root(db)?, 126 PathKind::Crate => self.crate_root(db),
136 PathKind::Self_ | PathKind::Plain => self.clone(), 127 PathKind::Self_ | PathKind::Plain => self.clone(),
137 PathKind::Super => { 128 PathKind::Super => {
138 if let Some(p) = self.parent(db)? { 129 if let Some(p) = self.parent(db) {
139 p 130 p
140 } else { 131 } else {
141 return Ok(PerNs::none()); 132 return PerNs::none();
142 } 133 }
143 } 134 }
144 } 135 }
@@ -150,47 +141,44 @@ impl Module {
150 let curr = if let Some(r) = curr_per_ns.as_ref().take_types() { 141 let curr = if let Some(r) = curr_per_ns.as_ref().take_types() {
151 r 142 r
152 } else { 143 } else {
153 return Ok(PerNs::none()); 144 return PerNs::none();
154 }; 145 };
155 let module = match curr.resolve(db)? { 146 let module = match curr.resolve(db) {
156 Def::Module(it) => it, 147 Def::Module(it) => it,
157 Def::Enum(e) => { 148 Def::Enum(e) => {
158 if segments.len() == idx + 1 { 149 if segments.len() == idx + 1 {
159 // enum variant 150 // enum variant
160 let matching_variant = 151 let matching_variant =
161 e.variants(db)?.into_iter().find(|(n, _variant)| n == name); 152 e.variants(db).into_iter().find(|(n, _variant)| n == name);
162 153
163 if let Some((_n, variant)) = matching_variant { 154 if let Some((_n, variant)) = matching_variant {
164 return Ok(PerNs::both(variant.def_id(), e.def_id())); 155 return PerNs::both(variant.def_id(), e.def_id());
165 } else { 156 } else {
166 return Ok(PerNs::none()); 157 return PerNs::none();
167 } 158 }
168 } else if segments.len() == idx { 159 } else if segments.len() == idx {
169 // enum 160 // enum
170 return Ok(PerNs::types(e.def_id())); 161 return PerNs::types(e.def_id());
171 } else { 162 } else {
172 // malformed enum? 163 // malformed enum?
173 return Ok(PerNs::none()); 164 return PerNs::none();
174 } 165 }
175 } 166 }
176 _ => return Ok(PerNs::none()), 167 _ => return PerNs::none(),
177 }; 168 };
178 let scope = module.scope(db)?; 169 let scope = module.scope(db);
179 curr_per_ns = if let Some(r) = scope.get(&name) { 170 curr_per_ns = if let Some(r) = scope.get(&name) {
180 r.def_id 171 r.def_id
181 } else { 172 } else {
182 return Ok(PerNs::none()); 173 return PerNs::none();
183 }; 174 };
184 } 175 }
185 Ok(curr_per_ns) 176 curr_per_ns
186 } 177 }
187 178
188 pub fn problems_impl( 179 pub fn problems_impl(&self, db: &impl HirDatabase) -> Vec<(TreeArc<SyntaxNode>, Problem)> {
189 &self,
190 db: &impl HirDatabase,
191 ) -> Cancelable<Vec<(TreeArc<SyntaxNode>, Problem)>> {
192 let loc = self.def_id.loc(db); 180 let loc = self.def_id.loc(db);
193 let module_tree = db.module_tree(loc.source_root_id)?; 181 let module_tree = db.module_tree(loc.source_root_id);
194 Ok(loc.module_id.problems(&module_tree, db)) 182 loc.module_id.problems(&module_tree, db)
195 } 183 }
196} 184}
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index fd6336dd8..0a0994f5f 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,7 +1,7 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; 3use ra_syntax::{SyntaxNode, TreeArc, SourceFile};
4use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase, Cancelable}; 4use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase};
5 5
6use crate::{ 6use crate::{
7 DefLoc, DefId, MacroCallLoc, MacroCallId, Name, HirFileId, 7 DefLoc, DefId, MacroCallLoc, MacroCallId, Name, HirFileId,
@@ -32,37 +32,37 @@ pub trait HirDatabase: SyntaxDatabase
32 use fn crate::macros::expand_macro_invocation; 32 use fn crate::macros::expand_macro_invocation;
33 } 33 }
34 34
35 fn fn_scopes(def_id: DefId) -> Cancelable<Arc<FnScopes>> { 35 fn fn_scopes(def_id: DefId) -> Arc<FnScopes> {
36 type FnScopesQuery; 36 type FnScopesQuery;
37 use fn query_definitions::fn_scopes; 37 use fn query_definitions::fn_scopes;
38 } 38 }
39 39
40 fn struct_data(def_id: DefId) -> Cancelable<Arc<StructData>> { 40 fn struct_data(def_id: DefId) -> Arc<StructData> {
41 type StructDataQuery; 41 type StructDataQuery;
42 use fn crate::adt::StructData::struct_data_query; 42 use fn crate::adt::StructData::struct_data_query;
43 } 43 }
44 44
45 fn enum_data(def_id: DefId) -> Cancelable<Arc<EnumData>> { 45 fn enum_data(def_id: DefId) -> Arc<EnumData> {
46 type EnumDataQuery; 46 type EnumDataQuery;
47 use fn crate::adt::EnumData::enum_data_query; 47 use fn crate::adt::EnumData::enum_data_query;
48 } 48 }
49 49
50 fn enum_variant_data(def_id: DefId) -> Cancelable<Arc<EnumVariantData>> { 50 fn enum_variant_data(def_id: DefId) -> Arc<EnumVariantData> {
51 type EnumVariantDataQuery; 51 type EnumVariantDataQuery;
52 use fn crate::adt::EnumVariantData::enum_variant_data_query; 52 use fn crate::adt::EnumVariantData::enum_variant_data_query;
53 } 53 }
54 54
55 fn infer(def_id: DefId) -> Cancelable<Arc<InferenceResult>> { 55 fn infer(def_id: DefId) -> Arc<InferenceResult> {
56 type InferQuery; 56 type InferQuery;
57 use fn crate::ty::infer; 57 use fn crate::ty::infer;
58 } 58 }
59 59
60 fn type_for_def(def_id: DefId) -> Cancelable<Ty> { 60 fn type_for_def(def_id: DefId) -> Ty {
61 type TypeForDefQuery; 61 type TypeForDefQuery;
62 use fn crate::ty::type_for_def; 62 use fn crate::ty::type_for_def;
63 } 63 }
64 64
65 fn type_for_field(def_id: DefId, field: Name) -> Cancelable<Option<Ty>> { 65 fn type_for_field(def_id: DefId, field: Name) -> Option<Ty> {
66 type TypeForFieldQuery; 66 type TypeForFieldQuery;
67 use fn crate::ty::type_for_field; 67 use fn crate::ty::type_for_field;
68 } 68 }
@@ -77,42 +77,42 @@ pub trait HirDatabase: SyntaxDatabase
77 use fn query_definitions::file_item; 77 use fn query_definitions::file_item;
78 } 78 }
79 79
80 fn submodules(source: SourceItemId) -> Cancelable<Arc<Vec<crate::module_tree::Submodule>>> { 80 fn submodules(source: SourceItemId) -> Arc<Vec<crate::module_tree::Submodule>> {
81 type SubmodulesQuery; 81 type SubmodulesQuery;
82 use fn crate::module_tree::Submodule::submodules_query; 82 use fn crate::module_tree::Submodule::submodules_query;
83 } 83 }
84 84
85 fn input_module_items(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<InputModuleItems>> { 85 fn input_module_items(source_root_id: SourceRootId, module_id: ModuleId) -> Arc<InputModuleItems> {
86 type InputModuleItemsQuery; 86 type InputModuleItemsQuery;
87 use fn query_definitions::input_module_items; 87 use fn query_definitions::input_module_items;
88 } 88 }
89 89
90 fn item_map(source_root_id: SourceRootId) -> Cancelable<Arc<ItemMap>> { 90 fn item_map(source_root_id: SourceRootId) -> Arc<ItemMap> {
91 type ItemMapQuery; 91 type ItemMapQuery;
92 use fn query_definitions::item_map; 92 use fn query_definitions::item_map;
93 } 93 }
94 94
95 fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> { 95 fn module_tree(source_root_id: SourceRootId) -> Arc<ModuleTree> {
96 type ModuleTreeQuery; 96 type ModuleTreeQuery;
97 use fn crate::module_tree::ModuleTree::module_tree_query; 97 use fn crate::module_tree::ModuleTree::module_tree_query;
98 } 98 }
99 99
100 fn impls_in_module(source_root_id: SourceRootId, module_id: ModuleId) -> Cancelable<Arc<ModuleImplBlocks>> { 100 fn impls_in_module(source_root_id: SourceRootId, module_id: ModuleId) -> Arc<ModuleImplBlocks> {
101 type ImplsInModuleQuery; 101 type ImplsInModuleQuery;
102 use fn crate::impl_block::impls_in_module; 102 use fn crate::impl_block::impls_in_module;
103 } 103 }
104 104
105 fn impls_in_crate(krate: Crate) -> Cancelable<Arc<CrateImplBlocks>> { 105 fn impls_in_crate(krate: Crate) -> Arc<CrateImplBlocks> {
106 type ImplsInCrateQuery; 106 type ImplsInCrateQuery;
107 use fn crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query; 107 use fn crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query;
108 } 108 }
109 109
110 fn body_hir(def_id: DefId) -> Cancelable<Arc<crate::expr::Body>> { 110 fn body_hir(def_id: DefId) -> Arc<crate::expr::Body> {
111 type BodyHirQuery; 111 type BodyHirQuery;
112 use fn crate::expr::body_hir; 112 use fn crate::expr::body_hir;
113 } 113 }
114 114
115 fn body_syntax_mapping(def_id: DefId) -> Cancelable<Arc<crate::expr::BodySyntaxMapping>> { 115 fn body_syntax_mapping(def_id: DefId) -> Arc<crate::expr::BodySyntaxMapping> {
116 type BodySyntaxMappingQuery; 116 type BodySyntaxMappingQuery;
117 use fn crate::expr::body_syntax_mapping; 117 use fn crate::expr::body_syntax_mapping;
118 } 118 }
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index f0936e9f3..663338844 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -4,10 +4,11 @@ use std::sync::Arc;
4use rustc_hash::FxHashMap; 4use rustc_hash::FxHashMap;
5 5
6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; 6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
7use ra_db::{LocalSyntaxPtr, Cancelable}; 7use ra_db::LocalSyntaxPtr;
8use ra_syntax::ast::{self, AstNode, LoopBodyOwner, ArgListOwner, NameOwner}; 8use ra_syntax::ast::{self, AstNode, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor};
9 9
10use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName}; 10use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName};
11use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy};
11 12
12#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub struct ExprId(RawId); 14pub struct ExprId(RawId);
@@ -104,6 +105,16 @@ impl BodySyntaxMapping {
104} 105}
105 106
106#[derive(Debug, Clone, Eq, PartialEq)] 107#[derive(Debug, Clone, Eq, PartialEq)]
108pub enum Literal {
109 String(String),
110 ByteString(Vec<u8>),
111 Char(char),
112 Bool(bool),
113 Int(u64, UncertainIntTy),
114 Float(u64, UncertainFloatTy), // FIXME: f64 is not Eq
115}
116
117#[derive(Debug, Clone, Eq, PartialEq)]
107pub enum Expr { 118pub enum Expr {
108 /// This is produced if syntax tree does not have a required expression piece. 119 /// This is produced if syntax tree does not have a required expression piece.
109 Missing, 120 Missing,
@@ -171,7 +182,7 @@ pub enum Expr {
171 }, 182 },
172 UnaryOp { 183 UnaryOp {
173 expr: ExprId, 184 expr: ExprId,
174 op: Option<UnaryOp>, 185 op: UnaryOp,
175 }, 186 },
176 BinaryOp { 187 BinaryOp {
177 lhs: ExprId, 188 lhs: ExprId,
@@ -186,6 +197,7 @@ pub enum Expr {
186 Tuple { 197 Tuple {
187 exprs: Vec<ExprId>, 198 exprs: Vec<ExprId>,
188 }, 199 },
200 Literal(Literal),
189} 201}
190 202
191pub use ra_syntax::ast::PrefixOp as UnaryOp; 203pub use ra_syntax::ast::PrefixOp as UnaryOp;
@@ -305,6 +317,7 @@ impl Expr {
305 f(*expr); 317 f(*expr);
306 } 318 }
307 } 319 }
320 Expr::Literal(_) => {}
308 } 321 }
309 } 322 }
310} 323}
@@ -343,8 +356,8 @@ impl Pat {
343 356
344// Queries 357// Queries
345 358
346pub(crate) fn body_hir(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<Body>> { 359pub(crate) fn body_hir(db: &impl HirDatabase, def_id: DefId) -> Arc<Body> {
347 Ok(Arc::clone(&body_syntax_mapping(db, def_id)?.body)) 360 Arc::clone(&body_syntax_mapping(db, def_id).body)
348} 361}
349 362
350struct ExprCollector { 363struct ExprCollector {
@@ -599,8 +612,11 @@ impl ExprCollector {
599 } 612 }
600 ast::ExprKind::PrefixExpr(e) => { 613 ast::ExprKind::PrefixExpr(e) => {
601 let expr = self.collect_expr_opt(e.expr()); 614 let expr = self.collect_expr_opt(e.expr());
602 let op = e.op(); 615 if let Some(op) = e.op() {
603 self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr) 616 self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr)
617 } else {
618 self.alloc_expr(Expr::Missing, syntax_ptr)
619 }
604 } 620 }
605 ast::ExprKind::LambdaExpr(e) => { 621 ast::ExprKind::LambdaExpr(e) => {
606 let mut args = Vec::new(); 622 let mut args = Vec::new();
@@ -633,13 +649,50 @@ impl ExprCollector {
633 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect(); 649 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect();
634 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr) 650 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
635 } 651 }
652 ast::ExprKind::Literal(e) => {
653 let child = if let Some(child) = e.literal_expr() {
654 child
655 } else {
656 return self.alloc_expr(Expr::Missing, syntax_ptr);
657 };
658
659 let lit = match child.flavor() {
660 LiteralFlavor::IntNumber { suffix } => {
661 let known_name = suffix
662 .map(|s| Name::new(s))
663 .and_then(|name| UncertainIntTy::from_name(&name));
664
665 Literal::Int(
666 Default::default(),
667 known_name.unwrap_or(UncertainIntTy::Unknown),
668 )
669 }
670 LiteralFlavor::FloatNumber { suffix } => {
671 let known_name = suffix
672 .map(|s| Name::new(s))
673 .and_then(|name| UncertainFloatTy::from_name(&name));
674
675 Literal::Float(
676 Default::default(),
677 known_name.unwrap_or(UncertainFloatTy::Unknown),
678 )
679 }
680 LiteralFlavor::ByteString => Literal::ByteString(Default::default()),
681 LiteralFlavor::String => Literal::String(Default::default()),
682 LiteralFlavor::Byte => {
683 Literal::Int(Default::default(), UncertainIntTy::Unsigned(UintTy::U8))
684 }
685 LiteralFlavor::Bool => Literal::Bool(Default::default()),
686 LiteralFlavor::Char => Literal::Char(Default::default()),
687 };
688 self.alloc_expr(Expr::Literal(lit), syntax_ptr)
689 }
636 690
637 // TODO implement HIR for these: 691 // TODO implement HIR for these:
638 ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 692 ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
639 ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 693 ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
640 ast::ExprKind::ArrayExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 694 ast::ExprKind::ArrayExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
641 ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 695 ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
642 ast::ExprKind::Literal(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
643 } 696 }
644 } 697 }
645 698
@@ -776,17 +829,14 @@ pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping {
776 collector.into_body_syntax_mapping(params, body) 829 collector.into_body_syntax_mapping(params, body)
777} 830}
778 831
779pub(crate) fn body_syntax_mapping( 832pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, def_id: DefId) -> Arc<BodySyntaxMapping> {
780 db: &impl HirDatabase, 833 let def = def_id.resolve(db);
781 def_id: DefId,
782) -> Cancelable<Arc<BodySyntaxMapping>> {
783 let def = def_id.resolve(db)?;
784 834
785 let body_syntax_mapping = match def { 835 let body_syntax_mapping = match def {
786 Def::Function(f) => collect_fn_body_syntax(&f.source(db)?.1), 836 Def::Function(f) => collect_fn_body_syntax(&f.source(db).1),
787 // TODO: consts, etc. 837 // TODO: consts, etc.
788 _ => panic!("Trying to get body for item type without body"), 838 _ => panic!("Trying to get body for item type without body"),
789 }; 839 };
790 840
791 Ok(Arc::new(body_syntax_mapping)) 841 Arc::new(body_syntax_mapping)
792} 842}
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 316896dce..0d8e67547 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -1,4 +1,4 @@
1use ra_db::{SourceRootId, LocationIntener, Cancelable, FileId}; 1use ra_db::{SourceRootId, LocationIntener, FileId};
2use ra_syntax::{TreeArc, SyntaxKind, SyntaxNode, SourceFile, AstNode, ast}; 2use ra_syntax::{TreeArc, SyntaxKind, SyntaxNode, SourceFile, AstNode, ast};
3use ra_arena::{Arena, RawId, impl_arena_id}; 3use ra_arena::{Arena, RawId, impl_arena_id};
4 4
@@ -159,11 +159,11 @@ impl DefId {
159 db.as_ref().id2loc(self) 159 db.as_ref().id2loc(self)
160 } 160 }
161 161
162 pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> { 162 pub fn resolve(self, db: &impl HirDatabase) -> Def {
163 let loc = self.loc(db); 163 let loc = self.loc(db);
164 let res = match loc.kind { 164 match loc.kind {
165 DefKind::Module => { 165 DefKind::Module => {
166 let module = Module::from_module_id(db, loc.source_root_id, loc.module_id)?; 166 let module = Module::from_module_id(db, loc.source_root_id, loc.module_id);
167 Def::Module(module) 167 Def::Module(module)
168 } 168 }
169 DefKind::Function => { 169 DefKind::Function => {
@@ -195,8 +195,7 @@ impl DefId {
195 195
196 DefKind::StructCtor => Def::Item, 196 DefKind::StructCtor => Def::Item,
197 DefKind::Item => Def::Item, 197 DefKind::Item => Def::Item,
198 }; 198 }
199 Ok(res)
200 } 199 }
201 200
202 pub(crate) fn source(self, db: &impl HirDatabase) -> (HirFileId, TreeArc<SyntaxNode>) { 201 pub(crate) fn source(self, db: &impl HirDatabase) -> (HirFileId, TreeArc<SyntaxNode>) {
@@ -206,21 +205,21 @@ impl DefId {
206 } 205 }
207 206
208 /// For a module, returns that module; for any other def, returns the containing module. 207 /// For a module, returns that module; for any other def, returns the containing module.
209 pub fn module(self, db: &impl HirDatabase) -> Cancelable<Module> { 208 pub fn module(self, db: &impl HirDatabase) -> Module {
210 let loc = self.loc(db); 209 let loc = self.loc(db);
211 Module::from_module_id(db, loc.source_root_id, loc.module_id) 210 Module::from_module_id(db, loc.source_root_id, loc.module_id)
212 } 211 }
213 212
214 /// Returns the containing crate. 213 /// Returns the containing crate.
215 pub fn krate(&self, db: &impl HirDatabase) -> Cancelable<Option<Crate>> { 214 pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> {
216 Ok(self.module(db)?.krate(db)?) 215 self.module(db).krate(db)
217 } 216 }
218 217
219 /// Returns the containing impl block, if this is an impl item. 218 /// Returns the containing impl block, if this is an impl item.
220 pub fn impl_block(self, db: &impl HirDatabase) -> Cancelable<Option<ImplBlock>> { 219 pub fn impl_block(self, db: &impl HirDatabase) -> Option<ImplBlock> {
221 let loc = self.loc(db); 220 let loc = self.loc(db);
222 let module_impls = db.impls_in_module(loc.source_root_id, loc.module_id)?; 221 let module_impls = db.impls_in_module(loc.source_root_id, loc.module_id);
223 Ok(ImplBlock::containing(module_impls, self)) 222 ImplBlock::containing(module_impls, self)
224 } 223 }
225} 224}
226 225
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index d0b086308..ab996a12c 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -3,7 +3,7 @@ use rustc_hash::FxHashMap;
3 3
4use ra_arena::{Arena, RawId, impl_arena_id}; 4use ra_arena::{Arena, RawId, impl_arena_id};
5use ra_syntax::ast::{self, AstNode}; 5use ra_syntax::ast::{self, AstNode};
6use ra_db::{LocationIntener, Cancelable, SourceRootId}; 6use ra_db::{LocationIntener, SourceRootId};
7 7
8use crate::{ 8use crate::{
9 DefId, DefLoc, DefKind, SourceItemId, SourceFileItems, 9 DefId, DefLoc, DefKind, SourceItemId, SourceFileItems,
@@ -166,8 +166,8 @@ impl ModuleImplBlocks {
166 } 166 }
167 } 167 }
168 168
169 fn collect(&mut self, db: &impl HirDatabase, module: Module) -> Cancelable<()> { 169 fn collect(&mut self, db: &impl HirDatabase, module: Module) {
170 let (file_id, module_source) = module.definition_source(db)?; 170 let (file_id, module_source) = module.definition_source(db);
171 let node = match &module_source { 171 let node = match &module_source {
172 ModuleSource::SourceFile(node) => node.syntax(), 172 ModuleSource::SourceFile(node) => node.syntax(),
173 ModuleSource::Module(node) => node 173 ModuleSource::Module(node) => node
@@ -185,8 +185,6 @@ impl ModuleImplBlocks {
185 self.impls_by_def.insert(impl_item.def_id(), id); 185 self.impls_by_def.insert(impl_item.def_id(), id);
186 } 186 }
187 } 187 }
188
189 Ok(())
190 } 188 }
191} 189}
192 190
@@ -194,9 +192,9 @@ pub(crate) fn impls_in_module(
194 db: &impl HirDatabase, 192 db: &impl HirDatabase,
195 source_root_id: SourceRootId, 193 source_root_id: SourceRootId,
196 module_id: ModuleId, 194 module_id: ModuleId,
197) -> Cancelable<Arc<ModuleImplBlocks>> { 195) -> Arc<ModuleImplBlocks> {
198 let mut result = ModuleImplBlocks::new(); 196 let mut result = ModuleImplBlocks::new();
199 let module = Module::from_module_id(db, source_root_id, module_id)?; 197 let module = Module::from_module_id(db, source_root_id, module_id);
200 result.collect(db, module)?; 198 result.collect(db, module);
201 Ok(Arc::new(result)) 199 Arc::new(result)
202} 200}
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 45dda4f7f..ef7d049ee 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -5,15 +5,6 @@
5//! to a particular crate instance. That is, it has cfg flags and features 5//! to a particular crate instance. That is, it has cfg flags and features
6//! applied. So, the relation between syntax and HIR is many-to-one. 6//! applied. So, the relation between syntax and HIR is many-to-one.
7 7
8macro_rules! ctry {
9 ($expr:expr) => {
10 match $expr {
11 None => return Ok(None),
12 Some(it) => it,
13 }
14 };
15}
16
17pub mod db; 8pub mod db;
18#[cfg(test)] 9#[cfg(test)]
19mod mock; 10mod mock;
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs
index 67823e970..0256d7996 100644
--- a/crates/ra_hir/src/module_tree.rs
+++ b/crates/ra_hir/src/module_tree.rs
@@ -3,7 +3,7 @@ use std::sync::Arc;
3use rustc_hash::{FxHashMap, FxHashSet}; 3use rustc_hash::{FxHashMap, FxHashSet};
4use arrayvec::ArrayVec; 4use arrayvec::ArrayVec;
5use relative_path::RelativePathBuf; 5use relative_path::RelativePathBuf;
6use ra_db::{FileId, SourceRootId, Cancelable, SourceRoot}; 6use ra_db::{FileId, SourceRootId, SourceRoot};
7use ra_syntax::{ 7use ra_syntax::{
8 SyntaxNode, TreeArc, 8 SyntaxNode, TreeArc,
9 algo::generate, 9 algo::generate,
@@ -41,8 +41,8 @@ impl Submodule {
41 pub(crate) fn submodules_query( 41 pub(crate) fn submodules_query(
42 db: &impl HirDatabase, 42 db: &impl HirDatabase,
43 source: SourceItemId, 43 source: SourceItemId,
44 ) -> Cancelable<Arc<Vec<Submodule>>> { 44 ) -> Arc<Vec<Submodule>> {
45 db.check_canceled()?; 45 db.check_canceled();
46 let file_id = source.file_id; 46 let file_id = source.file_id;
47 let file_items = db.file_items(file_id); 47 let file_items = db.file_items(file_id);
48 let module_source = ModuleSource::from_source_item_id(db, source); 48 let module_source = ModuleSource::from_source_item_id(db, source);
@@ -54,7 +54,7 @@ impl Submodule {
54 collect_submodules(file_id, &file_items, module.item_list().unwrap()) 54 collect_submodules(file_id, &file_items, module.item_list().unwrap())
55 } 55 }
56 }; 56 };
57 return Ok(Arc::new(submodules)); 57 return Arc::new(submodules);
58 58
59 fn collect_submodules( 59 fn collect_submodules(
60 file_id: HirFileId, 60 file_id: HirFileId,
@@ -116,10 +116,10 @@ impl ModuleTree {
116 pub(crate) fn module_tree_query( 116 pub(crate) fn module_tree_query(
117 db: &impl HirDatabase, 117 db: &impl HirDatabase,
118 source_root: SourceRootId, 118 source_root: SourceRootId,
119 ) -> Cancelable<Arc<ModuleTree>> { 119 ) -> Arc<ModuleTree> {
120 db.check_canceled()?; 120 db.check_canceled();
121 let res = create_module_tree(db, source_root); 121 let res = create_module_tree(db, source_root);
122 Ok(Arc::new(res?)) 122 Arc::new(res)
123 } 123 }
124 124
125 pub(crate) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a { 125 pub(crate) fn modules<'a>(&'a self) -> impl Iterator<Item = ModuleId> + 'a {
@@ -225,10 +225,7 @@ fn modules(root: &impl ast::ModuleItemOwner) -> impl Iterator<Item = (Name, &ast
225 }) 225 })
226} 226}
227 227
228fn create_module_tree<'a>( 228fn create_module_tree<'a>(db: &impl HirDatabase, source_root: SourceRootId) -> ModuleTree {
229 db: &impl HirDatabase,
230 source_root: SourceRootId,
231) -> Cancelable<ModuleTree> {
232 let mut tree = ModuleTree::default(); 229 let mut tree = ModuleTree::default();
233 230
234 let mut roots = FxHashMap::default(); 231 let mut roots = FxHashMap::default();
@@ -252,10 +249,10 @@ fn create_module_tree<'a>(
252 &mut roots, 249 &mut roots,
253 None, 250 None,
254 source, 251 source,
255 )?; 252 );
256 roots.insert(file_id, module_id); 253 roots.insert(file_id, module_id);
257 } 254 }
258 Ok(tree) 255 tree
259} 256}
260 257
261fn build_subtree( 258fn build_subtree(
@@ -266,14 +263,14 @@ fn build_subtree(
266 roots: &mut FxHashMap<FileId, ModuleId>, 263 roots: &mut FxHashMap<FileId, ModuleId>,
267 parent: Option<LinkId>, 264 parent: Option<LinkId>,
268 source: SourceItemId, 265 source: SourceItemId,
269) -> Cancelable<ModuleId> { 266) -> ModuleId {
270 visited.insert(source); 267 visited.insert(source);
271 let id = tree.push_mod(ModuleData { 268 let id = tree.push_mod(ModuleData {
272 source, 269 source,
273 parent, 270 parent,
274 children: Vec::new(), 271 children: Vec::new(),
275 }); 272 });
276 for sub in db.submodules(source)?.iter() { 273 for sub in db.submodules(source).iter() {
277 let link = tree.push_link(LinkData { 274 let link = tree.push_link(LinkData {
278 source: sub.source, 275 source: sub.source,
279 name: sub.name.clone(), 276 name: sub.name.clone(),
@@ -289,7 +286,7 @@ fn build_subtree(
289 .map(|file_id| match roots.remove(&file_id) { 286 .map(|file_id| match roots.remove(&file_id) {
290 Some(module_id) => { 287 Some(module_id) => {
291 tree.mods[module_id].parent = Some(link); 288 tree.mods[module_id].parent = Some(link);
292 Ok(module_id) 289 module_id
293 } 290 }
294 None => build_subtree( 291 None => build_subtree(
295 db, 292 db,
@@ -304,7 +301,7 @@ fn build_subtree(
304 }, 301 },
305 ), 302 ),
306 }) 303 })
307 .collect::<Cancelable<Vec<_>>>()?; 304 .collect::<Vec<_>>();
308 (points_to, problem) 305 (points_to, problem)
309 } else { 306 } else {
310 let points_to = build_subtree( 307 let points_to = build_subtree(
@@ -315,14 +312,14 @@ fn build_subtree(
315 roots, 312 roots,
316 Some(link), 313 Some(link),
317 sub.source, 314 sub.source,
318 )?; 315 );
319 (vec![points_to], None) 316 (vec![points_to], None)
320 }; 317 };
321 318
322 tree.links[link].points_to = points_to; 319 tree.links[link].points_to = points_to;
323 tree.links[link].problem = problem; 320 tree.links[link].problem = problem;
324 } 321 }
325 Ok(id) 322 id
326} 323}
327 324
328fn resolve_submodule( 325fn resolve_submodule(
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
index d9683549c..8d786d2ac 100644
--- a/crates/ra_hir/src/name.rs
+++ b/crates/ra_hir/src/name.rs
@@ -23,7 +23,7 @@ impl fmt::Debug for Name {
23} 23}
24 24
25impl Name { 25impl Name {
26 fn new(text: SmolStr) -> Name { 26 pub(crate) fn new(text: SmolStr) -> Name {
27 Name { text } 27 Name { text }
28 } 28 }
29 29
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 6bf949654..484f668d0 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -22,7 +22,7 @@ use ra_syntax::{
22 SyntaxKind::{self, *}, 22 SyntaxKind::{self, *},
23 ast::{self, AstNode} 23 ast::{self, AstNode}
24}; 24};
25use ra_db::{SourceRootId, Cancelable, FileId}; 25use ra_db::{SourceRootId, FileId};
26 26
27use crate::{ 27use crate::{
28 HirFileId, 28 HirFileId,
@@ -319,30 +319,26 @@ where
319 } 319 }
320 } 320 }
321 321
322 pub(crate) fn resolve(mut self) -> Cancelable<ItemMap> { 322 pub(crate) fn resolve(mut self) -> ItemMap {
323 for (&module_id, items) in self.input.iter() { 323 for (&module_id, items) in self.input.iter() {
324 self.populate_module(module_id, Arc::clone(items))?; 324 self.populate_module(module_id, Arc::clone(items));
325 } 325 }
326 326
327 loop { 327 loop {
328 let processed_imports_count = self.processed_imports.len(); 328 let processed_imports_count = self.processed_imports.len();
329 for &module_id in self.input.keys() { 329 for &module_id in self.input.keys() {
330 self.db.check_canceled()?; 330 self.db.check_canceled();
331 self.resolve_imports(module_id)?; 331 self.resolve_imports(module_id);
332 } 332 }
333 if processed_imports_count == self.processed_imports.len() { 333 if processed_imports_count == self.processed_imports.len() {
334 // no new imports resolved 334 // no new imports resolved
335 break; 335 break;
336 } 336 }
337 } 337 }
338 Ok(self.result) 338 self.result
339 } 339 }
340 340
341 fn populate_module( 341 fn populate_module(&mut self, module_id: ModuleId, input: Arc<InputModuleItems>) {
342 &mut self,
343 module_id: ModuleId,
344 input: Arc<InputModuleItems>,
345 ) -> Cancelable<()> {
346 let mut module_items = ModuleScope::default(); 342 let mut module_items = ModuleScope::default();
347 343
348 // Populate extern crates prelude 344 // Populate extern crates prelude
@@ -353,8 +349,8 @@ where
353 if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file()) 349 if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file())
354 { 350 {
355 let krate = Crate::new(crate_id); 351 let krate = Crate::new(crate_id);
356 for dep in krate.dependencies(self.db)? { 352 for dep in krate.dependencies(self.db) {
357 if let Some(module) = dep.krate.root_module(self.db)? { 353 if let Some(module) = dep.krate.root_module(self.db) {
358 let def_id = module.def_id; 354 let def_id = module.def_id;
359 self.add_module_item( 355 self.add_module_item(
360 &mut module_items, 356 &mut module_items,
@@ -415,7 +411,6 @@ where
415 } 411 }
416 412
417 self.result.per_module.insert(module_id, module_items); 413 self.result.per_module.insert(module_id, module_items);
418 Ok(())
419 } 414 }
420 415
421 fn add_module_item(&self, module_items: &mut ModuleScope, name: Name, def_id: PerNs<DefId>) { 416 fn add_module_item(&self, module_items: &mut ModuleScope, name: Name, def_id: PerNs<DefId>) {
@@ -426,24 +421,23 @@ where
426 module_items.items.insert(name, resolution); 421 module_items.items.insert(name, resolution);
427 } 422 }
428 423
429 fn resolve_imports(&mut self, module_id: ModuleId) -> Cancelable<()> { 424 fn resolve_imports(&mut self, module_id: ModuleId) {
430 for (i, import) in self.input[&module_id].imports.iter().enumerate() { 425 for (i, import) in self.input[&module_id].imports.iter().enumerate() {
431 if self.processed_imports.contains(&(module_id, i)) { 426 if self.processed_imports.contains(&(module_id, i)) {
432 // already done 427 // already done
433 continue; 428 continue;
434 } 429 }
435 if self.resolve_import(module_id, import)? { 430 if self.resolve_import(module_id, import) {
436 log::debug!("import {:?} resolved (or definite error)", import); 431 log::debug!("import {:?} resolved (or definite error)", import);
437 self.processed_imports.insert((module_id, i)); 432 self.processed_imports.insert((module_id, i));
438 } 433 }
439 } 434 }
440 Ok(())
441 } 435 }
442 436
443 fn resolve_import(&mut self, module_id: ModuleId, import: &Import) -> Cancelable<bool> { 437 fn resolve_import(&mut self, module_id: ModuleId, import: &Import) -> bool {
444 log::debug!("resolving import: {:?}", import); 438 log::debug!("resolving import: {:?}", import);
445 let ptr = match import.kind { 439 let ptr = match import.kind {
446 ImportKind::Glob => return Ok(false), 440 ImportKind::Glob => return false,
447 ImportKind::Named(ptr) => ptr, 441 ImportKind::Named(ptr) => ptr,
448 }; 442 };
449 443
@@ -455,7 +449,7 @@ where
455 None => { 449 None => {
456 // TODO: error 450 // TODO: error
457 log::debug!("super path in root module"); 451 log::debug!("super path in root module");
458 return Ok(true); // this can't suddenly resolve if we just resolve some other imports 452 return true; // this can't suddenly resolve if we just resolve some other imports
459 } 453 }
460 } 454 }
461 } 455 }
@@ -469,7 +463,7 @@ where
469 Some(res) if !res.def_id.is_none() => res.def_id, 463 Some(res) if !res.def_id.is_none() => res.def_id,
470 _ => { 464 _ => {
471 log::debug!("path segment {:?} not found", name); 465 log::debug!("path segment {:?} not found", name);
472 return Ok(false); 466 return false;
473 } 467 }
474 }; 468 };
475 469
@@ -481,7 +475,7 @@ where
481 "path segment {:?} resolved to value only, but is not last", 475 "path segment {:?} resolved to value only, but is not last",
482 name 476 name
483 ); 477 );
484 return Ok(false); 478 return false;
485 }; 479 };
486 curr = match type_def_id.loc(self.db) { 480 curr = match type_def_id.loc(self.db) {
487 DefLoc { 481 DefLoc {
@@ -499,7 +493,7 @@ where
499 kind: PathKind::Crate, 493 kind: PathKind::Crate,
500 }; 494 };
501 log::debug!("resolving {:?} in other source root", path); 495 log::debug!("resolving {:?} in other source root", path);
502 let def_id = module.resolve_path(self.db, &path)?; 496 let def_id = module.resolve_path(self.db, &path);
503 if !def_id.is_none() { 497 if !def_id.is_none() {
504 let name = path.segments.last().unwrap(); 498 let name = path.segments.last().unwrap();
505 self.update(module_id, |items| { 499 self.update(module_id, |items| {
@@ -515,10 +509,10 @@ where
515 import, 509 import,
516 def_id.map(|did| did.loc(self.db)) 510 def_id.map(|did| did.loc(self.db))
517 ); 511 );
518 return Ok(true); 512 return true;
519 } else { 513 } else {
520 log::debug!("rest of path did not resolve in other source root"); 514 log::debug!("rest of path did not resolve in other source root");
521 return Ok(true); 515 return true;
522 } 516 }
523 } 517 }
524 } 518 }
@@ -528,7 +522,7 @@ where
528 name, 522 name,
529 type_def_id.loc(self.db) 523 type_def_id.loc(self.db)
530 ); 524 );
531 return Ok(true); // this resolved to a non-module, so the path won't ever resolve 525 return true; // this resolved to a non-module, so the path won't ever resolve
532 } 526 }
533 } 527 }
534 } else { 528 } else {
@@ -547,7 +541,7 @@ where
547 }) 541 })
548 } 542 }
549 } 543 }
550 Ok(true) 544 true
551 } 545 }
552 546
553 fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleScope)) { 547 fn update(&mut self, module_id: ModuleId, f: impl FnOnce(&mut ModuleScope)) {
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index 647fd92aa..9a0474045 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -15,11 +15,9 @@ use crate::{
15fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { 15fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) {
16 let (db, pos) = MockDatabase::with_position(fixture); 16 let (db, pos) = MockDatabase::with_position(fixture);
17 let source_root = db.file_source_root(pos.file_id); 17 let source_root = db.file_source_root(pos.file_id);
18 let module = crate::source_binder::module_from_position(&db, pos) 18 let module = crate::source_binder::module_from_position(&db, pos).unwrap();
19 .unwrap()
20 .unwrap();
21 let module_id = module.def_id.loc(&db).module_id; 19 let module_id = module.def_id.loc(&db).module_id;
22 (db.item_map(source_root).unwrap(), module_id) 20 (db.item_map(source_root), module_id)
23} 21}
24 22
25fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { 23fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) {
@@ -242,11 +240,9 @@ fn item_map_across_crates() {
242 db.set_crate_graph(crate_graph); 240 db.set_crate_graph(crate_graph);
243 241
244 let source_root = db.file_source_root(main_id); 242 let source_root = db.file_source_root(main_id);
245 let module = crate::source_binder::module_from_file_id(&db, main_id) 243 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
246 .unwrap()
247 .unwrap();
248 let module_id = module.def_id.loc(&db).module_id; 244 let module_id = module.def_id.loc(&db).module_id;
249 let item_map = db.item_map(source_root).unwrap(); 245 let item_map = db.item_map(source_root);
250 246
251 check_module_item_map( 247 check_module_item_map(
252 &item_map, 248 &item_map,
@@ -296,11 +292,9 @@ fn import_across_source_roots() {
296 292
297 db.set_crate_graph(crate_graph); 293 db.set_crate_graph(crate_graph);
298 294
299 let module = crate::source_binder::module_from_file_id(&db, main_id) 295 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
300 .unwrap()
301 .unwrap();
302 let module_id = module.def_id.loc(&db).module_id; 296 let module_id = module.def_id.loc(&db).module_id;
303 let item_map = db.item_map(source_root).unwrap(); 297 let item_map = db.item_map(source_root);
304 298
305 check_module_item_map( 299 check_module_item_map(
306 &item_map, 300 &item_map,
@@ -341,11 +335,9 @@ fn reexport_across_crates() {
341 db.set_crate_graph(crate_graph); 335 db.set_crate_graph(crate_graph);
342 336
343 let source_root = db.file_source_root(main_id); 337 let source_root = db.file_source_root(main_id);
344 let module = crate::source_binder::module_from_file_id(&db, main_id) 338 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
345 .unwrap()
346 .unwrap();
347 let module_id = module.def_id.loc(&db).module_id; 339 let module_id = module.def_id.loc(&db).module_id;
348 let item_map = db.item_map(source_root).unwrap(); 340 let item_map = db.item_map(source_root);
349 341
350 check_module_item_map( 342 check_module_item_map(
351 &item_map, 343 &item_map,
@@ -362,7 +354,7 @@ fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) {
362 let source_root = db.file_source_root(pos.file_id); 354 let source_root = db.file_source_root(pos.file_id);
363 { 355 {
364 let events = db.log_executed(|| { 356 let events = db.log_executed(|| {
365 db.item_map(source_root).unwrap(); 357 db.item_map(source_root);
366 }); 358 });
367 assert!(format!("{:?}", events).contains("item_map")) 359 assert!(format!("{:?}", events).contains("item_map"))
368 } 360 }
@@ -371,7 +363,7 @@ fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) {
371 363
372 { 364 {
373 let events = db.log_executed(|| { 365 let events = db.log_executed(|| {
374 db.item_map(source_root).unwrap(); 366 db.item_map(source_root);
375 }); 367 });
376 assert!( 368 assert!(
377 !format!("{:?}", events).contains("item_map"), 369 !format!("{:?}", events).contains("item_map"),
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs
index 214a9d68b..24cb5c752 100644
--- a/crates/ra_hir/src/query_definitions.rs
+++ b/crates/ra_hir/src/query_definitions.rs
@@ -8,7 +8,7 @@ use ra_syntax::{
8 AstNode, SyntaxNode, TreeArc, 8 AstNode, SyntaxNode, TreeArc,
9 ast::{self, ModuleItemOwner} 9 ast::{self, ModuleItemOwner}
10}; 10};
11use ra_db::{SourceRootId, Cancelable,}; 11use ra_db::SourceRootId;
12 12
13use crate::{ 13use crate::{
14 SourceFileItems, SourceItemId, DefId, HirFileId, ModuleSource, 14 SourceFileItems, SourceItemId, DefId, HirFileId, ModuleSource,
@@ -18,10 +18,10 @@ use crate::{
18 nameres::{InputModuleItems, ItemMap, Resolver}, 18 nameres::{InputModuleItems, ItemMap, Resolver},
19}; 19};
20 20
21pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<FnScopes>> { 21pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Arc<FnScopes> {
22 let body = db.body_hir(def_id)?; 22 let body = db.body_hir(def_id);
23 let res = FnScopes::new(body); 23 let res = FnScopes::new(body);
24 Ok(Arc::new(res)) 24 Arc::new(res)
25} 25}
26 26
27pub(super) fn file_items(db: &impl HirDatabase, file_id: HirFileId) -> Arc<SourceFileItems> { 27pub(super) fn file_items(db: &impl HirDatabase, file_id: HirFileId) -> Arc<SourceFileItems> {
@@ -47,8 +47,8 @@ pub(super) fn input_module_items(
47 db: &impl HirDatabase, 47 db: &impl HirDatabase,
48 source_root_id: SourceRootId, 48 source_root_id: SourceRootId,
49 module_id: ModuleId, 49 module_id: ModuleId,
50) -> Cancelable<Arc<InputModuleItems>> { 50) -> Arc<InputModuleItems> {
51 let module_tree = db.module_tree(source_root_id)?; 51 let module_tree = db.module_tree(source_root_id);
52 let source = module_id.source(&module_tree); 52 let source = module_id.source(&module_tree);
53 let file_id = source.file_id; 53 let file_id = source.file_id;
54 let source = ModuleSource::from_source_item_id(db, source); 54 let source = ModuleSource::from_source_item_id(db, source);
@@ -90,26 +90,20 @@ pub(super) fn input_module_items(
90 } 90 }
91 } 91 }
92 }; 92 };
93 Ok(Arc::new(res)) 93 Arc::new(res)
94} 94}
95 95
96pub(super) fn item_map( 96pub(super) fn item_map(db: &impl HirDatabase, source_root: SourceRootId) -> Arc<ItemMap> {
97 db: &impl HirDatabase,
98 source_root: SourceRootId,
99) -> Cancelable<Arc<ItemMap>> {
100 let start = Instant::now(); 97 let start = Instant::now();
101 let module_tree = db.module_tree(source_root)?; 98 let module_tree = db.module_tree(source_root);
102 let input = module_tree 99 let input = module_tree
103 .modules() 100 .modules()
104 .map(|id| { 101 .map(|id| (id, db.input_module_items(source_root, id)))
105 let items = db.input_module_items(source_root, id)?; 102 .collect::<FxHashMap<_, _>>();
106 Ok((id, items))
107 })
108 .collect::<Cancelable<FxHashMap<_, _>>>()?;
109 103
110 let resolver = Resolver::new(db, &input, source_root, module_tree); 104 let resolver = Resolver::new(db, &input, source_root, module_tree);
111 let res = resolver.resolve()?; 105 let res = resolver.resolve();
112 let elapsed = start.elapsed(); 106 let elapsed = start.elapsed();
113 log::info!("item_map: {:?}", elapsed); 107 log::info!("item_map: {:?}", elapsed);
114 Ok(Arc::new(res)) 108 Arc::new(res)
115} 109}
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 1f149a366..7ab8eeae2 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -5,7 +5,7 @@
5/// 5///
6/// So, this modules should not be used during hir construction, it exists 6/// So, this modules should not be used during hir construction, it exists
7/// purely for "IDE needs". 7/// purely for "IDE needs".
8use ra_db::{FileId, FilePosition, Cancelable}; 8use ra_db::{FileId, FilePosition};
9use ra_syntax::{ 9use ra_syntax::{
10 SmolStr, TextRange, SyntaxNode, 10 SmolStr, TextRange, SyntaxNode,
11 ast::{self, AstNode, NameOwner}, 11 ast::{self, AstNode, NameOwner},
@@ -18,7 +18,7 @@ use crate::{
18}; 18};
19 19
20/// Locates the module by `FileId`. Picks topmost module in the file. 20/// Locates the module by `FileId`. Picks topmost module in the file.
21pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Cancelable<Option<Module>> { 21pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Option<Module> {
22 let module_source = SourceItemId { 22 let module_source = SourceItemId {
23 file_id: file_id.into(), 23 file_id: file_id.into(),
24 item_id: None, 24 item_id: None,
@@ -31,25 +31,22 @@ pub fn module_from_declaration(
31 db: &impl HirDatabase, 31 db: &impl HirDatabase,
32 file_id: FileId, 32 file_id: FileId,
33 decl: &ast::Module, 33 decl: &ast::Module,
34) -> Cancelable<Option<Module>> { 34) -> Option<Module> {
35 let parent_module = module_from_file_id(db, file_id)?; 35 let parent_module = module_from_file_id(db, file_id);
36 let child_name = decl.name(); 36 let child_name = decl.name();
37 match (parent_module, child_name) { 37 match (parent_module, child_name) {
38 (Some(parent_module), Some(child_name)) => { 38 (Some(parent_module), Some(child_name)) => {
39 if let Some(child) = parent_module.child(db, &child_name.as_name())? { 39 if let Some(child) = parent_module.child(db, &child_name.as_name()) {
40 return Ok(Some(child)); 40 return Some(child);
41 } 41 }
42 } 42 }
43 _ => (), 43 _ => (),
44 } 44 }
45 Ok(None) 45 None
46} 46}
47 47
48/// Locates the module by position in the source code. 48/// Locates the module by position in the source code.
49pub fn module_from_position( 49pub fn module_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Module> {
50 db: &impl HirDatabase,
51 position: FilePosition,
52) -> Cancelable<Option<Module>> {
53 let file = db.source_file(position.file_id); 50 let file = db.source_file(position.file_id);
54 match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) { 51 match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) {
55 Some(m) if !m.has_semi() => module_from_inline(db, position.file_id.into(), m), 52 Some(m) if !m.has_semi() => module_from_inline(db, position.file_id.into(), m),
@@ -61,7 +58,7 @@ fn module_from_inline(
61 db: &impl HirDatabase, 58 db: &impl HirDatabase,
62 file_id: FileId, 59 file_id: FileId,
63 module: &ast::Module, 60 module: &ast::Module,
64) -> Cancelable<Option<Module>> { 61) -> Option<Module> {
65 assert!(!module.has_semi()); 62 assert!(!module.has_semi());
66 let file_id = file_id.into(); 63 let file_id = file_id.into();
67 let file_items = db.file_items(file_id); 64 let file_items = db.file_items(file_id);
@@ -78,7 +75,7 @@ pub fn module_from_child_node(
78 db: &impl HirDatabase, 75 db: &impl HirDatabase,
79 file_id: FileId, 76 file_id: FileId,
80 child: &SyntaxNode, 77 child: &SyntaxNode,
81) -> Cancelable<Option<Module>> { 78) -> Option<Module> {
82 if let Some(m) = child 79 if let Some(m) = child
83 .ancestors() 80 .ancestors()
84 .filter_map(ast::Module::cast) 81 .filter_map(ast::Module::cast)
@@ -90,22 +87,16 @@ pub fn module_from_child_node(
90 } 87 }
91} 88}
92 89
93fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Cancelable<Option<Module>> { 90fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Option<Module> {
94 let source_root_id = db.file_source_root(source.file_id.as_original_file()); 91 let source_root_id = db.file_source_root(source.file_id.as_original_file());
95 let module_tree = db.module_tree(source_root_id)?; 92 let module_tree = db.module_tree(source_root_id);
96 let module_id = ctry!(module_tree.find_module_by_source(source)); 93 let module_id = module_tree.find_module_by_source(source)?;
97 Ok(Some(Module::from_module_id(db, source_root_id, module_id)?)) 94 Some(Module::from_module_id(db, source_root_id, module_id))
98} 95}
99 96
100pub fn function_from_position( 97pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> {
101 db: &impl HirDatabase,
102 position: FilePosition,
103) -> Cancelable<Option<Function>> {
104 let file = db.source_file(position.file_id); 98 let file = db.source_file(position.file_id);
105 let fn_def = ctry!(find_node_at_offset::<ast::FnDef>( 99 let fn_def = find_node_at_offset::<ast::FnDef>(file.syntax(), position.offset)?;
106 file.syntax(),
107 position.offset
108 ));
109 function_from_source(db, position.file_id, fn_def) 100 function_from_source(db, position.file_id, fn_def)
110} 101}
111 102
@@ -113,10 +104,10 @@ pub fn function_from_source(
113 db: &impl HirDatabase, 104 db: &impl HirDatabase,
114 file_id: FileId, 105 file_id: FileId,
115 fn_def: &ast::FnDef, 106 fn_def: &ast::FnDef,
116) -> Cancelable<Option<Function>> { 107) -> Option<Function> {
117 let module = ctry!(module_from_child_node(db, file_id, fn_def.syntax())?); 108 let module = module_from_child_node(db, file_id, fn_def.syntax())?;
118 let res = function_from_module(db, &module, fn_def); 109 let res = function_from_module(db, &module, fn_def);
119 Ok(Some(res)) 110 Some(res)
120} 111}
121 112
122pub fn function_from_module( 113pub fn function_from_module(
@@ -145,21 +136,18 @@ pub fn function_from_child_node(
145 db: &impl HirDatabase, 136 db: &impl HirDatabase,
146 file_id: FileId, 137 file_id: FileId,
147 node: &SyntaxNode, 138 node: &SyntaxNode,
148) -> Cancelable<Option<Function>> { 139) -> Option<Function> {
149 let fn_def = ctry!(node.ancestors().find_map(ast::FnDef::cast)); 140 let fn_def = node.ancestors().find_map(ast::FnDef::cast)?;
150 function_from_source(db, file_id, fn_def) 141 function_from_source(db, file_id, fn_def)
151} 142}
152 143
153pub fn macro_symbols( 144pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> {
154 db: &impl HirDatabase, 145 let module = match module_from_file_id(db, file_id) {
155 file_id: FileId,
156) -> Cancelable<Vec<(SmolStr, TextRange)>> {
157 let module = match module_from_file_id(db, file_id)? {
158 Some(it) => it, 146 Some(it) => it,
159 None => return Ok(Vec::new()), 147 None => return Vec::new(),
160 }; 148 };
161 let loc = module.def_id.loc(db); 149 let loc = module.def_id.loc(db);
162 let items = db.input_module_items(loc.source_root_id, loc.module_id)?; 150 let items = db.input_module_items(loc.source_root_id, loc.module_id);
163 let mut res = Vec::new(); 151 let mut res = Vec::new();
164 152
165 for macro_call_id in items 153 for macro_call_id in items
@@ -184,5 +172,5 @@ pub fn macro_symbols(
184 } 172 }
185 } 173 }
186 174
187 Ok(res) 175 res
188} 176}
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index fa46ddfe9..85d4dc05c 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -14,7 +14,7 @@
14//! rustc. 14//! rustc.
15 15
16mod autoderef; 16mod autoderef;
17mod primitive; 17pub(crate) mod primitive;
18#[cfg(test)] 18#[cfg(test)]
19mod tests; 19mod tests;
20pub(crate) mod method_resolution; 20pub(crate) mod method_resolution;
@@ -30,25 +30,15 @@ use ra_arena::map::ArenaMap;
30use join_to_string::join; 30use join_to_string::join;
31use rustc_hash::FxHashMap; 31use rustc_hash::FxHashMap;
32 32
33use ra_db::Cancelable;
34
35use crate::{ 33use crate::{
36 Def, DefId, Module, Function, Struct, Enum, EnumVariant, Path, Name, ImplBlock, 34 Def, DefId, Module, Function, Struct, Enum, EnumVariant, Path, Name, ImplBlock,
37 FnSignature, FnScopes, 35 FnSignature, FnScopes,
38 db::HirDatabase, 36 db::HirDatabase,
39 type_ref::{TypeRef, Mutability}, 37 type_ref::{TypeRef, Mutability},
40 name::KnownName, 38 name::KnownName,
41 expr::{Body, Expr, ExprId, PatId, UnaryOp, BinaryOp, Statement}, 39 expr::{Body, Expr, Literal, ExprId, PatId, UnaryOp, BinaryOp, Statement},
42}; 40};
43 41
44fn transpose<T>(x: Cancelable<Option<T>>) -> Option<Cancelable<T>> {
45 match x {
46 Ok(Some(t)) => Some(Ok(t)),
47 Ok(None) => None,
48 Err(e) => Some(Err(e)),
49 }
50}
51
52/// The ID of a type variable. 42/// The ID of a type variable.
53#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] 43#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
54pub struct TypeVarId(u32); 44pub struct TypeVarId(u32);
@@ -107,13 +97,35 @@ impl UnifyValue for TypeVarValue {
107 } 97 }
108} 98}
109 99
110/// The kinds of placeholders we need during type inference. Currently, we only 100/// The kinds of placeholders we need during type inference. There's separate
111/// have type variables; in the future, we will probably also need int and float 101/// values for general types, and for integer and float variables. The latter
112/// variables, for inference of literal values (e.g. `100` could be one of 102/// two are used for inference of literal values (e.g. `100` could be one of
113/// several integer types). 103/// several integer types).
114#[derive(Clone, PartialEq, Eq, Hash, Debug)] 104#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
115pub enum InferTy { 105pub enum InferTy {
116 TypeVar(TypeVarId), 106 TypeVar(TypeVarId),
107 IntVar(TypeVarId),
108 FloatVar(TypeVarId),
109}
110
111impl InferTy {
112 fn to_inner(self) -> TypeVarId {
113 match self {
114 InferTy::TypeVar(ty) | InferTy::IntVar(ty) | InferTy::FloatVar(ty) => ty,
115 }
116 }
117
118 fn fallback_value(self) -> Ty {
119 match self {
120 InferTy::TypeVar(..) => Ty::Unknown,
121 InferTy::IntVar(..) => {
122 Ty::Int(primitive::UncertainIntTy::Signed(primitive::IntTy::I32))
123 }
124 InferTy::FloatVar(..) => {
125 Ty::Float(primitive::UncertainFloatTy::Known(primitive::FloatTy::F64))
126 }
127 }
128 }
117} 129}
118 130
119/// When inferring an expression, we propagate downward whatever type hint we 131/// When inferring an expression, we propagate downward whatever type hint we
@@ -151,14 +163,11 @@ pub enum Ty {
151 /// (a non-surrogate code point). Written as `char`. 163 /// (a non-surrogate code point). Written as `char`.
152 Char, 164 Char,
153 165
154 /// A primitive signed integer type. For example, `i32`. 166 /// A primitive integer type. For example, `i32`.
155 Int(primitive::IntTy), 167 Int(primitive::UncertainIntTy),
156
157 /// A primitive unsigned integer type. For example, `u32`.
158 Uint(primitive::UintTy),
159 168
160 /// A primitive floating-point type. For example, `f64`. 169 /// A primitive floating-point type. For example, `f64`.
161 Float(primitive::FloatTy), 170 Float(primitive::UncertainFloatTy),
162 171
163 /// Structures, enumerations and unions. 172 /// Structures, enumerations and unions.
164 Adt { 173 Adt {
@@ -198,8 +207,9 @@ pub enum Ty {
198 // above function pointer type. Once we implement generics, we will probably 207 // above function pointer type. Once we implement generics, we will probably
199 // need this as well. 208 // need this as well.
200 209
201 // A trait, defined with `dyn trait`. 210 // A trait, defined with `dyn Trait`.
202 // Dynamic(), 211 // Dynamic(),
212
203 // The anonymous type of a closure. Used to represent the type of 213 // The anonymous type of a closure. Used to represent the type of
204 // `|a| a`. 214 // `|a| a`.
205 // Closure(DefId, ClosureSubsts<'tcx>), 215 // Closure(DefId, ClosureSubsts<'tcx>),
@@ -251,28 +261,28 @@ impl Ty {
251 module: &Module, 261 module: &Module,
252 impl_block: Option<&ImplBlock>, 262 impl_block: Option<&ImplBlock>,
253 type_ref: &TypeRef, 263 type_ref: &TypeRef,
254 ) -> Cancelable<Self> { 264 ) -> Self {
255 Ok(match type_ref { 265 match type_ref {
256 TypeRef::Never => Ty::Never, 266 TypeRef::Never => Ty::Never,
257 TypeRef::Tuple(inner) => { 267 TypeRef::Tuple(inner) => {
258 let inner_tys = inner 268 let inner_tys = inner
259 .iter() 269 .iter()
260 .map(|tr| Ty::from_hir(db, module, impl_block, tr)) 270 .map(|tr| Ty::from_hir(db, module, impl_block, tr))
261 .collect::<Cancelable<Vec<_>>>()?; 271 .collect::<Vec<_>>();
262 Ty::Tuple(inner_tys.into()) 272 Ty::Tuple(inner_tys.into())
263 } 273 }
264 TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, path)?, 274 TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, path),
265 TypeRef::RawPtr(inner, mutability) => { 275 TypeRef::RawPtr(inner, mutability) => {
266 let inner_ty = Ty::from_hir(db, module, impl_block, inner)?; 276 let inner_ty = Ty::from_hir(db, module, impl_block, inner);
267 Ty::RawPtr(Arc::new(inner_ty), *mutability) 277 Ty::RawPtr(Arc::new(inner_ty), *mutability)
268 } 278 }
269 TypeRef::Array(_inner) => Ty::Unknown, // TODO 279 TypeRef::Array(_inner) => Ty::Unknown, // TODO
270 TypeRef::Slice(inner) => { 280 TypeRef::Slice(inner) => {
271 let inner_ty = Ty::from_hir(db, module, impl_block, inner)?; 281 let inner_ty = Ty::from_hir(db, module, impl_block, inner);
272 Ty::Slice(Arc::new(inner_ty)) 282 Ty::Slice(Arc::new(inner_ty))
273 } 283 }
274 TypeRef::Reference(inner, mutability) => { 284 TypeRef::Reference(inner, mutability) => {
275 let inner_ty = Ty::from_hir(db, module, impl_block, inner)?; 285 let inner_ty = Ty::from_hir(db, module, impl_block, inner);
276 Ty::Ref(Arc::new(inner_ty), *mutability) 286 Ty::Ref(Arc::new(inner_ty), *mutability)
277 } 287 }
278 TypeRef::Placeholder => Ty::Unknown, 288 TypeRef::Placeholder => Ty::Unknown,
@@ -280,7 +290,7 @@ impl Ty {
280 let mut inner_tys = params 290 let mut inner_tys = params
281 .iter() 291 .iter()
282 .map(|tr| Ty::from_hir(db, module, impl_block, tr)) 292 .map(|tr| Ty::from_hir(db, module, impl_block, tr))
283 .collect::<Cancelable<Vec<_>>>()?; 293 .collect::<Vec<_>>();
284 let return_ty = inner_tys 294 let return_ty = inner_tys
285 .pop() 295 .pop()
286 .expect("TypeRef::Fn should always have at least return type"); 296 .expect("TypeRef::Fn should always have at least return type");
@@ -291,7 +301,7 @@ impl Ty {
291 Ty::FnPtr(Arc::new(sig)) 301 Ty::FnPtr(Arc::new(sig))
292 } 302 }
293 TypeRef::Error => Ty::Unknown, 303 TypeRef::Error => Ty::Unknown,
294 }) 304 }
295 } 305 }
296 306
297 pub(crate) fn from_hir_opt( 307 pub(crate) fn from_hir_opt(
@@ -299,10 +309,8 @@ impl Ty {
299 module: &Module, 309 module: &Module,
300 impl_block: Option<&ImplBlock>, 310 impl_block: Option<&ImplBlock>,
301 type_ref: Option<&TypeRef>, 311 type_ref: Option<&TypeRef>,
302 ) -> Cancelable<Self> { 312 ) -> Self {
303 type_ref 313 type_ref.map_or(Ty::Unknown, |t| Ty::from_hir(db, module, impl_block, t))
304 .map(|t| Ty::from_hir(db, module, impl_block, t))
305 .unwrap_or(Ok(Ty::Unknown))
306 } 314 }
307 315
308 pub(crate) fn from_hir_path( 316 pub(crate) fn from_hir_path(
@@ -310,33 +318,31 @@ impl Ty {
310 module: &Module, 318 module: &Module,
311 impl_block: Option<&ImplBlock>, 319 impl_block: Option<&ImplBlock>,
312 path: &Path, 320 path: &Path,
313 ) -> Cancelable<Self> { 321 ) -> Self {
314 if let Some(name) = path.as_ident() { 322 if let Some(name) = path.as_ident() {
315 if let Some(KnownName::Bool) = name.as_known_name() { 323 if let Some(int_ty) = primitive::UncertainIntTy::from_name(name) {
316 return Ok(Ty::Bool); 324 return Ty::Int(int_ty);
317 } else if let Some(KnownName::Char) = name.as_known_name() { 325 } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) {
318 return Ok(Ty::Char); 326 return Ty::Float(float_ty);
319 } else if let Some(KnownName::Str) = name.as_known_name() {
320 return Ok(Ty::Str);
321 } else if let Some(int_ty) = primitive::IntTy::from_name(name) {
322 return Ok(Ty::Int(int_ty));
323 } else if let Some(uint_ty) = primitive::UintTy::from_name(name) {
324 return Ok(Ty::Uint(uint_ty));
325 } else if let Some(float_ty) = primitive::FloatTy::from_name(name) {
326 return Ok(Ty::Float(float_ty));
327 } else if name.as_known_name() == Some(KnownName::SelfType) { 327 } else if name.as_known_name() == Some(KnownName::SelfType) {
328 return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target_type())); 328 return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target_type()));
329 } else if let Some(known) = name.as_known_name() {
330 match known {
331 KnownName::Bool => return Ty::Bool,
332 KnownName::Char => return Ty::Char,
333 KnownName::Str => return Ty::Str,
334 _ => {}
335 }
329 } 336 }
330 } 337 }
331 338
332 // Resolve in module (in type namespace) 339 // Resolve in module (in type namespace)
333 let resolved = if let Some(r) = module.resolve_path(db, path)?.take_types() { 340 let resolved = if let Some(r) = module.resolve_path(db, path).take_types() {
334 r 341 r
335 } else { 342 } else {
336 return Ok(Ty::Unknown); 343 return Ty::Unknown;
337 }; 344 };
338 let ty = db.type_for_def(resolved)?; 345 db.type_for_def(resolved)
339 Ok(ty)
340 } 346 }
341 347
342 pub fn unit() -> Self { 348 pub fn unit() -> Self {
@@ -392,7 +398,6 @@ impl fmt::Display for Ty {
392 Ty::Bool => write!(f, "bool"), 398 Ty::Bool => write!(f, "bool"),
393 Ty::Char => write!(f, "char"), 399 Ty::Char => write!(f, "char"),
394 Ty::Int(t) => write!(f, "{}", t.ty_to_string()), 400 Ty::Int(t) => write!(f, "{}", t.ty_to_string()),
395 Ty::Uint(t) => write!(f, "{}", t.ty_to_string()),
396 Ty::Float(t) => write!(f, "{}", t.ty_to_string()), 401 Ty::Float(t) => write!(f, "{}", t.ty_to_string()),
397 Ty::Str => write!(f, "str"), 402 Ty::Str => write!(f, "str"),
398 Ty::Slice(t) => write!(f, "[{}]", t), 403 Ty::Slice(t) => write!(f, "[{}]", t),
@@ -427,47 +432,47 @@ impl fmt::Display for Ty {
427 432
428/// Compute the declared type of a function. This should not need to look at the 433/// Compute the declared type of a function. This should not need to look at the
429/// function body. 434/// function body.
430fn type_for_fn(db: &impl HirDatabase, f: Function) -> Cancelable<Ty> { 435fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty {
431 let signature = f.signature(db); 436 let signature = f.signature(db);
432 let module = f.module(db)?; 437 let module = f.module(db);
433 let impl_block = f.impl_block(db)?; 438 let impl_block = f.impl_block(db);
434 // TODO we ignore type parameters for now 439 // TODO we ignore type parameters for now
435 let input = signature 440 let input = signature
436 .params() 441 .params()
437 .iter() 442 .iter()
438 .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), tr)) 443 .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), tr))
439 .collect::<Cancelable<Vec<_>>>()?; 444 .collect::<Vec<_>>();
440 let output = Ty::from_hir(db, &module, impl_block.as_ref(), signature.ret_type())?; 445 let output = Ty::from_hir(db, &module, impl_block.as_ref(), signature.ret_type());
441 let sig = FnSig { input, output }; 446 let sig = FnSig { input, output };
442 Ok(Ty::FnPtr(Arc::new(sig))) 447 Ty::FnPtr(Arc::new(sig))
443} 448}
444 449
445fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Cancelable<Ty> { 450fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
446 Ok(Ty::Adt { 451 Ty::Adt {
447 def_id: s.def_id(), 452 def_id: s.def_id(),
448 name: s.name(db)?.unwrap_or_else(Name::missing), 453 name: s.name(db).unwrap_or_else(Name::missing),
449 }) 454 }
450} 455}
451 456
452pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Cancelable<Ty> { 457pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
453 Ok(Ty::Adt { 458 Ty::Adt {
454 def_id: s.def_id(), 459 def_id: s.def_id(),
455 name: s.name(db)?.unwrap_or_else(Name::missing), 460 name: s.name(db).unwrap_or_else(Name::missing),
456 }) 461 }
457} 462}
458 463
459pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> Cancelable<Ty> { 464pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> Ty {
460 let enum_parent = ev.parent_enum(db)?; 465 let enum_parent = ev.parent_enum(db);
461 466
462 type_for_enum(db, enum_parent) 467 type_for_enum(db, enum_parent)
463} 468}
464 469
465pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Ty> { 470pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty {
466 let def = def_id.resolve(db)?; 471 let def = def_id.resolve(db);
467 match def { 472 match def {
468 Def::Module(..) => { 473 Def::Module(..) => {
469 log::debug!("trying to get type for module {:?}", def_id); 474 log::debug!("trying to get type for module {:?}", def_id);
470 Ok(Ty::Unknown) 475 Ty::Unknown
471 } 476 }
472 Def::Function(f) => type_for_fn(db, f), 477 Def::Function(f) => type_for_fn(db, f),
473 Def::Struct(s) => type_for_struct(db, s), 478 Def::Struct(s) => type_for_struct(db, s),
@@ -479,35 +484,26 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Cancelable<T
479 def_id, 484 def_id,
480 def 485 def
481 ); 486 );
482 Ok(Ty::Unknown) 487 Ty::Unknown
483 } 488 }
484 } 489 }
485} 490}
486 491
487pub(super) fn type_for_field( 492pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> {
488 db: &impl HirDatabase, 493 let def = def_id.resolve(db);
489 def_id: DefId,
490 field: Name,
491) -> Cancelable<Option<Ty>> {
492 let def = def_id.resolve(db)?;
493 let variant_data = match def { 494 let variant_data = match def {
494 Def::Struct(s) => s.variant_data(db)?, 495 Def::Struct(s) => s.variant_data(db),
495 Def::EnumVariant(ev) => ev.variant_data(db)?, 496 Def::EnumVariant(ev) => ev.variant_data(db),
496 // TODO: unions 497 // TODO: unions
497 _ => panic!( 498 _ => panic!(
498 "trying to get type for field in non-struct/variant {:?}", 499 "trying to get type for field in non-struct/variant {:?}",
499 def_id 500 def_id
500 ), 501 ),
501 }; 502 };
502 let module = def_id.module(db)?; 503 let module = def_id.module(db);
503 let impl_block = def_id.impl_block(db)?; 504 let impl_block = def_id.impl_block(db);
504 let type_ref = ctry!(variant_data.get_field_type_ref(&field)); 505 let type_ref = variant_data.get_field_type_ref(&field)?;
505 Ok(Some(Ty::from_hir( 506 Some(Ty::from_hir(db, &module, impl_block.as_ref(), &type_ref))
506 db,
507 &module,
508 impl_block.as_ref(),
509 &type_ref,
510 )?))
511} 507}
512 508
513/// The result of type inference: A mapping from expressions and patterns to types. 509/// The result of type inference: A mapping from expressions and patterns to types.
@@ -587,7 +583,7 @@ fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty {
587 | BinaryOp::BitwiseAnd 583 | BinaryOp::BitwiseAnd
588 | BinaryOp::BitwiseOr 584 | BinaryOp::BitwiseOr
589 | BinaryOp::BitwiseXor => match rhs_ty { 585 | BinaryOp::BitwiseXor => match rhs_ty {
590 Ty::Uint(..) | Ty::Int(..) | Ty::Float(..) => rhs_ty, 586 Ty::Int(..) | Ty::Float(..) => rhs_ty,
591 _ => Ty::Unknown, 587 _ => Ty::Unknown,
592 }, 588 },
593 BinaryOp::RangeRightOpen | BinaryOp::RangeRightClosed => Ty::Unknown, 589 BinaryOp::RangeRightOpen | BinaryOp::RangeRightClosed => Ty::Unknown,
@@ -598,7 +594,7 @@ fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty {
598 match op { 594 match op {
599 BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::Bool, 595 BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::Bool,
600 BinaryOp::Assignment | BinaryOp::EqualityTest => match lhs_ty { 596 BinaryOp::Assignment | BinaryOp::EqualityTest => match lhs_ty {
601 Ty::Uint(..) | Ty::Int(..) | Ty::Float(..) | Ty::Str | Ty::Char | Ty::Bool => lhs_ty, 597 Ty::Int(..) | Ty::Float(..) | Ty::Str | Ty::Char | Ty::Bool => lhs_ty,
602 _ => Ty::Unknown, 598 _ => Ty::Unknown,
603 }, 599 },
604 BinaryOp::LesserEqualTest 600 BinaryOp::LesserEqualTest
@@ -625,7 +621,7 @@ fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty {
625 | BinaryOp::BitwiseAnd 621 | BinaryOp::BitwiseAnd
626 | BinaryOp::BitwiseOr 622 | BinaryOp::BitwiseOr
627 | BinaryOp::BitwiseXor => match lhs_ty { 623 | BinaryOp::BitwiseXor => match lhs_ty {
628 Ty::Uint(..) | Ty::Int(..) | Ty::Float(..) => lhs_ty, 624 Ty::Int(..) | Ty::Float(..) => lhs_ty,
629 _ => Ty::Unknown, 625 _ => Ty::Unknown,
630 }, 626 },
631 _ => Ty::Unknown, 627 _ => Ty::Unknown,
@@ -684,7 +680,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
684 self.type_of_pat.insert(pat, ty); 680 self.type_of_pat.insert(pat, ty);
685 } 681 }
686 682
687 fn make_ty(&self, type_ref: &TypeRef) -> Cancelable<Ty> { 683 fn make_ty(&self, type_ref: &TypeRef) -> Ty {
688 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref) 684 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref)
689 } 685 }
690 686
@@ -695,13 +691,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
695 match (&*ty1, &*ty2) { 691 match (&*ty1, &*ty2) {
696 (Ty::Unknown, ..) => true, 692 (Ty::Unknown, ..) => true,
697 (.., Ty::Unknown) => true, 693 (.., Ty::Unknown) => true,
698 (Ty::Bool, _) 694 (Ty::Int(t1), Ty::Int(t2)) => match (t1, t2) {
699 | (Ty::Str, _) 695 (primitive::UncertainIntTy::Unknown, _)
700 | (Ty::Never, _) 696 | (_, primitive::UncertainIntTy::Unknown) => true,
701 | (Ty::Char, _) 697 _ => t1 == t2,
702 | (Ty::Int(..), Ty::Int(..)) 698 },
703 | (Ty::Uint(..), Ty::Uint(..)) 699 (Ty::Float(t1), Ty::Float(t2)) => match (t1, t2) {
704 | (Ty::Float(..), Ty::Float(..)) => ty1 == ty2, 700 (primitive::UncertainFloatTy::Unknown, _)
701 | (_, primitive::UncertainFloatTy::Unknown) => true,
702 _ => t1 == t2,
703 },
704 (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2,
705 ( 705 (
706 Ty::Adt { 706 Ty::Adt {
707 def_id: def_id1, .. 707 def_id: def_id1, ..
@@ -718,12 +718,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
718 .iter() 718 .iter()
719 .zip(ts2.iter()) 719 .zip(ts2.iter())
720 .all(|(t1, t2)| self.unify(t1, t2)), 720 .all(|(t1, t2)| self.unify(t1, t2)),
721 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) => { 721 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2)))
722 | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2)))
723 | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => {
722 // both type vars are unknown since we tried to resolve them 724 // both type vars are unknown since we tried to resolve them
723 self.var_unification_table.union(*tv1, *tv2); 725 self.var_unification_table.union(*tv1, *tv2);
724 true 726 true
725 } 727 }
726 (Ty::Infer(InferTy::TypeVar(tv)), other) | (other, Ty::Infer(InferTy::TypeVar(tv))) => { 728 (Ty::Infer(InferTy::TypeVar(tv)), other)
729 | (other, Ty::Infer(InferTy::TypeVar(tv)))
730 | (Ty::Infer(InferTy::IntVar(tv)), other)
731 | (other, Ty::Infer(InferTy::IntVar(tv)))
732 | (Ty::Infer(InferTy::FloatVar(tv)), other)
733 | (other, Ty::Infer(InferTy::FloatVar(tv))) => {
727 // the type var is unknown since we tried to resolve it 734 // the type var is unknown since we tried to resolve it
728 self.var_unification_table 735 self.var_unification_table
729 .union_value(*tv, TypeVarValue::Known(other.clone())); 736 .union_value(*tv, TypeVarValue::Known(other.clone()));
@@ -739,10 +746,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
739 )) 746 ))
740 } 747 }
741 748
749 fn new_integer_var(&mut self) -> Ty {
750 Ty::Infer(InferTy::IntVar(
751 self.var_unification_table.new_key(TypeVarValue::Unknown),
752 ))
753 }
754
755 fn new_float_var(&mut self) -> Ty {
756 Ty::Infer(InferTy::FloatVar(
757 self.var_unification_table.new_key(TypeVarValue::Unknown),
758 ))
759 }
760
742 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. 761 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
743 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { 762 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
744 match ty { 763 match ty {
745 Ty::Unknown => self.new_type_var(), 764 Ty::Unknown => self.new_type_var(),
765 Ty::Int(primitive::UncertainIntTy::Unknown) => self.new_integer_var(),
766 Ty::Float(primitive::UncertainFloatTy::Unknown) => self.new_float_var(),
746 _ => ty, 767 _ => ty,
747 } 768 }
748 } 769 }
@@ -757,12 +778,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
757 /// known type. 778 /// known type.
758 fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty { 779 fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
759 ty.fold(&mut |ty| match ty { 780 ty.fold(&mut |ty| match ty {
760 Ty::Infer(InferTy::TypeVar(tv)) => { 781 Ty::Infer(tv) => {
761 if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() { 782 let inner = tv.to_inner();
783 if let Some(known_ty) = self.var_unification_table.probe_value(inner).known() {
762 // known_ty may contain other variables that are known by now 784 // known_ty may contain other variables that are known by now
763 self.resolve_ty_as_possible(known_ty.clone()) 785 self.resolve_ty_as_possible(known_ty.clone())
764 } else { 786 } else {
765 Ty::Infer(InferTy::TypeVar(tv)) 787 ty
766 } 788 }
767 } 789 }
768 _ => ty, 790 _ => ty,
@@ -773,8 +795,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
773 /// otherwise, return ty. 795 /// otherwise, return ty.
774 fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { 796 fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
775 match ty { 797 match ty {
776 Ty::Infer(InferTy::TypeVar(tv)) => { 798 Ty::Infer(tv) => {
777 match self.var_unification_table.probe_value(*tv).known() { 799 let inner = tv.to_inner();
800 match self.var_unification_table.probe_value(inner).known() {
778 Some(known_ty) => { 801 Some(known_ty) => {
779 // The known_ty can't be a type var itself 802 // The known_ty can't be a type var itself
780 Cow::Owned(known_ty.clone()) 803 Cow::Owned(known_ty.clone())
@@ -790,61 +813,62 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
790 /// replaced by Ty::Unknown. 813 /// replaced by Ty::Unknown.
791 fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { 814 fn resolve_ty_completely(&mut self, ty: Ty) -> Ty {
792 ty.fold(&mut |ty| match ty { 815 ty.fold(&mut |ty| match ty {
793 Ty::Infer(InferTy::TypeVar(tv)) => { 816 Ty::Infer(tv) => {
794 if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() { 817 let inner = tv.to_inner();
818 if let Some(known_ty) = self.var_unification_table.probe_value(inner).known() {
795 // known_ty may contain other variables that are known by now 819 // known_ty may contain other variables that are known by now
796 self.resolve_ty_completely(known_ty.clone()) 820 self.resolve_ty_completely(known_ty.clone())
797 } else { 821 } else {
798 Ty::Unknown 822 tv.fallback_value()
799 } 823 }
800 } 824 }
801 _ => ty, 825 _ => ty,
802 }) 826 })
803 } 827 }
804 828
805 fn infer_path_expr(&mut self, expr: ExprId, path: &Path) -> Cancelable<Option<Ty>> { 829 fn infer_path_expr(&mut self, expr: ExprId, path: &Path) -> Option<Ty> {
806 if path.is_ident() || path.is_self() { 830 if path.is_ident() || path.is_self() {
807 // resolve locally 831 // resolve locally
808 let name = path.as_ident().cloned().unwrap_or_else(Name::self_param); 832 let name = path.as_ident().cloned().unwrap_or_else(Name::self_param);
809 if let Some(scope_entry) = self.scopes.resolve_local_name(expr, name) { 833 if let Some(scope_entry) = self.scopes.resolve_local_name(expr, name) {
810 let ty = ctry!(self.type_of_pat.get(scope_entry.pat())); 834 let ty = self.type_of_pat.get(scope_entry.pat())?;
811 let ty = self.resolve_ty_as_possible(ty.clone()); 835 let ty = self.resolve_ty_as_possible(ty.clone());
812 return Ok(Some(ty)); 836 return Some(ty);
813 }; 837 };
814 }; 838 };
815 839
816 // resolve in module 840 // resolve in module
817 let resolved = ctry!(self.module.resolve_path(self.db, &path)?.take_values()); 841 let resolved = self.module.resolve_path(self.db, &path).take_values()?;
818 let ty = self.db.type_for_def(resolved)?; 842 let ty = self.db.type_for_def(resolved);
819 let ty = self.insert_type_vars(ty); 843 let ty = self.insert_type_vars(ty);
820 Ok(Some(ty)) 844 Some(ty)
821 } 845 }
822 846
823 fn resolve_variant(&self, path: Option<&Path>) -> Cancelable<(Ty, Option<DefId>)> { 847 fn resolve_variant(&self, path: Option<&Path>) -> (Ty, Option<DefId>) {
824 let path = if let Some(path) = path { 848 let path = if let Some(path) = path {
825 path 849 path
826 } else { 850 } else {
827 return Ok((Ty::Unknown, None)); 851 return (Ty::Unknown, None);
828 }; 852 };
829 let def_id = if let Some(def_id) = self.module.resolve_path(self.db, &path)?.take_types() { 853 let def_id = if let Some(def_id) = self.module.resolve_path(self.db, &path).take_types() {
830 def_id 854 def_id
831 } else { 855 } else {
832 return Ok((Ty::Unknown, None)); 856 return (Ty::Unknown, None);
833 }; 857 };
834 Ok(match def_id.resolve(self.db)? { 858 match def_id.resolve(self.db) {
835 Def::Struct(s) => { 859 Def::Struct(s) => {
836 let ty = type_for_struct(self.db, s)?; 860 let ty = type_for_struct(self.db, s);
837 (ty, Some(def_id)) 861 (ty, Some(def_id))
838 } 862 }
839 Def::EnumVariant(ev) => { 863 Def::EnumVariant(ev) => {
840 let ty = type_for_enum_variant(self.db, ev)?; 864 let ty = type_for_enum_variant(self.db, ev);
841 (ty, Some(def_id)) 865 (ty, Some(def_id))
842 } 866 }
843 _ => (Ty::Unknown, None), 867 _ => (Ty::Unknown, None),
844 }) 868 }
845 } 869 }
846 870
847 fn infer_expr(&mut self, expr: ExprId, expected: &Expectation) -> Cancelable<Ty> { 871 fn infer_expr(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
848 let body = Arc::clone(&self.body); // avoid borrow checker problem 872 let body = Arc::clone(&self.body); // avoid borrow checker problem
849 let ty = match &body[expr] { 873 let ty = match &body[expr] {
850 Expr::Missing => Ty::Unknown, 874 Expr::Missing => Ty::Unknown,
@@ -854,11 +878,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
854 else_branch, 878 else_branch,
855 } => { 879 } => {
856 // if let is desugared to match, so this is always simple if 880 // if let is desugared to match, so this is always simple if
857 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool))?; 881 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool));
858 let then_ty = self.infer_expr(*then_branch, expected)?; 882 let then_ty = self.infer_expr(*then_branch, expected);
859 match else_branch { 883 match else_branch {
860 Some(else_branch) => { 884 Some(else_branch) => {
861 self.infer_expr(*else_branch, expected)?; 885 self.infer_expr(*else_branch, expected);
862 } 886 }
863 None => { 887 None => {
864 // no else branch -> unit 888 // no else branch -> unit
@@ -867,31 +891,31 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
867 }; 891 };
868 then_ty 892 then_ty
869 } 893 }
870 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected)?, 894 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected),
871 Expr::Loop { body } => { 895 Expr::Loop { body } => {
872 self.infer_expr(*body, &Expectation::has_type(Ty::unit()))?; 896 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
873 // TODO handle break with value 897 // TODO handle break with value
874 Ty::Never 898 Ty::Never
875 } 899 }
876 Expr::While { condition, body } => { 900 Expr::While { condition, body } => {
877 // while let is desugared to a match loop, so this is always simple while 901 // while let is desugared to a match loop, so this is always simple while
878 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool))?; 902 self.infer_expr(*condition, &Expectation::has_type(Ty::Bool));
879 self.infer_expr(*body, &Expectation::has_type(Ty::unit()))?; 903 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
880 Ty::unit() 904 Ty::unit()
881 } 905 }
882 Expr::For { iterable, body, .. } => { 906 Expr::For { iterable, body, .. } => {
883 let _iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 907 let _iterable_ty = self.infer_expr(*iterable, &Expectation::none());
884 // TODO write type for pat 908 // TODO write type for pat
885 self.infer_expr(*body, &Expectation::has_type(Ty::unit()))?; 909 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
886 Ty::unit() 910 Ty::unit()
887 } 911 }
888 Expr::Lambda { body, .. } => { 912 Expr::Lambda { body, .. } => {
889 // TODO write types for args, infer lambda type etc. 913 // TODO write types for args, infer lambda type etc.
890 let _body_ty = self.infer_expr(*body, &Expectation::none())?; 914 let _body_ty = self.infer_expr(*body, &Expectation::none());
891 Ty::Unknown 915 Ty::Unknown
892 } 916 }
893 Expr::Call { callee, args } => { 917 Expr::Call { callee, args } => {
894 let callee_ty = self.infer_expr(*callee, &Expectation::none())?; 918 let callee_ty = self.infer_expr(*callee, &Expectation::none());
895 let (param_tys, ret_ty) = match &callee_ty { 919 let (param_tys, ret_ty) = match &callee_ty {
896 Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()), 920 Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()),
897 _ => { 921 _ => {
@@ -904,7 +928,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
904 self.infer_expr( 928 self.infer_expr(
905 *arg, 929 *arg,
906 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)), 930 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
907 )?; 931 );
908 } 932 }
909 ret_ty 933 ret_ty
910 } 934 }
@@ -913,12 +937,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
913 args, 937 args,
914 method_name, 938 method_name,
915 } => { 939 } => {
916 let receiver_ty = self.infer_expr(*receiver, &Expectation::none())?; 940 let receiver_ty = self.infer_expr(*receiver, &Expectation::none());
917 let resolved = receiver_ty.clone().lookup_method(self.db, method_name)?; 941 let resolved = receiver_ty.clone().lookup_method(self.db, method_name);
918 let method_ty = match resolved { 942 let method_ty = match resolved {
919 Some(def_id) => { 943 Some(def_id) => {
920 self.write_method_resolution(expr, def_id); 944 self.write_method_resolution(expr, def_id);
921 self.db.type_for_def(def_id)? 945 self.db.type_for_def(def_id)
922 } 946 }
923 None => Ty::Unknown, 947 None => Ty::Unknown,
924 }; 948 };
@@ -940,32 +964,32 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
940 self.infer_expr( 964 self.infer_expr(
941 *arg, 965 *arg,
942 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)), 966 &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
943 )?; 967 );
944 } 968 }
945 ret_ty 969 ret_ty
946 } 970 }
947 Expr::Match { expr, arms } => { 971 Expr::Match { expr, arms } => {
948 let _ty = self.infer_expr(*expr, &Expectation::none())?; 972 let _ty = self.infer_expr(*expr, &Expectation::none());
949 for arm in arms { 973 for arm in arms {
950 // TODO type the bindings in pats 974 // TODO type the bindings in pats
951 // TODO type the guard 975 // TODO type the guard
952 let _ty = self.infer_expr(arm.expr, &Expectation::none())?; 976 let _ty = self.infer_expr(arm.expr, &Expectation::none());
953 } 977 }
954 // TODO unify all the match arm types 978 // TODO unify all the match arm types
955 Ty::Unknown 979 Ty::Unknown
956 } 980 }
957 Expr::Path(p) => self.infer_path_expr(expr, p)?.unwrap_or(Ty::Unknown), 981 Expr::Path(p) => self.infer_path_expr(expr, p).unwrap_or(Ty::Unknown),
958 Expr::Continue => Ty::Never, 982 Expr::Continue => Ty::Never,
959 Expr::Break { expr } => { 983 Expr::Break { expr } => {
960 if let Some(expr) = expr { 984 if let Some(expr) = expr {
961 // TODO handle break with value 985 // TODO handle break with value
962 self.infer_expr(*expr, &Expectation::none())?; 986 self.infer_expr(*expr, &Expectation::none());
963 } 987 }
964 Ty::Never 988 Ty::Never
965 } 989 }
966 Expr::Return { expr } => { 990 Expr::Return { expr } => {
967 if let Some(expr) = expr { 991 if let Some(expr) = expr {
968 self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone()))?; 992 self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone()));
969 } 993 }
970 Ty::Never 994 Ty::Never
971 } 995 }
@@ -974,62 +998,60 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
974 fields, 998 fields,
975 spread, 999 spread,
976 } => { 1000 } => {
977 let (ty, def_id) = self.resolve_variant(path.as_ref())?; 1001 let (ty, def_id) = self.resolve_variant(path.as_ref());
978 for field in fields { 1002 for field in fields {
979 let field_ty = if let Some(def_id) = def_id { 1003 let field_ty = if let Some(def_id) = def_id {
980 self.db 1004 self.db
981 .type_for_field(def_id, field.name.clone())? 1005 .type_for_field(def_id, field.name.clone())
982 .unwrap_or(Ty::Unknown) 1006 .unwrap_or(Ty::Unknown)
983 } else { 1007 } else {
984 Ty::Unknown 1008 Ty::Unknown
985 }; 1009 };
986 self.infer_expr(field.expr, &Expectation::has_type(field_ty))?; 1010 self.infer_expr(field.expr, &Expectation::has_type(field_ty));
987 } 1011 }
988 if let Some(expr) = spread { 1012 if let Some(expr) = spread {
989 self.infer_expr(*expr, &Expectation::has_type(ty.clone()))?; 1013 self.infer_expr(*expr, &Expectation::has_type(ty.clone()));
990 } 1014 }
991 ty 1015 ty
992 } 1016 }
993 Expr::Field { expr, name } => { 1017 Expr::Field { expr, name } => {
994 let receiver_ty = self.infer_expr(*expr, &Expectation::none())?; 1018 let receiver_ty = self.infer_expr(*expr, &Expectation::none());
995 let ty = receiver_ty 1019 let ty = receiver_ty
996 .autoderef(self.db) 1020 .autoderef(self.db)
997 .find_map(|derefed_ty| match derefed_ty { 1021 .find_map(|derefed_ty| match derefed_ty {
998 // this is more complicated than necessary because type_for_field is cancelable 1022 // this is more complicated than necessary because type_for_field is cancelable
999 Ty::Tuple(fields) => { 1023 Ty::Tuple(fields) => {
1000 let i = name.to_string().parse::<usize>().ok(); 1024 let i = name.to_string().parse::<usize>().ok();
1001 i.and_then(|i| fields.get(i).cloned()).map(Ok) 1025 i.and_then(|i| fields.get(i).cloned())
1002 }
1003 Ty::Adt { def_id, .. } => {
1004 transpose(self.db.type_for_field(def_id, name.clone()))
1005 } 1026 }
1027 Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, name.clone()),
1006 _ => None, 1028 _ => None,
1007 }) 1029 })
1008 .unwrap_or(Ok(Ty::Unknown))?; 1030 .unwrap_or(Ty::Unknown);
1009 self.insert_type_vars(ty) 1031 self.insert_type_vars(ty)
1010 } 1032 }
1011 Expr::Try { expr } => { 1033 Expr::Try { expr } => {
1012 let _inner_ty = self.infer_expr(*expr, &Expectation::none())?; 1034 let _inner_ty = self.infer_expr(*expr, &Expectation::none());
1013 Ty::Unknown 1035 Ty::Unknown
1014 } 1036 }
1015 Expr::Cast { expr, type_ref } => { 1037 Expr::Cast { expr, type_ref } => {
1016 let _inner_ty = self.infer_expr(*expr, &Expectation::none())?; 1038 let _inner_ty = self.infer_expr(*expr, &Expectation::none());
1017 let cast_ty = 1039 let cast_ty =
1018 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref)?; 1040 Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref);
1019 let cast_ty = self.insert_type_vars(cast_ty); 1041 let cast_ty = self.insert_type_vars(cast_ty);
1020 // TODO check the cast... 1042 // TODO check the cast...
1021 cast_ty 1043 cast_ty
1022 } 1044 }
1023 Expr::Ref { expr, mutability } => { 1045 Expr::Ref { expr, mutability } => {
1024 // TODO pass the expectation down 1046 // TODO pass the expectation down
1025 let inner_ty = self.infer_expr(*expr, &Expectation::none())?; 1047 let inner_ty = self.infer_expr(*expr, &Expectation::none());
1026 // TODO reference coercions etc. 1048 // TODO reference coercions etc.
1027 Ty::Ref(Arc::new(inner_ty), *mutability) 1049 Ty::Ref(Arc::new(inner_ty), *mutability)
1028 } 1050 }
1029 Expr::UnaryOp { expr, op } => { 1051 Expr::UnaryOp { expr, op } => {
1030 let inner_ty = self.infer_expr(*expr, &Expectation::none())?; 1052 let inner_ty = self.infer_expr(*expr, &Expectation::none());
1031 match op { 1053 match op {
1032 Some(UnaryOp::Deref) => { 1054 UnaryOp::Deref => {
1033 if let Some(derefed_ty) = inner_ty.builtin_deref() { 1055 if let Some(derefed_ty) = inner_ty.builtin_deref() {
1034 derefed_ty 1056 derefed_ty
1035 } else { 1057 } else {
@@ -1037,7 +1059,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1037 Ty::Unknown 1059 Ty::Unknown
1038 } 1060 }
1039 } 1061 }
1040 _ => Ty::Unknown, 1062 UnaryOp::Neg => {
1063 match inner_ty {
1064 Ty::Int(primitive::UncertainIntTy::Unknown)
1065 | Ty::Int(primitive::UncertainIntTy::Signed(..))
1066 | Ty::Infer(InferTy::IntVar(..))
1067 | Ty::Infer(InferTy::FloatVar(..))
1068 | Ty::Float(..) => inner_ty,
1069 // TODO: resolve ops::Neg trait
1070 _ => Ty::Unknown,
1071 }
1072 }
1073 UnaryOp::Not if inner_ty == Ty::Bool => Ty::Bool,
1074 // TODO: resolve ops::Not trait for inner_ty
1075 UnaryOp::Not => Ty::Unknown,
1041 } 1076 }
1042 } 1077 }
1043 Expr::BinaryOp { lhs, rhs, op } => match op { 1078 Expr::BinaryOp { lhs, rhs, op } => match op {
@@ -1048,11 +1083,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1048 } 1083 }
1049 _ => Expectation::none(), 1084 _ => Expectation::none(),
1050 }; 1085 };
1051 let lhs_ty = self.infer_expr(*lhs, &lhs_expectation)?; 1086 let lhs_ty = self.infer_expr(*lhs, &lhs_expectation);
1052 // TODO: find implementation of trait corresponding to operation 1087 // TODO: find implementation of trait corresponding to operation
1053 // symbol and resolve associated `Output` type 1088 // symbol and resolve associated `Output` type
1054 let rhs_expectation = binary_op_rhs_expectation(*op, lhs_ty); 1089 let rhs_expectation = binary_op_rhs_expectation(*op, lhs_ty);
1055 let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation))?; 1090 let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation));
1056 1091
1057 // TODO: similar as above, return ty is often associated trait type 1092 // TODO: similar as above, return ty is often associated trait type
1058 binary_op_return_ty(*op, rhs_ty) 1093 binary_op_return_ty(*op, rhs_ty)
@@ -1062,18 +1097,32 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1062 Expr::Tuple { exprs } => { 1097 Expr::Tuple { exprs } => {
1063 let mut ty_vec = Vec::with_capacity(exprs.len()); 1098 let mut ty_vec = Vec::with_capacity(exprs.len());
1064 for arg in exprs.iter() { 1099 for arg in exprs.iter() {
1065 ty_vec.push(self.infer_expr(*arg, &Expectation::none())?); 1100 ty_vec.push(self.infer_expr(*arg, &Expectation::none()));
1066 } 1101 }
1067 1102
1068 Ty::Tuple(Arc::from(ty_vec)) 1103 Ty::Tuple(Arc::from(ty_vec))
1069 } 1104 }
1105 Expr::Literal(lit) => match lit {
1106 Literal::Bool(..) => Ty::Bool,
1107 Literal::String(..) => Ty::Ref(Arc::new(Ty::Str), Mutability::Shared),
1108 Literal::ByteString(..) => {
1109 let byte_type = Arc::new(Ty::Int(primitive::UncertainIntTy::Unsigned(
1110 primitive::UintTy::U8,
1111 )));
1112 let slice_type = Arc::new(Ty::Slice(byte_type));
1113 Ty::Ref(slice_type, Mutability::Shared)
1114 }
1115 Literal::Char(..) => Ty::Char,
1116 Literal::Int(_v, ty) => Ty::Int(*ty),
1117 Literal::Float(_v, ty) => Ty::Float(*ty),
1118 },
1070 }; 1119 };
1071 // use a new type variable if we got Ty::Unknown here 1120 // use a new type variable if we got Ty::Unknown here
1072 let ty = self.insert_type_vars_shallow(ty); 1121 let ty = self.insert_type_vars_shallow(ty);
1073 self.unify(&ty, &expected.ty); 1122 self.unify(&ty, &expected.ty);
1074 let ty = self.resolve_ty_as_possible(ty); 1123 let ty = self.resolve_ty_as_possible(ty);
1075 self.write_expr_ty(expr, ty.clone()); 1124 self.write_expr_ty(expr, ty.clone());
1076 Ok(ty) 1125 ty
1077 } 1126 }
1078 1127
1079 fn infer_block( 1128 fn infer_block(
@@ -1081,7 +1130,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1081 statements: &[Statement], 1130 statements: &[Statement],
1082 tail: Option<ExprId>, 1131 tail: Option<ExprId>,
1083 expected: &Expectation, 1132 expected: &Expectation,
1084 ) -> Cancelable<Ty> { 1133 ) -> Ty {
1085 for stmt in statements { 1134 for stmt in statements {
1086 match stmt { 1135 match stmt {
1087 Statement::Let { 1136 Statement::Let {
@@ -1094,10 +1143,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1094 &self.module, 1143 &self.module,
1095 self.impl_block.as_ref(), 1144 self.impl_block.as_ref(),
1096 type_ref.as_ref(), 1145 type_ref.as_ref(),
1097 )?; 1146 );
1098 let decl_ty = self.insert_type_vars(decl_ty); 1147 let decl_ty = self.insert_type_vars(decl_ty);
1099 let ty = if let Some(expr) = initializer { 1148 let ty = if let Some(expr) = initializer {
1100 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty))?; 1149 let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty));
1101 expr_ty 1150 expr_ty
1102 } else { 1151 } else {
1103 decl_ty 1152 decl_ty
@@ -1106,55 +1155,53 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1106 self.write_pat_ty(*pat, ty); 1155 self.write_pat_ty(*pat, ty);
1107 } 1156 }
1108 Statement::Expr(expr) => { 1157 Statement::Expr(expr) => {
1109 self.infer_expr(*expr, &Expectation::none())?; 1158 self.infer_expr(*expr, &Expectation::none());
1110 } 1159 }
1111 } 1160 }
1112 } 1161 }
1113 let ty = if let Some(expr) = tail { 1162 let ty = if let Some(expr) = tail {
1114 self.infer_expr(expr, expected)? 1163 self.infer_expr(expr, expected)
1115 } else { 1164 } else {
1116 Ty::unit() 1165 Ty::unit()
1117 }; 1166 };
1118 Ok(ty) 1167 ty
1119 } 1168 }
1120 1169
1121 fn collect_fn_signature(&mut self, signature: &FnSignature) -> Cancelable<()> { 1170 fn collect_fn_signature(&mut self, signature: &FnSignature) {
1122 let body = Arc::clone(&self.body); // avoid borrow checker problem 1171 let body = Arc::clone(&self.body); // avoid borrow checker problem
1123 for (type_ref, pat) in signature.params().iter().zip(body.params()) { 1172 for (type_ref, pat) in signature.params().iter().zip(body.params()) {
1124 let ty = self.make_ty(type_ref)?; 1173 let ty = self.make_ty(type_ref);
1125 let ty = self.insert_type_vars(ty); 1174 let ty = self.insert_type_vars(ty);
1126 self.write_pat_ty(*pat, ty); 1175 self.write_pat_ty(*pat, ty);
1127 } 1176 }
1128 self.return_ty = { 1177 self.return_ty = {
1129 let ty = self.make_ty(signature.ret_type())?; 1178 let ty = self.make_ty(signature.ret_type());
1130 let ty = self.insert_type_vars(ty); 1179 let ty = self.insert_type_vars(ty);
1131 ty 1180 ty
1132 }; 1181 };
1133 Ok(())
1134 } 1182 }
1135 1183
1136 fn infer_body(&mut self) -> Cancelable<()> { 1184 fn infer_body(&mut self) {
1137 self.infer_expr( 1185 self.infer_expr(
1138 self.body.body_expr(), 1186 self.body.body_expr(),
1139 &Expectation::has_type(self.return_ty.clone()), 1187 &Expectation::has_type(self.return_ty.clone()),
1140 )?; 1188 );
1141 Ok(())
1142 } 1189 }
1143} 1190}
1144 1191
1145pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Cancelable<Arc<InferenceResult>> { 1192pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Arc<InferenceResult> {
1146 db.check_canceled()?; 1193 db.check_canceled();
1147 let function = Function::new(def_id); // TODO: consts also need inference 1194 let function = Function::new(def_id); // TODO: consts also need inference
1148 let body = function.body(db)?; 1195 let body = function.body(db);
1149 let scopes = db.fn_scopes(def_id)?; 1196 let scopes = db.fn_scopes(def_id);
1150 let module = function.module(db)?; 1197 let module = function.module(db);
1151 let impl_block = function.impl_block(db)?; 1198 let impl_block = function.impl_block(db);
1152 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); 1199 let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block);
1153 1200
1154 let signature = function.signature(db); 1201 let signature = function.signature(db);
1155 ctx.collect_fn_signature(&signature)?; 1202 ctx.collect_fn_signature(&signature);
1156 1203
1157 ctx.infer_body()?; 1204 ctx.infer_body();
1158 1205
1159 Ok(Arc::new(ctx.resolve_all())) 1206 Arc::new(ctx.resolve_all())
1160} 1207}
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 7c3839388..b221bd142 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -6,7 +6,7 @@ use std::sync::Arc;
6 6
7use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
8 8
9use ra_db::{Cancelable, SourceRootId}; 9use ra_db::SourceRootId;
10 10
11use crate::{HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}}; 11use crate::{HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}};
12use super::Ty; 12use super::Ty;
@@ -42,21 +42,21 @@ impl CrateImplBlocks {
42 &'a self, 42 &'a self,
43 db: &'a impl HirDatabase, 43 db: &'a impl HirDatabase,
44 ty: &Ty, 44 ty: &Ty,
45 ) -> impl Iterator<Item = Cancelable<ImplBlock>> + 'a { 45 ) -> impl Iterator<Item = ImplBlock> + 'a {
46 let fingerprint = TyFingerprint::for_impl(ty); 46 let fingerprint = TyFingerprint::for_impl(ty);
47 fingerprint 47 fingerprint
48 .and_then(|f| self.impls.get(&f)) 48 .and_then(|f| self.impls.get(&f))
49 .into_iter() 49 .into_iter()
50 .flat_map(|i| i.iter()) 50 .flat_map(|i| i.iter())
51 .map(move |(module_id, impl_id)| { 51 .map(move |(module_id, impl_id)| {
52 let module_impl_blocks = db.impls_in_module(self.source_root_id, *module_id)?; 52 let module_impl_blocks = db.impls_in_module(self.source_root_id, *module_id);
53 Ok(ImplBlock::from_id(module_impl_blocks, *impl_id)) 53 ImplBlock::from_id(module_impl_blocks, *impl_id)
54 }) 54 })
55 } 55 }
56 56
57 fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) -> Cancelable<()> { 57 fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) {
58 let module_id = module.def_id.loc(db).module_id; 58 let module_id = module.def_id.loc(db).module_id;
59 let module_impl_blocks = db.impls_in_module(self.source_root_id, module_id)?; 59 let module_impl_blocks = db.impls_in_module(self.source_root_id, module_id);
60 60
61 for (impl_id, impl_data) in module_impl_blocks.impls.iter() { 61 for (impl_id, impl_data) in module_impl_blocks.impls.iter() {
62 let impl_block = ImplBlock::from_id(Arc::clone(&module_impl_blocks), impl_id); 62 let impl_block = ImplBlock::from_id(Arc::clone(&module_impl_blocks), impl_id);
@@ -65,7 +65,7 @@ impl CrateImplBlocks {
65 // ignore for now 65 // ignore for now
66 } else { 66 } else {
67 let target_ty = 67 let target_ty =
68 Ty::from_hir(db, &module, Some(&impl_block), impl_data.target_type())?; 68 Ty::from_hir(db, &module, Some(&impl_block), impl_data.target_type());
69 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { 69 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
70 self.impls 70 self.impls
71 .entry(target_ty_fp) 71 .entry(target_ty_fp)
@@ -75,17 +75,15 @@ impl CrateImplBlocks {
75 } 75 }
76 } 76 }
77 77
78 for child in module.children(db)? { 78 for child in module.children(db) {
79 self.collect_recursive(db, child)?; 79 self.collect_recursive(db, child);
80 } 80 }
81
82 Ok(())
83 } 81 }
84 82
85 pub(crate) fn impls_in_crate_query( 83 pub(crate) fn impls_in_crate_query(
86 db: &impl HirDatabase, 84 db: &impl HirDatabase,
87 krate: Crate, 85 krate: Crate,
88 ) -> Cancelable<Arc<CrateImplBlocks>> { 86 ) -> Arc<CrateImplBlocks> {
89 let crate_graph = db.crate_graph(); 87 let crate_graph = db.crate_graph();
90 let file_id = crate_graph.crate_root(krate.crate_id); 88 let file_id = crate_graph.crate_root(krate.crate_id);
91 let source_root_id = db.file_source_root(file_id); 89 let source_root_id = db.file_source_root(file_id);
@@ -93,17 +91,17 @@ impl CrateImplBlocks {
93 source_root_id, 91 source_root_id,
94 impls: FxHashMap::default(), 92 impls: FxHashMap::default(),
95 }; 93 };
96 if let Some(module) = krate.root_module(db)? { 94 if let Some(module) = krate.root_module(db) {
97 crate_impl_blocks.collect_recursive(db, module)?; 95 crate_impl_blocks.collect_recursive(db, module);
98 } 96 }
99 Ok(Arc::new(crate_impl_blocks)) 97 Arc::new(crate_impl_blocks)
100 } 98 }
101} 99}
102 100
103fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Cancelable<Option<Crate>> { 101fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> {
104 match ty { 102 match ty {
105 Ty::Adt { def_id, .. } => def_id.krate(db), 103 Ty::Adt { def_id, .. } => def_id.krate(db),
106 _ => Ok(None), 104 _ => None,
107 } 105 }
108} 106}
109 107
@@ -111,13 +109,13 @@ impl Ty {
111 // TODO: cache this as a query? 109 // TODO: cache this as a query?
112 // - if so, what signature? (TyFingerprint, Name)? 110 // - if so, what signature? (TyFingerprint, Name)?
113 // - or maybe cache all names and def_ids of methods per fingerprint? 111 // - or maybe cache all names and def_ids of methods per fingerprint?
114 pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<DefId>> { 112 pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<DefId> {
115 self.iterate_methods(db, |f| { 113 self.iterate_methods(db, |f| {
116 let sig = f.signature(db); 114 let sig = f.signature(db);
117 if sig.name() == name && sig.has_self_param() { 115 if sig.name() == name && sig.has_self_param() {
118 Ok(Some(f.def_id())) 116 Some(f.def_id())
119 } else { 117 } else {
120 Ok(None) 118 None
121 } 119 }
122 }) 120 })
123 } 121 }
@@ -127,8 +125,8 @@ impl Ty {
127 pub fn iterate_methods<T>( 125 pub fn iterate_methods<T>(
128 self, 126 self,
129 db: &impl HirDatabase, 127 db: &impl HirDatabase,
130 mut callback: impl FnMut(Function) -> Cancelable<Option<T>>, 128 mut callback: impl FnMut(Function) -> Option<T>,
131 ) -> Cancelable<Option<T>> { 129 ) -> Option<T> {
132 // For method calls, rust first does any number of autoderef, and then one 130 // For method calls, rust first does any number of autoderef, and then one
133 // autoref (i.e. when the method takes &self or &mut self). We just ignore 131 // autoref (i.e. when the method takes &self or &mut self). We just ignore
134 // the autoref currently -- when we find a method matching the given name, 132 // the autoref currently -- when we find a method matching the given name,
@@ -139,19 +137,18 @@ impl Ty {
139 // rustc does an autoderef and then autoref again). 137 // rustc does an autoderef and then autoref again).
140 138
141 for derefed_ty in self.autoderef(db) { 139 for derefed_ty in self.autoderef(db) {
142 let krate = match def_crate(db, &derefed_ty)? { 140 let krate = match def_crate(db, &derefed_ty) {
143 Some(krate) => krate, 141 Some(krate) => krate,
144 None => continue, 142 None => continue,
145 }; 143 };
146 let impls = db.impls_in_crate(krate)?; 144 let impls = db.impls_in_crate(krate);
147 145
148 for impl_block in impls.lookup_impl_blocks(db, &derefed_ty) { 146 for impl_block in impls.lookup_impl_blocks(db, &derefed_ty) {
149 let impl_block = impl_block?;
150 for item in impl_block.items() { 147 for item in impl_block.items() {
151 match item { 148 match item {
152 ImplItem::Method(f) => { 149 ImplItem::Method(f) => {
153 if let Some(result) = callback(f.clone())? { 150 if let Some(result) = callback(f.clone()) {
154 return Ok(Some(result)); 151 return Some(result);
155 } 152 }
156 } 153 }
157 _ => {} 154 _ => {}
@@ -159,6 +156,6 @@ impl Ty {
159 } 156 }
160 } 157 }
161 } 158 }
162 Ok(None) 159 None
163 } 160 }
164} 161}
diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs
index 498d42d52..5741ca90d 100644
--- a/crates/ra_hir/src/ty/primitive.rs
+++ b/crates/ra_hir/src/ty/primitive.rs
@@ -2,6 +2,56 @@ use std::fmt;
2 2
3use crate::{Name, KnownName}; 3use crate::{Name, KnownName};
4 4
5#[derive(Debug, Clone, Eq, PartialEq, Hash, Copy)]
6pub enum UncertainIntTy {
7 Unknown,
8 Unsigned(UintTy),
9 Signed(IntTy),
10}
11
12impl UncertainIntTy {
13 pub fn ty_to_string(&self) -> &'static str {
14 match *self {
15 UncertainIntTy::Unknown => "{integer}",
16 UncertainIntTy::Signed(ty) => ty.ty_to_string(),
17 UncertainIntTy::Unsigned(ty) => ty.ty_to_string(),
18 }
19 }
20
21 pub fn from_name(name: &Name) -> Option<UncertainIntTy> {
22 if let Some(ty) = IntTy::from_name(name) {
23 Some(UncertainIntTy::Signed(ty))
24 } else if let Some(ty) = UintTy::from_name(name) {
25 Some(UncertainIntTy::Unsigned(ty))
26 } else {
27 None
28 }
29 }
30}
31
32#[derive(Debug, Clone, Eq, PartialEq, Hash, Copy)]
33pub enum UncertainFloatTy {
34 Unknown,
35 Known(FloatTy),
36}
37
38impl UncertainFloatTy {
39 pub fn ty_to_string(&self) -> &'static str {
40 match *self {
41 UncertainFloatTy::Unknown => "{float}",
42 UncertainFloatTy::Known(ty) => ty.ty_to_string(),
43 }
44 }
45
46 pub fn from_name(name: &Name) -> Option<UncertainFloatTy> {
47 if let Some(ty) = FloatTy::from_name(name) {
48 Some(UncertainFloatTy::Known(ty))
49 } else {
50 None
51 }
52 }
53}
54
5#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] 55#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
6pub enum IntTy { 56pub enum IntTy {
7 Isize, 57 Isize,
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 920188fc9..5d7bc25cc 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -133,6 +133,55 @@ fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
133} 133}
134 134
135#[test] 135#[test]
136fn infer_literals() {
137 check_inference(
138 r##"
139fn test() {
140 5i32;
141 "hello";
142 b"bytes";
143 'c';
144 b'b';
145 3.14;
146 5000;
147 false;
148 true;
149 r#"
150 //! doc
151 // non-doc
152 mod foo {}
153 "#;
154 br#"yolo"#;
155}
156"##,
157 "literals.txt",
158 );
159}
160
161#[test]
162fn infer_unary_op() {
163 check_inference(
164 r#"
165enum SomeType {}
166
167fn test(x: SomeType) {
168 let b = false;
169 let c = !b;
170 let a = 100;
171 let d: i128 = -a;
172 let e = -100;
173 let f = !!!true;
174 -3.14;
175 -x;
176 !x;
177 -"hello";
178}
179"#,
180 "unary_op.txt",
181 );
182}
183
184#[test]
136fn infer_backwards() { 185fn infer_backwards() {
137 check_inference( 186 check_inference(
138 r#" 187 r#"
@@ -180,7 +229,7 @@ fn f(x: bool) -> i32 {
180 0i32 229 0i32
181} 230}
182 231
183fn test() { 232fn test() -> bool {
184 let x = a && b; 233 let x = a && b;
185 let y = true || false; 234 let y = true || false;
186 let z = x == y; 235 let z = x == y;
@@ -277,8 +326,6 @@ fn test(x: &str, y: isize) {
277 let b = (a, x); 326 let b = (a, x);
278 let c = (y, x); 327 let c = (y, x);
279 let d = (c, x); 328 let d = (c, x);
280
281 // we have not infered these case yet.
282 let e = (1, "e"); 329 let e = (1, "e");
283 let f = (e, "d"); 330 let f = (e, "d");
284} 331}
@@ -296,11 +343,9 @@ fn infer(content: &str) -> String {
296 .descendants() 343 .descendants()
297 .filter_map(ast::FnDef::cast) 344 .filter_map(ast::FnDef::cast)
298 { 345 {
299 let func = source_binder::function_from_source(&db, file_id, fn_def) 346 let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap();
300 .unwrap() 347 let inference_result = func.infer(&db);
301 .unwrap(); 348 let body_syntax_mapping = func.body_syntax_mapping(&db);
302 let inference_result = func.infer(&db).unwrap();
303 let body_syntax_mapping = func.body_syntax_mapping(&db).unwrap();
304 let mut types = Vec::new(); 349 let mut types = Vec::new();
305 for (pat, ty) in inference_result.type_of_pat.iter() { 350 for (pat, ty) in inference_result.type_of_pat.iter() {
306 let syntax_ptr = match body_syntax_mapping.pat_syntax(pat) { 351 let syntax_ptr = match body_syntax_mapping.pat_syntax(pat) {
@@ -380,12 +425,10 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
380 } 425 }
381 ", 426 ",
382 ); 427 );
383 let func = source_binder::function_from_position(&db, pos) 428 let func = source_binder::function_from_position(&db, pos).unwrap();
384 .unwrap()
385 .unwrap();
386 { 429 {
387 let events = db.log_executed(|| { 430 let events = db.log_executed(|| {
388 func.infer(&db).unwrap(); 431 func.infer(&db);
389 }); 432 });
390 assert!(format!("{:?}", events).contains("infer")) 433 assert!(format!("{:?}", events).contains("infer"))
391 } 434 }
@@ -404,7 +447,7 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
404 447
405 { 448 {
406 let events = db.log_executed(|| { 449 let events = db.log_executed(|| {
407 func.infer(&db).unwrap(); 450 func.infer(&db);
408 }); 451 });
409 assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events) 452 assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events)
410 } 453 }
diff --git a/crates/ra_hir/src/ty/tests/data/basics.txt b/crates/ra_hir/src/ty/tests/data/basics.txt
index ac7faae0a..e65fe07aa 100644
--- a/crates/ra_hir/src/ty/tests/data/basics.txt
+++ b/crates/ra_hir/src/ty/tests/data/basics.txt
@@ -7,7 +7,7 @@
7[55; 56) 'b': isize 7[55; 56) 'b': isize
8[62; 63) 'c': ! 8[62; 63) 'c': !
9[69; 70) 'd': &str 9[69; 70) 'd': &str
10[76; 82) '1usize': [unknown] 10[76; 82) '1usize': usize
11[88; 94) '1isize': [unknown] 11[88; 94) '1isize': isize
12[100; 106) '"test"': [unknown] 12[100; 106) '"test"': &str
13[112; 118) '1.0f32': [unknown] 13[112; 118) '1.0f32': f32
diff --git a/crates/ra_hir/src/ty/tests/data/binary_op.txt b/crates/ra_hir/src/ty/tests/data/binary_op.txt
index 8a515ac5e..58a727691 100644
--- a/crates/ra_hir/src/ty/tests/data/binary_op.txt
+++ b/crates/ra_hir/src/ty/tests/data/binary_op.txt
@@ -1,46 +1,46 @@
1[6; 7) 'x': bool 1[6; 7) 'x': bool
2[22; 34) '{ 0i32 }': i32 2[22; 34) '{ 0i32 }': i32
3[28; 32) '0i32': i32 3[28; 32) '0i32': i32
4[46; 342) '{ ... < 3 }': bool 4[54; 350) '{ ... < 3 }': bool
5[56; 57) 'x': bool 5[64; 65) 'x': bool
6[60; 61) 'a': bool 6[68; 69) 'a': bool
7[60; 66) 'a && b': bool 7[68; 74) 'a && b': bool
8[65; 66) 'b': bool 8[73; 74) 'b': bool
9[76; 77) 'y': bool 9[84; 85) 'y': bool
10[80; 84) 'true': bool 10[88; 92) 'true': bool
11[80; 93) 'true || false': bool 11[88; 101) 'true || false': bool
12[88; 93) 'false': bool 12[96; 101) 'false': bool
13[103; 104) 'z': bool 13[111; 112) 'z': bool
14[107; 108) 'x': bool 14[115; 116) 'x': bool
15[107; 113) 'x == y': bool 15[115; 121) 'x == y': bool
16[112; 113) 'y': bool 16[120; 121) 'y': bool
17[123; 134) 'minus_forty': isize 17[131; 142) 'minus_forty': isize
18[144; 152) '-40isize': isize 18[152; 160) '-40isize': isize
19[145; 152) '40isize': [unknown] 19[153; 160) '40isize': isize
20[162; 163) 'h': bool 20[170; 171) 'h': bool
21[166; 177) 'minus_forty': isize 21[174; 185) 'minus_forty': isize
22[166; 188) 'minus_...ONST_2': bool 22[174; 196) 'minus_...ONST_2': bool
23[181; 188) 'CONST_2': isize 23[189; 196) 'CONST_2': isize
24[198; 199) 'c': i32 24[206; 207) 'c': i32
25[202; 203) 'f': fn(bool) -> i32 25[210; 211) 'f': fn(bool) -> i32
26[202; 211) 'f(z || y)': i32 26[210; 219) 'f(z || y)': i32
27[202; 215) 'f(z || y) + 5': i32 27[210; 223) 'f(z || y) + 5': i32
28[204; 205) 'z': bool 28[212; 213) 'z': bool
29[204; 210) 'z || y': bool 29[212; 218) 'z || y': bool
30[209; 210) 'y': bool 30[217; 218) 'y': bool
31[214; 215) '5': i32 31[222; 223) '5': i32
32[225; 226) 'd': [unknown] 32[233; 234) 'd': [unknown]
33[229; 230) 'b': [unknown] 33[237; 238) 'b': [unknown]
34[240; 241) 'g': () 34[248; 249) 'g': ()
35[244; 255) 'minus_forty': isize 35[252; 263) 'minus_forty': isize
36[244; 260) 'minus_...y ^= i': () 36[252; 268) 'minus_...y ^= i': ()
37[259; 260) 'i': isize 37[267; 268) 'i': isize
38[270; 273) 'ten': usize 38[278; 281) 'ten': usize
39[283; 285) '10': usize 39[291; 293) '10': usize
40[295; 308) 'ten_is_eleven': bool 40[303; 316) 'ten_is_eleven': bool
41[311; 314) 'ten': usize 41[319; 322) 'ten': usize
42[311; 326) 'ten == some_num': bool 42[319; 334) 'ten == some_num': bool
43[318; 326) 'some_num': usize 43[326; 334) 'some_num': usize
44[333; 336) 'ten': usize 44[341; 344) 'ten': usize
45[333; 340) 'ten < 3': bool 45[341; 348) 'ten < 3': bool
46[339; 340) '3': usize 46[347; 348) '3': usize
diff --git a/crates/ra_hir/src/ty/tests/data/let.txt b/crates/ra_hir/src/ty/tests/data/let.txt
index 30f4a2cf5..8815dba41 100644
--- a/crates/ra_hir/src/ty/tests/data/let.txt
+++ b/crates/ra_hir/src/ty/tests/data/let.txt
@@ -1,6 +1,6 @@
1[11; 71) '{ ...= b; }': () 1[11; 71) '{ ...= b; }': ()
2[21; 22) 'a': [unknown] 2[21; 22) 'a': isize
3[25; 31) '1isize': [unknown] 3[25; 31) '1isize': isize
4[41; 42) 'b': usize 4[41; 42) 'b': usize
5[52; 53) '1': usize 5[52; 53) '1': usize
6[63; 64) 'c': usize 6[63; 64) 'c': usize
diff --git a/crates/ra_hir/src/ty/tests/data/literals.txt b/crates/ra_hir/src/ty/tests/data/literals.txt
new file mode 100644
index 000000000..84ee2c11b
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/literals.txt
@@ -0,0 +1,12 @@
1[11; 201) '{ ...o"#; }': ()
2[17; 21) '5i32': i32
3[27; 34) '"hello"': &str
4[40; 48) 'b"bytes"': &[u8]
5[54; 57) ''c'': char
6[63; 67) 'b'b'': u8
7[73; 77) '3.14': f64
8[83; 87) '5000': i32
9[93; 98) 'false': bool
10[104; 108) 'true': bool
11[114; 182) 'r#" ... "#': &str
12[188; 198) 'br#"yolo"#': &[u8]
diff --git a/crates/ra_hir/src/ty/tests/data/struct.txt b/crates/ra_hir/src/ty/tests/data/struct.txt
index 7b324c82f..be9e12d02 100644
--- a/crates/ra_hir/src/ty/tests/data/struct.txt
+++ b/crates/ra_hir/src/ty/tests/data/struct.txt
@@ -2,14 +2,14 @@
2[82; 83) 'c': [unknown] 2[82; 83) 'c': [unknown]
3[86; 87) 'C': [unknown] 3[86; 87) 'C': [unknown]
4[86; 90) 'C(1)': [unknown] 4[86; 90) 'C(1)': [unknown]
5[88; 89) '1': [unknown] 5[88; 89) '1': i32
6[96; 97) 'B': [unknown] 6[96; 97) 'B': [unknown]
7[107; 108) 'a': A 7[107; 108) 'a': A
8[114; 133) 'A { b:...C(1) }': A 8[114; 133) 'A { b:...C(1) }': A
9[121; 122) 'B': B 9[121; 122) 'B': B
10[127; 128) 'C': [unknown] 10[127; 128) 'C': [unknown]
11[127; 131) 'C(1)': C 11[127; 131) 'C(1)': C
12[129; 130) '1': [unknown] 12[129; 130) '1': i32
13[139; 140) 'a': A 13[139; 140) 'a': A
14[139; 142) 'a.b': B 14[139; 142) 'a.b': B
15[148; 149) 'a': A 15[148; 149) 'a': A
diff --git a/crates/ra_hir/src/ty/tests/data/tuple.txt b/crates/ra_hir/src/ty/tests/data/tuple.txt
index 96169180d..a95d3c286 100644
--- a/crates/ra_hir/src/ty/tests/data/tuple.txt
+++ b/crates/ra_hir/src/ty/tests/data/tuple.txt
@@ -1,6 +1,6 @@
1[9; 10) 'x': &str 1[9; 10) 'x': &str
2[18; 19) 'y': isize 2[18; 19) 'y': isize
3[28; 214) '{ ...d"); }': () 3[28; 170) '{ ...d"); }': ()
4[38; 39) 'a': (u32, &str) 4[38; 39) 'a': (u32, &str)
5[55; 63) '(1, "a")': (u32, &str) 5[55; 63) '(1, "a")': (u32, &str)
6[56; 57) '1': u32 6[56; 57) '1': u32
@@ -17,11 +17,11 @@
17[117; 123) '(c, x)': ((isize, &str), &str) 17[117; 123) '(c, x)': ((isize, &str), &str)
18[118; 119) 'c': (isize, &str) 18[118; 119) 'c': (isize, &str)
19[121; 122) 'x': &str 19[121; 122) 'x': &str
20[177; 178) 'e': ([unknown], [unknown]) 20[133; 134) 'e': (i32, &str)
21[181; 189) '(1, "e")': ([unknown], [unknown]) 21[137; 145) '(1, "e")': (i32, &str)
22[182; 183) '1': [unknown] 22[138; 139) '1': i32
23[185; 188) '"e"': [unknown] 23[141; 144) '"e"': &str
24[199; 200) 'f': (([unknown], [unknown]), [unknown]) 24[155; 156) 'f': ((i32, &str), &str)
25[203; 211) '(e, "d")': (([unknown], [unknown]), [unknown]) 25[159; 167) '(e, "d")': ((i32, &str), &str)
26[204; 205) 'e': ([unknown], [unknown]) 26[160; 161) 'e': (i32, &str)
27[207; 210) '"d"': [unknown] 27[163; 166) '"d"': &str
diff --git a/crates/ra_hir/src/ty/tests/data/unary_op.txt b/crates/ra_hir/src/ty/tests/data/unary_op.txt
new file mode 100644
index 000000000..203022e82
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/unary_op.txt
@@ -0,0 +1,28 @@
1[27; 28) 'x': SomeType
2[40; 197) '{ ...lo"; }': ()
3[50; 51) 'b': bool
4[54; 59) 'false': bool
5[69; 70) 'c': bool
6[73; 75) '!b': bool
7[74; 75) 'b': bool
8[85; 86) 'a': i128
9[89; 92) '100': i128
10[102; 103) 'd': i128
11[112; 114) '-a': i128
12[113; 114) 'a': i128
13[124; 125) 'e': i32
14[128; 132) '-100': i32
15[129; 132) '100': i32
16[142; 143) 'f': bool
17[146; 153) '!!!true': bool
18[147; 153) '!!true': bool
19[148; 153) '!true': bool
20[149; 153) 'true': bool
21[159; 164) '-3.14': f64
22[160; 164) '3.14': f64
23[170; 172) '-x': [unknown]
24[171; 172) 'x': SomeType
25[178; 180) '!x': [unknown]
26[179; 180) 'x': SomeType
27[186; 194) '-"hello"': [unknown]
28[187; 194) '"hello"': &str