diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/adt.rs | 70 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/ids.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/mock.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/module_tree.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/query_definitions.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 60 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__bug_651.snap | 13 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 17 |
16 files changed, 178 insertions, 89 deletions
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml index 3d802ade4..57a4b155b 100644 --- a/crates/ra_hir/Cargo.toml +++ b/crates/ra_hir/Cargo.toml | |||
@@ -12,7 +12,6 @@ rustc-hash = "1.0" | |||
12 | parking_lot = "0.7.0" | 12 | parking_lot = "0.7.0" |
13 | ena = "0.11" | 13 | ena = "0.11" |
14 | join_to_string = "0.1.3" | 14 | join_to_string = "0.1.3" |
15 | salsa = "0.10.0-alpha3" | ||
16 | 15 | ||
17 | ra_syntax = { path = "../ra_syntax" } | 16 | ra_syntax = { path = "../ra_syntax" } |
18 | ra_arena = { path = "../ra_arena" } | 17 | ra_arena = { path = "../ra_arena" } |
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index ec6a10353..22bbad964 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -11,7 +11,7 @@ use ra_syntax::{ | |||
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | Name, AsName, Struct, Enum, EnumVariant, Crate, | 13 | Name, AsName, Struct, Enum, EnumVariant, Crate, |
14 | HirDatabase, HirFileId, | 14 | HirDatabase, HirFileId, StructField, FieldSource, |
15 | type_ref::TypeRef, | 15 | type_ref::TypeRef, |
16 | }; | 16 | }; |
17 | 17 | ||
@@ -150,7 +150,7 @@ impl VariantData { | |||
150 | impl VariantData { | 150 | impl VariantData { |
151 | fn new(flavor: StructFlavor) -> Self { | 151 | fn new(flavor: StructFlavor) -> Self { |
152 | let inner = match flavor { | 152 | let inner = match flavor { |
153 | StructFlavor::Tuple(fl) => { | 153 | ast::StructFlavor::Tuple(fl) => { |
154 | let fields = fl | 154 | let fields = fl |
155 | .fields() | 155 | .fields() |
156 | .enumerate() | 156 | .enumerate() |
@@ -161,7 +161,7 @@ impl VariantData { | |||
161 | .collect(); | 161 | .collect(); |
162 | VariantDataInner::Tuple(fields) | 162 | VariantDataInner::Tuple(fields) |
163 | } | 163 | } |
164 | StructFlavor::Named(fl) => { | 164 | ast::StructFlavor::Named(fl) => { |
165 | let fields = fl | 165 | let fields = fl |
166 | .fields() | 166 | .fields() |
167 | .map(|fd| StructFieldData { | 167 | .map(|fd| StructFieldData { |
@@ -171,8 +171,70 @@ impl VariantData { | |||
171 | .collect(); | 171 | .collect(); |
172 | VariantDataInner::Struct(fields) | 172 | VariantDataInner::Struct(fields) |
173 | } | 173 | } |
174 | StructFlavor::Unit => VariantDataInner::Unit, | 174 | ast::StructFlavor::Unit => VariantDataInner::Unit, |
175 | }; | 175 | }; |
176 | VariantData(inner) | 176 | VariantData(inner) |
177 | } | 177 | } |
178 | } | 178 | } |
179 | |||
180 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
181 | pub enum VariantDef { | ||
182 | Struct(Struct), | ||
183 | EnumVariant(EnumVariant), | ||
184 | } | ||
185 | impl_froms!(VariantDef: Struct, EnumVariant); | ||
186 | |||
187 | impl VariantDef { | ||
188 | pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { | ||
189 | match self { | ||
190 | VariantDef::Struct(it) => it.field(db, name), | ||
191 | VariantDef::EnumVariant(it) => it.field(db, name), | ||
192 | } | ||
193 | } | ||
194 | pub(crate) fn variant_data(self, db: &impl HirDatabase) -> Arc<VariantData> { | ||
195 | match self { | ||
196 | VariantDef::Struct(it) => it.variant_data(db), | ||
197 | VariantDef::EnumVariant(it) => it.variant_data(db), | ||
198 | } | ||
199 | } | ||
200 | } | ||
201 | |||
202 | impl StructField { | ||
203 | pub(crate) fn source_impl(&self, db: &impl HirDatabase) -> (HirFileId, FieldSource) { | ||
204 | let var_data = self.parent.variant_data(db); | ||
205 | let fields = var_data.fields().unwrap(); | ||
206 | let ss; | ||
207 | let es; | ||
208 | let (file_id, struct_flavor) = match self.parent { | ||
209 | VariantDef::Struct(s) => { | ||
210 | let (file_id, source) = s.source(db); | ||
211 | ss = source; | ||
212 | (file_id, ss.flavor()) | ||
213 | } | ||
214 | VariantDef::EnumVariant(e) => { | ||
215 | let (file_id, source) = e.source(db); | ||
216 | es = source; | ||
217 | (file_id, es.flavor()) | ||
218 | } | ||
219 | }; | ||
220 | |||
221 | let field_sources = match struct_flavor { | ||
222 | ast::StructFlavor::Tuple(fl) => fl | ||
223 | .fields() | ||
224 | .map(|it| FieldSource::Pos(it.to_owned())) | ||
225 | .collect(), | ||
226 | ast::StructFlavor::Named(fl) => fl | ||
227 | .fields() | ||
228 | .map(|it| FieldSource::Named(it.to_owned())) | ||
229 | .collect(), | ||
230 | ast::StructFlavor::Unit => Vec::new(), | ||
231 | }; | ||
232 | let field = field_sources | ||
233 | .into_iter() | ||
234 | .zip(fields.iter()) | ||
235 | .find(|(_syntax, (id, _))| *id == self.id) | ||
236 | .unwrap() | ||
237 | .0; | ||
238 | (file_id, field) | ||
239 | } | ||
240 | } | ||
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 118562984..191104890 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -10,8 +10,8 @@ use crate::{ | |||
10 | nameres::{ModuleScope, lower::ImportId}, | 10 | nameres::{ModuleScope, lower::ImportId}, |
11 | db::HirDatabase, | 11 | db::HirDatabase, |
12 | expr::BodySyntaxMapping, | 12 | expr::BodySyntaxMapping, |
13 | ty::{InferenceResult, VariantDef}, | 13 | ty::InferenceResult, |
14 | adt::{EnumVariantId, StructFieldId}, | 14 | adt::{EnumVariantId, StructFieldId, VariantDef}, |
15 | generics::GenericParams, | 15 | generics::GenericParams, |
16 | docs::{Documentation, Docs, docs_from_ast}, | 16 | docs::{Documentation, Docs, docs_from_ast}, |
17 | module_tree::ModuleId, | 17 | module_tree::ModuleId, |
@@ -177,12 +177,25 @@ impl Module { | |||
177 | } | 177 | } |
178 | } | 178 | } |
179 | 179 | ||
180 | impl Docs for Module { | ||
181 | fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> { | ||
182 | self.declaration_source(db) | ||
183 | .and_then(|it| docs_from_ast(&*it.1)) | ||
184 | } | ||
185 | } | ||
186 | |||
180 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 187 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
181 | pub struct StructField { | 188 | pub struct StructField { |
182 | parent: VariantDef, | 189 | pub(crate) parent: VariantDef, |
183 | pub(crate) id: StructFieldId, | 190 | pub(crate) id: StructFieldId, |
184 | } | 191 | } |
185 | 192 | ||
193 | #[derive(Debug)] | ||
194 | pub enum FieldSource { | ||
195 | Named(TreeArc<ast::NamedFieldDef>), | ||
196 | Pos(TreeArc<ast::PosFieldDef>), | ||
197 | } | ||
198 | |||
186 | impl StructField { | 199 | impl StructField { |
187 | pub fn name(&self, db: &impl HirDatabase) -> Name { | 200 | pub fn name(&self, db: &impl HirDatabase) -> Name { |
188 | self.parent.variant_data(db).fields().unwrap()[self.id] | 201 | self.parent.variant_data(db).fields().unwrap()[self.id] |
@@ -190,6 +203,10 @@ impl StructField { | |||
190 | .clone() | 203 | .clone() |
191 | } | 204 | } |
192 | 205 | ||
206 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, FieldSource) { | ||
207 | self.source_impl(db) | ||
208 | } | ||
209 | |||
193 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { | 210 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { |
194 | db.type_for_field(*self) | 211 | db.type_for_field(*self) |
195 | } | 212 | } |
@@ -199,6 +216,15 @@ impl StructField { | |||
199 | } | 216 | } |
200 | } | 217 | } |
201 | 218 | ||
219 | impl Docs for StructField { | ||
220 | fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> { | ||
221 | match self.source(db).1 { | ||
222 | FieldSource::Named(named) => docs_from_ast(&*named), | ||
223 | FieldSource::Pos(..) => return None, | ||
224 | } | ||
225 | } | ||
226 | } | ||
227 | |||
202 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 228 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
203 | pub struct Struct { | 229 | pub struct Struct { |
204 | pub(crate) id: StructId, | 230 | pub(crate) id: StructId, |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 3c82262a2..5df4bd4a1 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; | 3 | use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; |
4 | use ra_db::{SyntaxDatabase, CrateId, salsa}; | 4 | use ra_db::{SourceDatabase, CrateId, salsa}; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | MacroCallId, HirFileId, | 7 | MacroCallId, HirFileId, |
@@ -18,10 +18,10 @@ use crate::{ | |||
18 | generics::{GenericParams, GenericDef}, | 18 | generics::{GenericParams, GenericDef}, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | #[salsa::query_group] | 21 | #[salsa::query_group(HirDatabaseStorage)] |
22 | pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> { | 22 | pub trait HirDatabase: SourceDatabase + AsRef<HirInterner> { |
23 | #[salsa::invoke(HirFileId::hir_source_file)] | 23 | #[salsa::invoke(HirFileId::hir_parse)] |
24 | fn hir_source_file(&self, file_id: HirFileId) -> TreeArc<SourceFile>; | 24 | fn hir_parse(&self, file_id: HirFileId) -> TreeArc<SourceFile>; |
25 | 25 | ||
26 | #[salsa::invoke(crate::macros::expand_macro_invocation)] | 26 | #[salsa::invoke(crate::macros::expand_macro_invocation)] |
27 | fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>; | 27 | fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>; |
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 5272656ec..7dd4b540e 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -86,12 +86,9 @@ impl HirFileId { | |||
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
89 | pub(crate) fn hir_source_file( | 89 | pub(crate) fn hir_parse(db: &impl HirDatabase, file_id: HirFileId) -> TreeArc<SourceFile> { |
90 | db: &impl HirDatabase, | ||
91 | file_id: HirFileId, | ||
92 | ) -> TreeArc<SourceFile> { | ||
93 | match file_id.0 { | 90 | match file_id.0 { |
94 | HirFileIdRepr::File(file_id) => db.source_file(file_id), | 91 | HirFileIdRepr::File(file_id) => db.parse(file_id), |
95 | HirFileIdRepr::Macro(m) => { | 92 | HirFileIdRepr::Macro(m) => { |
96 | if let Some(exp) = db.expand_macro_invocation(m) { | 93 | if let Some(exp) = db.expand_macro_invocation(m) { |
97 | return exp.file(); | 94 | return exp.file(); |
@@ -370,7 +367,7 @@ impl SourceFileItems { | |||
370 | self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(), | 367 | self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(), |
371 | ); | 368 | ); |
372 | } | 369 | } |
373 | pub fn id_of_source_file(&self) -> SourceFileItemId { | 370 | pub fn id_of_parse(&self) -> SourceFileItemId { |
374 | let (id, _syntax) = self.arena.iter().next().unwrap(); | 371 | let (id, _syntax) = self.arena.iter().next().unwrap(); |
375 | id | 372 | id |
376 | } | 373 | } |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 596f9c38c..eaf8565ee 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -68,7 +68,7 @@ pub use self::code_model_api::{ | |||
68 | Module, ModuleDef, ModuleSource, Problem, | 68 | Module, ModuleDef, ModuleSource, Problem, |
69 | Struct, Enum, EnumVariant, | 69 | Struct, Enum, EnumVariant, |
70 | Function, FnSignature, ScopeEntryWithSyntax, | 70 | Function, FnSignature, ScopeEntryWithSyntax, |
71 | StructField, | 71 | StructField, FieldSource, |
72 | Static, Const, | 72 | Static, Const, |
73 | Trait, Type, | 73 | Trait, Type, |
74 | }; | 74 | }; |
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 36b174cd6..7da15eca0 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs | |||
@@ -2,7 +2,7 @@ use std::{sync::Arc, panic}; | |||
2 | 2 | ||
3 | use parking_lot::Mutex; | 3 | use parking_lot::Mutex; |
4 | use ra_db::{ | 4 | use ra_db::{ |
5 | BaseDatabase, FilePosition, FileId, CrateGraph, SourceRoot, SourceRootId, FilesDatabase, | 5 | CheckCanceled, FilePosition, FileId, CrateGraph, SourceRoot, SourceRootId, SourceDatabase, salsa, |
6 | }; | 6 | }; |
7 | use relative_path::RelativePathBuf; | 7 | use relative_path::RelativePathBuf; |
8 | use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset}; | 8 | use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset}; |
@@ -11,7 +11,7 @@ use crate::{db, HirInterner}; | |||
11 | 11 | ||
12 | pub const WORKSPACE: SourceRootId = SourceRootId(0); | 12 | pub const WORKSPACE: SourceRootId = SourceRootId(0); |
13 | 13 | ||
14 | #[salsa::database(ra_db::FilesDatabase, ra_db::SyntaxDatabase, db::HirDatabase)] | 14 | #[salsa::database(ra_db::SourceDatabaseStorage, db::HirDatabaseStorage)] |
15 | #[derive(Debug)] | 15 | #[derive(Debug)] |
16 | pub(crate) struct MockDatabase { | 16 | pub(crate) struct MockDatabase { |
17 | events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>, | 17 | events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>, |
@@ -140,8 +140,6 @@ impl Default for MockDatabase { | |||
140 | file_counter: 0, | 140 | file_counter: 0, |
141 | }; | 141 | }; |
142 | db.set_crate_graph(Default::default()); | 142 | db.set_crate_graph(Default::default()); |
143 | db.set_local_roots(Default::default()); | ||
144 | db.set_library_roots(Default::default()); | ||
145 | db | 143 | db |
146 | } | 144 | } |
147 | } | 145 | } |
@@ -157,7 +155,7 @@ impl salsa::ParallelDatabase for MockDatabase { | |||
157 | } | 155 | } |
158 | } | 156 | } |
159 | 157 | ||
160 | impl BaseDatabase for MockDatabase {} | 158 | impl CheckCanceled for MockDatabase {} |
161 | 159 | ||
162 | impl AsRef<HirInterner> for MockDatabase { | 160 | impl AsRef<HirInterner> for MockDatabase { |
163 | fn as_ref(&self) -> &HirInterner { | 161 | fn as_ref(&self) -> &HirInterner { |
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs index c00834c4c..d5ad9decb 100644 --- a/crates/ra_hir/src/module_tree.rs +++ b/crates/ra_hir/src/module_tree.rs | |||
@@ -1,6 +1,5 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
4 | use arrayvec::ArrayVec; | 3 | use arrayvec::ArrayVec; |
5 | use relative_path::RelativePathBuf; | 4 | use relative_path::RelativePathBuf; |
6 | use ra_db::{FileId, SourceRoot, CrateId}; | 5 | use ra_db::{FileId, SourceRoot, CrateId}; |
@@ -147,28 +146,21 @@ impl ModuleTree { | |||
147 | let file_id = crate_graph.crate_root(crate_id); | 146 | let file_id = crate_graph.crate_root(crate_id); |
148 | let source_root_id = db.file_source_root(file_id); | 147 | let source_root_id = db.file_source_root(file_id); |
149 | 148 | ||
150 | let mut roots = FxHashMap::default(); | ||
151 | let mut visited = FxHashSet::default(); | ||
152 | |||
153 | let source_root = db.source_root(source_root_id); | 149 | let source_root = db.source_root(source_root_id); |
154 | let source = SourceItemId { | 150 | let source = SourceItemId { |
155 | file_id: file_id.into(), | 151 | file_id: file_id.into(), |
156 | item_id: None, | 152 | item_id: None, |
157 | }; | 153 | }; |
158 | let module_id = self.init_subtree(db, &source_root, &mut visited, &mut roots, None, source); | 154 | self.init_subtree(db, &source_root, None, source); |
159 | roots.insert(file_id, module_id); | ||
160 | } | 155 | } |
161 | 156 | ||
162 | fn init_subtree( | 157 | fn init_subtree( |
163 | &mut self, | 158 | &mut self, |
164 | db: &impl HirDatabase, | 159 | db: &impl HirDatabase, |
165 | source_root: &SourceRoot, | 160 | source_root: &SourceRoot, |
166 | visited: &mut FxHashSet<SourceItemId>, | ||
167 | roots: &mut FxHashMap<FileId, ModuleId>, | ||
168 | parent: Option<LinkId>, | 161 | parent: Option<LinkId>, |
169 | source: SourceItemId, | 162 | source: SourceItemId, |
170 | ) -> ModuleId { | 163 | ) -> ModuleId { |
171 | visited.insert(source); | ||
172 | let id = self.alloc_mod(ModuleData { | 164 | let id = self.alloc_mod(ModuleData { |
173 | source, | 165 | source, |
174 | parent, | 166 | parent, |
@@ -187,28 +179,21 @@ impl ModuleTree { | |||
187 | let (points_to, problem) = resolve_submodule(db, source.file_id, &sub.name); | 179 | let (points_to, problem) = resolve_submodule(db, source.file_id, &sub.name); |
188 | let points_to = points_to | 180 | let points_to = points_to |
189 | .into_iter() | 181 | .into_iter() |
190 | .map(|file_id| match roots.remove(&file_id) { | 182 | .map(|file_id| { |
191 | Some(module_id) => { | 183 | self.init_subtree( |
192 | self.mods[module_id].parent = Some(link); | ||
193 | module_id | ||
194 | } | ||
195 | None => self.init_subtree( | ||
196 | db, | 184 | db, |
197 | source_root, | 185 | source_root, |
198 | visited, | ||
199 | roots, | ||
200 | Some(link), | 186 | Some(link), |
201 | SourceItemId { | 187 | SourceItemId { |
202 | file_id: file_id.into(), | 188 | file_id: file_id.into(), |
203 | item_id: None, | 189 | item_id: None, |
204 | }, | 190 | }, |
205 | ), | 191 | ) |
206 | }) | 192 | }) |
207 | .collect::<Vec<_>>(); | 193 | .collect::<Vec<_>>(); |
208 | (points_to, problem) | 194 | (points_to, problem) |
209 | } else { | 195 | } else { |
210 | let points_to = | 196 | let points_to = self.init_subtree(db, source_root, Some(link), sub.source); |
211 | self.init_subtree(db, source_root, visited, roots, Some(link), sub.source); | ||
212 | (vec![points_to], None) | 197 | (vec![points_to], None) |
213 | }; | 198 | }; |
214 | 199 | ||
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 028c1882f..5193900e0 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -190,7 +190,12 @@ where | |||
190 | self.populate_module(module_id, Arc::clone(items)); | 190 | self.populate_module(module_id, Arc::clone(items)); |
191 | } | 191 | } |
192 | 192 | ||
193 | let mut iter = 0; | ||
193 | loop { | 194 | loop { |
195 | iter += 1; | ||
196 | if iter > 1000 { | ||
197 | panic!("failed to reach fixedpoint after 1000 iters") | ||
198 | } | ||
194 | let processed_imports_count = self.processed_imports.len(); | 199 | let processed_imports_count = self.processed_imports.len(); |
195 | for &module_id in self.input.keys() { | 200 | for &module_id in self.input.keys() { |
196 | self.db.check_canceled(); | 201 | self.db.check_canceled(); |
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index b4fe99ea7..1d77548f3 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -129,7 +129,7 @@ impl LoweredModule { | |||
129 | let id = loc.id(db); | 129 | let id = loc.id(db); |
130 | let file_id = HirFileId::from(id); | 130 | let file_id = HirFileId::from(id); |
131 | //FIXME: expand recursively | 131 | //FIXME: expand recursively |
132 | for item in db.hir_source_file(file_id).items() { | 132 | for item in db.hir_parse(file_id).items() { |
133 | self.add_def_id(source_map, db, module, file_id, item); | 133 | self.add_def_id(source_map, db, module, file_id, item); |
134 | } | 134 | } |
135 | } | 135 | } |
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index 24936976c..e72781f51 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_db::{CrateGraph, SourceRootId, FilesDatabase}; | 3 | use ra_db::{CrateGraph, SourceRootId, SourceDatabase}; |
4 | use relative_path::RelativePath; | 4 | use relative_path::RelativePath; |
5 | use test_utils::{assert_eq_text, covers}; | 5 | use test_utils::{assert_eq_text, covers}; |
6 | 6 | ||
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index cf8c7e435..61c93a964 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs | |||
@@ -23,7 +23,7 @@ pub(super) fn fn_scopes(db: &impl HirDatabase, func: Function) -> Arc<FnScopes> | |||
23 | } | 23 | } |
24 | 24 | ||
25 | pub(super) fn file_items(db: &impl HirDatabase, file_id: HirFileId) -> Arc<SourceFileItems> { | 25 | pub(super) fn file_items(db: &impl HirDatabase, file_id: HirFileId) -> Arc<SourceFileItems> { |
26 | let source_file = db.hir_source_file(file_id); | 26 | let source_file = db.hir_parse(file_id); |
27 | let res = SourceFileItems::new(file_id, &source_file); | 27 | let res = SourceFileItems::new(file_id, &source_file); |
28 | Arc::new(res) | 28 | Arc::new(res) |
29 | } | 29 | } |
@@ -34,10 +34,7 @@ pub(super) fn file_item( | |||
34 | ) -> TreeArc<SyntaxNode> { | 34 | ) -> TreeArc<SyntaxNode> { |
35 | match source_item_id.item_id { | 35 | match source_item_id.item_id { |
36 | Some(id) => db.file_items(source_item_id.file_id)[id].to_owned(), | 36 | Some(id) => db.file_items(source_item_id.file_id)[id].to_owned(), |
37 | None => db | 37 | None => db.hir_parse(source_item_id.file_id).syntax().to_owned(), |
38 | .hir_source_file(source_item_id.file_id) | ||
39 | .syntax() | ||
40 | .to_owned(), | ||
41 | } | 38 | } |
42 | } | 39 | } |
43 | 40 | ||
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index dbe040805..c0b3f1cd4 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -43,7 +43,7 @@ pub fn module_from_declaration( | |||
43 | 43 | ||
44 | /// Locates the module by position in the source code. | 44 | /// Locates the module by position in the source code. |
45 | pub fn module_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Module> { | 45 | pub fn module_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Module> { |
46 | let file = db.source_file(position.file_id); | 46 | let file = db.parse(position.file_id); |
47 | match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) { | 47 | match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) { |
48 | Some(m) if !m.has_semi() => module_from_inline(db, position.file_id.into(), m), | 48 | Some(m) if !m.has_semi() => module_from_inline(db, position.file_id.into(), m), |
49 | _ => module_from_file_id(db, position.file_id.into()), | 49 | _ => module_from_file_id(db, position.file_id.into()), |
@@ -95,7 +95,7 @@ fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Option<Mod | |||
95 | } | 95 | } |
96 | 96 | ||
97 | pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> { | 97 | pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> { |
98 | let file = db.source_file(position.file_id); | 98 | let file = db.parse(position.file_id); |
99 | let fn_def = find_node_at_offset::<ast::FnDef>(file.syntax(), position.offset)?; | 99 | let fn_def = find_node_at_offset::<ast::FnDef>(file.syntax(), position.offset)?; |
100 | function_from_source(db, position.file_id, fn_def) | 100 | function_from_source(db, position.file_id, fn_def) |
101 | } | 101 | } |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index c57e222dd..179ebddee 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -38,7 +38,7 @@ use crate::{ | |||
38 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, | 38 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, |
39 | generics::GenericParams, | 39 | generics::GenericParams, |
40 | path::GenericArg, | 40 | path::GenericArg, |
41 | adt::VariantData, | 41 | adt::VariantDef, |
42 | }; | 42 | }; |
43 | 43 | ||
44 | /// The ID of a type variable. | 44 | /// The ID of a type variable. |
@@ -696,28 +696,6 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { | |||
696 | } | 696 | } |
697 | } | 697 | } |
698 | 698 | ||
699 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
700 | pub enum VariantDef { | ||
701 | Struct(Struct), | ||
702 | EnumVariant(EnumVariant), | ||
703 | } | ||
704 | impl_froms!(VariantDef: Struct, EnumVariant); | ||
705 | |||
706 | impl VariantDef { | ||
707 | pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { | ||
708 | match self { | ||
709 | VariantDef::Struct(it) => it.field(db, name), | ||
710 | VariantDef::EnumVariant(it) => it.field(db, name), | ||
711 | } | ||
712 | } | ||
713 | pub(crate) fn variant_data(self, db: &impl HirDatabase) -> Arc<VariantData> { | ||
714 | match self { | ||
715 | VariantDef::Struct(it) => it.variant_data(db), | ||
716 | VariantDef::EnumVariant(it) => it.variant_data(db), | ||
717 | } | ||
718 | } | ||
719 | } | ||
720 | |||
721 | pub(super) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { | 699 | pub(super) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { |
722 | let parent_def = field.parent_def(db); | 700 | let parent_def = field.parent_def(db); |
723 | let (generics, module) = match parent_def { | 701 | let (generics, module) = match parent_def { |
@@ -732,8 +710,10 @@ pub(super) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { | |||
732 | /// The result of type inference: A mapping from expressions and patterns to types. | 710 | /// The result of type inference: A mapping from expressions and patterns to types. |
733 | #[derive(Clone, PartialEq, Eq, Debug)] | 711 | #[derive(Clone, PartialEq, Eq, Debug)] |
734 | pub struct InferenceResult { | 712 | pub struct InferenceResult { |
735 | /// For each method call expr, record the function it resolved to. | 713 | /// For each method call expr, records the function it resolves to. |
736 | method_resolutions: FxHashMap<ExprId, Function>, | 714 | method_resolutions: FxHashMap<ExprId, Function>, |
715 | /// For each field access expr, records the field it resolves to. | ||
716 | field_resolutions: FxHashMap<ExprId, StructField>, | ||
737 | type_of_expr: ArenaMap<ExprId, Ty>, | 717 | type_of_expr: ArenaMap<ExprId, Ty>, |
738 | type_of_pat: ArenaMap<PatId, Ty>, | 718 | type_of_pat: ArenaMap<PatId, Ty>, |
739 | } | 719 | } |
@@ -742,6 +722,9 @@ impl InferenceResult { | |||
742 | pub fn method_resolution(&self, expr: ExprId) -> Option<Function> { | 722 | pub fn method_resolution(&self, expr: ExprId) -> Option<Function> { |
743 | self.method_resolutions.get(&expr).map(|it| *it) | 723 | self.method_resolutions.get(&expr).map(|it| *it) |
744 | } | 724 | } |
725 | pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> { | ||
726 | self.field_resolutions.get(&expr).map(|it| *it) | ||
727 | } | ||
745 | } | 728 | } |
746 | 729 | ||
747 | impl Index<ExprId> for InferenceResult { | 730 | impl Index<ExprId> for InferenceResult { |
@@ -770,6 +753,7 @@ struct InferenceContext<'a, D: HirDatabase> { | |||
770 | impl_block: Option<ImplBlock>, | 753 | impl_block: Option<ImplBlock>, |
771 | var_unification_table: InPlaceUnificationTable<TypeVarId>, | 754 | var_unification_table: InPlaceUnificationTable<TypeVarId>, |
772 | method_resolutions: FxHashMap<ExprId, Function>, | 755 | method_resolutions: FxHashMap<ExprId, Function>, |
756 | field_resolutions: FxHashMap<ExprId, StructField>, | ||
773 | type_of_expr: ArenaMap<ExprId, Ty>, | 757 | type_of_expr: ArenaMap<ExprId, Ty>, |
774 | type_of_pat: ArenaMap<PatId, Ty>, | 758 | type_of_pat: ArenaMap<PatId, Ty>, |
775 | /// The return type of the function being inferred. | 759 | /// The return type of the function being inferred. |
@@ -806,7 +790,10 @@ fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | |||
806 | | BinaryOp::BitwiseAnd | 790 | | BinaryOp::BitwiseAnd |
807 | | BinaryOp::BitwiseOr | 791 | | BinaryOp::BitwiseOr |
808 | | BinaryOp::BitwiseXor => match rhs_ty { | 792 | | BinaryOp::BitwiseXor => match rhs_ty { |
809 | Ty::Int(..) | Ty::Float(..) => rhs_ty, | 793 | Ty::Int(..) |
794 | | Ty::Float(..) | ||
795 | | Ty::Infer(InferTy::IntVar(..)) | ||
796 | | Ty::Infer(InferTy::FloatVar(..)) => rhs_ty, | ||
810 | _ => Ty::Unknown, | 797 | _ => Ty::Unknown, |
811 | }, | 798 | }, |
812 | BinaryOp::RangeRightOpen | BinaryOp::RangeRightClosed => Ty::Unknown, | 799 | BinaryOp::RangeRightOpen | BinaryOp::RangeRightClosed => Ty::Unknown, |
@@ -861,6 +848,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
861 | ) -> Self { | 848 | ) -> Self { |
862 | InferenceContext { | 849 | InferenceContext { |
863 | method_resolutions: FxHashMap::default(), | 850 | method_resolutions: FxHashMap::default(), |
851 | field_resolutions: FxHashMap::default(), | ||
864 | type_of_expr: ArenaMap::default(), | 852 | type_of_expr: ArenaMap::default(), |
865 | type_of_pat: ArenaMap::default(), | 853 | type_of_pat: ArenaMap::default(), |
866 | var_unification_table: InPlaceUnificationTable::new(), | 854 | var_unification_table: InPlaceUnificationTable::new(), |
@@ -886,6 +874,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
886 | } | 874 | } |
887 | InferenceResult { | 875 | InferenceResult { |
888 | method_resolutions: mem::replace(&mut self.method_resolutions, Default::default()), | 876 | method_resolutions: mem::replace(&mut self.method_resolutions, Default::default()), |
877 | field_resolutions: mem::replace(&mut self.field_resolutions, Default::default()), | ||
889 | type_of_expr: expr_types, | 878 | type_of_expr: expr_types, |
890 | type_of_pat: pat_types, | 879 | type_of_pat: pat_types, |
891 | } | 880 | } |
@@ -899,6 +888,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
899 | self.method_resolutions.insert(expr, func); | 888 | self.method_resolutions.insert(expr, func); |
900 | } | 889 | } |
901 | 890 | ||
891 | fn write_field_resolution(&mut self, expr: ExprId, field: StructField) { | ||
892 | self.field_resolutions.insert(expr, field); | ||
893 | } | ||
894 | |||
902 | fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { | 895 | fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { |
903 | self.type_of_pat.insert(pat, ty); | 896 | self.type_of_pat.insert(pat, ty); |
904 | } | 897 | } |
@@ -1251,9 +1244,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1251 | ty | 1244 | ty |
1252 | } | 1245 | } |
1253 | 1246 | ||
1254 | fn infer_expr(&mut self, expr: ExprId, expected: &Expectation) -> Ty { | 1247 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { |
1255 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 1248 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
1256 | let ty = match &body[expr] { | 1249 | let ty = match &body[tgt_expr] { |
1257 | Expr::Missing => Ty::Unknown, | 1250 | Expr::Missing => Ty::Unknown, |
1258 | Expr::If { | 1251 | Expr::If { |
1259 | condition, | 1252 | condition, |
@@ -1344,7 +1337,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1344 | let resolved = receiver_ty.clone().lookup_method(self.db, method_name); | 1337 | let resolved = receiver_ty.clone().lookup_method(self.db, method_name); |
1345 | let method_ty = match resolved { | 1338 | let method_ty = match resolved { |
1346 | Some(func) => { | 1339 | Some(func) => { |
1347 | self.write_method_resolution(expr, func); | 1340 | self.write_method_resolution(tgt_expr, func); |
1348 | self.db.type_for_def(func.into()) | 1341 | self.db.type_for_def(func.into()) |
1349 | } | 1342 | } |
1350 | None => Ty::Unknown, | 1343 | None => Ty::Unknown, |
@@ -1389,7 +1382,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1389 | 1382 | ||
1390 | expected.ty | 1383 | expected.ty |
1391 | } | 1384 | } |
1392 | Expr::Path(p) => self.infer_path_expr(expr, p).unwrap_or(Ty::Unknown), | 1385 | Expr::Path(p) => self.infer_path_expr(tgt_expr, p).unwrap_or(Ty::Unknown), |
1393 | Expr::Continue => Ty::Never, | 1386 | Expr::Continue => Ty::Never, |
1394 | Expr::Break { expr } => { | 1387 | Expr::Break { expr } => { |
1395 | if let Some(expr) = expr { | 1388 | if let Some(expr) = expr { |
@@ -1436,9 +1429,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1436 | def_id: AdtDef::Struct(s), | 1429 | def_id: AdtDef::Struct(s), |
1437 | ref substs, | 1430 | ref substs, |
1438 | .. | 1431 | .. |
1439 | } => s | 1432 | } => s.field(self.db, name).map(|field| { |
1440 | .field(self.db, name) | 1433 | self.write_field_resolution(tgt_expr, field); |
1441 | .map(|field| field.ty(self.db).subst(substs)), | 1434 | field.ty(self.db).subst(substs) |
1435 | }), | ||
1442 | _ => None, | 1436 | _ => None, |
1443 | }) | 1437 | }) |
1444 | .unwrap_or(Ty::Unknown); | 1438 | .unwrap_or(Ty::Unknown); |
@@ -1545,7 +1539,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1545 | let ty = self.insert_type_vars_shallow(ty); | 1539 | let ty = self.insert_type_vars_shallow(ty); |
1546 | self.unify(&ty, &expected.ty); | 1540 | self.unify(&ty, &expected.ty); |
1547 | let ty = self.resolve_ty_as_possible(ty); | 1541 | let ty = self.resolve_ty_as_possible(ty); |
1548 | self.write_expr_ty(expr, ty.clone()); | 1542 | self.write_expr_ty(tgt_expr, ty.clone()); |
1549 | ty | 1543 | ty |
1550 | } | 1544 | } |
1551 | 1545 | ||
diff --git a/crates/ra_hir/src/ty/snapshots/tests__bug_651.snap b/crates/ra_hir/src/ty/snapshots/tests__bug_651.snap new file mode 100644 index 000000000..d23d3f139 --- /dev/null +++ b/crates/ra_hir/src/ty/snapshots/tests__bug_651.snap | |||
@@ -0,0 +1,13 @@ | |||
1 | --- | ||
2 | created: "2019-01-25T20:31:47.275112244+00:00" | ||
3 | creator: [email protected] | ||
4 | expression: "&result" | ||
5 | source: crates/ra_hir/src/ty/tests.rs | ||
6 | --- | ||
7 | [11; 41) '{ ...+ y; }': () | ||
8 | [21; 22) 'y': i32 | ||
9 | [25; 27) '92': i32 | ||
10 | [33; 34) '1': i32 | ||
11 | [33; 38) '1 + y': i32 | ||
12 | [37; 38) 'y': i32 | ||
13 | |||
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 92c74cf00..e0b0689f8 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | use std::fmt::Write; | 2 | use std::fmt::Write; |
3 | 3 | ||
4 | use ra_db::{SyntaxDatabase, salsa::Database}; | 4 | use ra_db::{SourceDatabase, salsa::Database}; |
5 | use ra_syntax::ast::{self, AstNode}; | 5 | use ra_syntax::ast::{self, AstNode}; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
@@ -532,9 +532,22 @@ fn test() { | |||
532 | ); | 532 | ); |
533 | } | 533 | } |
534 | 534 | ||
535 | #[test] | ||
536 | fn bug_651() { | ||
537 | check_inference( | ||
538 | "bug_651", | ||
539 | r#" | ||
540 | fn quux() { | ||
541 | let y = 92; | ||
542 | 1 + y; | ||
543 | } | ||
544 | "#, | ||
545 | ); | ||
546 | } | ||
547 | |||
535 | fn infer(content: &str) -> String { | 548 | fn infer(content: &str) -> String { |
536 | let (db, _, file_id) = MockDatabase::with_single_file(content); | 549 | let (db, _, file_id) = MockDatabase::with_single_file(content); |
537 | let source_file = db.source_file(file_id); | 550 | let source_file = db.parse(file_id); |
538 | let mut acc = String::new(); | 551 | let mut acc = String::new(); |
539 | for fn_def in source_file | 552 | for fn_def in source_file |
540 | .syntax() | 553 | .syntax() |