aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_db/Cargo.toml2
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs10
-rw-r--r--crates/ra_hir/src/db.rs7
-rw-r--r--crates/ra_hir/src/ids.rs38
-rw-r--r--crates/ra_hir/src/module_tree.rs99
-rw-r--r--crates/ra_hir/src/nameres.rs2
-rw-r--r--crates/ra_hir/src/nameres/lower.rs5
-rw-r--r--crates/ra_hir/src/query_definitions.rs12
-rw-r--r--crates/ra_hir/src/source_binder.rs28
-rw-r--r--crates/ra_syntax/src/grammar/expressions.rs2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.rs8
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.txt109
12 files changed, 216 insertions, 106 deletions
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml
index 9aa77f72e..2d39b77ed 100644
--- a/crates/ra_db/Cargo.toml
+++ b/crates/ra_db/Cargo.toml
@@ -6,7 +6,7 @@ authors = ["Aleksey Kladov <[email protected]>"]
6 6
7[dependencies] 7[dependencies]
8relative-path = "0.4.0" 8relative-path = "0.4.0"
9salsa = "0.10.0-alpha4" 9salsa = "0.10.0-alpha5"
10rustc-hash = "1.0" 10rustc-hash = "1.0"
11parking_lot = "0.7.0" 11parking_lot = "0.7.0"
12 12
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs
index 480ec27bf..418d59c91 100644
--- a/crates/ra_hir/src/code_model_impl/module.rs
+++ b/crates/ra_hir/src/code_model_impl/module.rs
@@ -25,9 +25,10 @@ impl Module {
25 25
26 pub(crate) fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) { 26 pub(crate) fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) {
27 let module_tree = db.module_tree(self.krate); 27 let module_tree = db.module_tree(self.krate);
28 let source = self.module_id.source(&module_tree); 28 let file_id = self.module_id.file_id(&module_tree);
29 let module_source = ModuleSource::from_source_item_id(db, source); 29 let decl_id = self.module_id.decl_id(&module_tree);
30 let file_id = source.file_id.as_original_file(); 30 let module_source = ModuleSource::new(db, file_id, decl_id);
31 let file_id = file_id.as_original_file();
31 (file_id, module_source) 32 (file_id, module_source)
32 } 33 }
33 34
@@ -39,8 +40,7 @@ impl Module {
39 let link = self.module_id.parent_link(&module_tree)?; 40 let link = self.module_id.parent_link(&module_tree)?;
40 let file_id = link 41 let file_id = link
41 .owner(&module_tree) 42 .owner(&module_tree)
42 .source(&module_tree) 43 .file_id(&module_tree)
43 .file_id
44 .as_original_file(); 44 .as_original_file();
45 let src = link.source(&module_tree, db); 45 let src = link.source(&module_tree, db);
46 Some((file_id, src)) 46 Some((file_id, src))
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 5df4bd4a1..3f76b769d 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -16,6 +16,7 @@ use crate::{
16 adt::{StructData, EnumData}, 16 adt::{StructData, EnumData},
17 impl_block::ModuleImplBlocks, 17 impl_block::ModuleImplBlocks,
18 generics::{GenericParams, GenericDef}, 18 generics::{GenericParams, GenericDef},
19 ids::SourceFileItemId,
19}; 20};
20 21
21#[salsa::query_group(HirDatabaseStorage)] 22#[salsa::query_group(HirDatabaseStorage)]
@@ -51,7 +52,11 @@ pub trait HirDatabase: SourceDatabase + AsRef<HirInterner> {
51 fn file_item(&self, source_item_id: SourceItemId) -> TreeArc<SyntaxNode>; 52 fn file_item(&self, source_item_id: SourceItemId) -> TreeArc<SyntaxNode>;
52 53
53 #[salsa::invoke(crate::module_tree::Submodule::submodules_query)] 54 #[salsa::invoke(crate::module_tree::Submodule::submodules_query)]
54 fn submodules(&self, source: SourceItemId) -> Arc<Vec<crate::module_tree::Submodule>>; 55 fn submodules(
56 &self,
57 file_id: HirFileId,
58 delc_id: Option<SourceFileItemId>,
59 ) -> Arc<Vec<crate::module_tree::Submodule>>;
55 60
56 #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_query)] 61 #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_query)]
57 fn lower_module(&self, module: Module) -> (Arc<LoweredModule>, Arc<ImportSourceMap>); 62 fn lower_module(&self, module: Module) -> (Arc<LoweredModule>, Arc<ImportSourceMap>);
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 7dd4b540e..0e4dc6261 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -4,7 +4,7 @@ use std::{
4}; 4};
5 5
6use ra_db::{LocationIntener, FileId}; 6use ra_db::{LocationIntener, FileId};
7use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; 7use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, SyntaxNodePtr, ast};
8use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; 8use ra_arena::{Arena, RawId, ArenaId, impl_arena_id};
9 9
10use crate::{ 10use crate::{
@@ -203,7 +203,7 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
203 let items = ctx.db.file_items(ctx.file_id); 203 let items = ctx.db.file_items(ctx.file_id);
204 let raw = SourceItemId { 204 let raw = SourceItemId {
205 file_id: ctx.file_id, 205 file_id: ctx.file_id,
206 item_id: Some(items.id_of(ctx.file_id, ast.syntax())), 206 item_id: items.id_of(ctx.file_id, ast.syntax()),
207 }; 207 };
208 let loc = ItemLoc { 208 let loc = ItemLoc {
209 module: ctx.module, 209 module: ctx.module,
@@ -301,15 +301,14 @@ impl_arena_id!(SourceFileItemId);
301#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 301#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
302pub struct SourceItemId { 302pub struct SourceItemId {
303 pub(crate) file_id: HirFileId, 303 pub(crate) file_id: HirFileId,
304 /// None for the whole file. 304 pub(crate) item_id: SourceFileItemId,
305 pub(crate) item_id: Option<SourceFileItemId>,
306} 305}
307 306
308/// Maps items' `SyntaxNode`s to `SourceFileItemId`s and back. 307/// Maps items' `SyntaxNode`s to `SourceFileItemId`s and back.
309#[derive(Debug, PartialEq, Eq)] 308#[derive(Debug, PartialEq, Eq)]
310pub struct SourceFileItems { 309pub struct SourceFileItems {
311 file_id: HirFileId, 310 file_id: HirFileId,
312 arena: Arena<SourceFileItemId, TreeArc<SyntaxNode>>, 311 arena: Arena<SourceFileItemId, SyntaxNodePtr>,
313} 312}
314 313
315impl SourceFileItems { 314impl SourceFileItems {
@@ -329,15 +328,15 @@ impl SourceFileItems {
329 // trait does not chage ids of top-level items, which helps caching. 328 // trait does not chage ids of top-level items, which helps caching.
330 bfs(source_file.syntax(), |it| { 329 bfs(source_file.syntax(), |it| {
331 if let Some(module_item) = ast::ModuleItem::cast(it) { 330 if let Some(module_item) = ast::ModuleItem::cast(it) {
332 self.alloc(module_item.syntax().to_owned()); 331 self.alloc(module_item.syntax());
333 } else if let Some(macro_call) = ast::MacroCall::cast(it) { 332 } else if let Some(macro_call) = ast::MacroCall::cast(it) {
334 self.alloc(macro_call.syntax().to_owned()); 333 self.alloc(macro_call.syntax());
335 } 334 }
336 }) 335 })
337 } 336 }
338 337
339 fn alloc(&mut self, item: TreeArc<SyntaxNode>) -> SourceFileItemId { 338 fn alloc(&mut self, item: &SyntaxNode) -> SourceFileItemId {
340 self.arena.alloc(item) 339 self.arena.alloc(SyntaxNodePtr::new(item))
341 } 340 }
342 pub(crate) fn id_of(&self, file_id: HirFileId, item: &SyntaxNode) -> SourceFileItemId { 341 pub(crate) fn id_of(&self, file_id: HirFileId, item: &SyntaxNode) -> SourceFileItemId {
343 assert_eq!( 342 assert_eq!(
@@ -348,17 +347,8 @@ impl SourceFileItems {
348 self.id_of_unchecked(item) 347 self.id_of_unchecked(item)
349 } 348 }
350 pub(crate) fn id_of_unchecked(&self, item: &SyntaxNode) -> SourceFileItemId { 349 pub(crate) fn id_of_unchecked(&self, item: &SyntaxNode) -> SourceFileItemId {
351 if let Some((id, _)) = self.arena.iter().find(|(_id, i)| *i == item) { 350 let ptr = SyntaxNodePtr::new(item);
352 return id; 351 if let Some((id, _)) = self.arena.iter().find(|(_id, i)| **i == ptr) {
353 }
354 // This should not happen. Let's try to give a sensible diagnostics.
355 if let Some((id, i)) = self.arena.iter().find(|(_id, i)| i.range() == item.range()) {
356 // FIXME(#288): whyyy are we getting here?
357 log::error!(
358 "unequal syntax nodes with the same range:\n{:?}\n{:?}",
359 item,
360 i
361 );
362 return id; 352 return id;
363 } 353 }
364 panic!( 354 panic!(
@@ -367,15 +357,11 @@ impl SourceFileItems {
367 self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(), 357 self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
368 ); 358 );
369 } 359 }
370 pub fn id_of_parse(&self) -> SourceFileItemId {
371 let (id, _syntax) = self.arena.iter().next().unwrap();
372 id
373 }
374} 360}
375 361
376impl std::ops::Index<SourceFileItemId> for SourceFileItems { 362impl std::ops::Index<SourceFileItemId> for SourceFileItems {
377 type Output = SyntaxNode; 363 type Output = SyntaxNodePtr;
378 fn index(&self, idx: SourceFileItemId) -> &SyntaxNode { 364 fn index(&self, idx: SourceFileItemId) -> &SyntaxNodePtr {
379 &self.arena[idx] 365 &self.arena[idx]
380 } 366 }
381} 367}
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs
index d5ad9decb..d1dc3fa4b 100644
--- a/crates/ra_hir/src/module_tree.rs
+++ b/crates/ra_hir/src/module_tree.rs
@@ -11,21 +11,28 @@ use ra_syntax::{
11use ra_arena::{Arena, RawId, impl_arena_id}; 11use ra_arena::{Arena, RawId, impl_arena_id};
12use test_utils::tested_by; 12use test_utils::tested_by;
13 13
14use crate::{Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource}; 14use crate::{
15 Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource,
16 ids::SourceFileItemId,
17};
15 18
16impl ModuleSource { 19impl ModuleSource {
17 pub(crate) fn from_source_item_id( 20 pub(crate) fn new(
18 db: &impl HirDatabase, 21 db: &impl HirDatabase,
19 source_item_id: SourceItemId, 22 file_id: HirFileId,
23 decl_id: Option<SourceFileItemId>,
20 ) -> ModuleSource { 24 ) -> ModuleSource {
21 let module_syntax = db.file_item(source_item_id); 25 match decl_id {
22 if let Some(source_file) = ast::SourceFile::cast(&module_syntax) { 26 Some(item_id) => {
23 ModuleSource::SourceFile(source_file.to_owned()) 27 let module = db.file_item(SourceItemId { file_id, item_id });
24 } else if let Some(module) = ast::Module::cast(&module_syntax) { 28 let module = ast::Module::cast(&*module).unwrap();
25 assert!(module.item_list().is_some(), "expected inline module"); 29 assert!(module.item_list().is_some(), "expected inline module");
26 ModuleSource::Module(module.to_owned()) 30 ModuleSource::Module(module.to_owned())
27 } else { 31 }
28 panic!("expected file or inline module") 32 None => {
33 let source_file = db.hir_parse(file_id);
34 ModuleSource::SourceFile(source_file)
35 }
29 } 36 }
30 } 37 }
31} 38}
@@ -34,18 +41,18 @@ impl ModuleSource {
34pub struct Submodule { 41pub struct Submodule {
35 name: Name, 42 name: Name,
36 is_declaration: bool, 43 is_declaration: bool,
37 source: SourceItemId, 44 decl_id: SourceFileItemId,
38} 45}
39 46
40impl Submodule { 47impl Submodule {
41 pub(crate) fn submodules_query( 48 pub(crate) fn submodules_query(
42 db: &impl HirDatabase, 49 db: &impl HirDatabase,
43 source: SourceItemId, 50 file_id: HirFileId,
51 decl_id: Option<SourceFileItemId>,
44 ) -> Arc<Vec<Submodule>> { 52 ) -> Arc<Vec<Submodule>> {
45 db.check_canceled(); 53 db.check_canceled();
46 let file_id = source.file_id;
47 let file_items = db.file_items(file_id); 54 let file_items = db.file_items(file_id);
48 let module_source = ModuleSource::from_source_item_id(db, source); 55 let module_source = ModuleSource::new(db, file_id, decl_id);
49 let submodules = match module_source { 56 let submodules = match module_source {
50 ModuleSource::SourceFile(source_file) => { 57 ModuleSource::SourceFile(source_file) => {
51 collect_submodules(file_id, &file_items, &*source_file) 58 collect_submodules(file_id, &file_items, &*source_file)
@@ -54,6 +61,7 @@ impl Submodule {
54 collect_submodules(file_id, &file_items, module.item_list().unwrap()) 61 collect_submodules(file_id, &file_items, module.item_list().unwrap())
55 } 62 }
56 }; 63 };
64
57 return Arc::new(submodules); 65 return Arc::new(submodules);
58 66
59 fn collect_submodules( 67 fn collect_submodules(
@@ -75,10 +83,7 @@ impl Submodule {
75 let sub = Submodule { 83 let sub = Submodule {
76 name, 84 name,
77 is_declaration: module.has_semi(), 85 is_declaration: module.has_semi(),
78 source: SourceItemId { 86 decl_id: file_items.id_of(file_id, module.syntax()),
79 file_id,
80 item_id: Some(file_items.id_of(file_id, module.syntax())),
81 },
82 }; 87 };
83 Some(sub) 88 Some(sub)
84 }) 89 })
@@ -110,7 +115,9 @@ pub struct ModuleTree {
110 115
111#[derive(Debug, PartialEq, Eq, Hash)] 116#[derive(Debug, PartialEq, Eq, Hash)]
112pub struct ModuleData { 117pub struct ModuleData {
113 source: SourceItemId, 118 file_id: HirFileId,
119 /// Points to `ast::Module`, `None` for the whole file.
120 decl_id: Option<SourceFileItemId>,
114 parent: Option<LinkId>, 121 parent: Option<LinkId>,
115 children: Vec<LinkId>, 122 children: Vec<LinkId>,
116} 123}
@@ -136,8 +143,15 @@ impl ModuleTree {
136 self.mods.iter().map(|(id, _)| id) 143 self.mods.iter().map(|(id, _)| id)
137 } 144 }
138 145
139 pub(crate) fn find_module_by_source(&self, source: SourceItemId) -> Option<ModuleId> { 146 pub(crate) fn find_module_by_source(
140 let (res, _) = self.mods.iter().find(|(_, m)| m.source == source)?; 147 &self,
148 file_id: HirFileId,
149 decl_id: Option<SourceFileItemId>,
150 ) -> Option<ModuleId> {
151 let (res, _) = self
152 .mods
153 .iter()
154 .find(|(_, m)| (m.file_id, m.decl_id) == (file_id, decl_id))?;
141 Some(res) 155 Some(res)
142 } 156 }
143 157
@@ -147,11 +161,7 @@ impl ModuleTree {
147 let source_root_id = db.file_source_root(file_id); 161 let source_root_id = db.file_source_root(file_id);
148 162
149 let source_root = db.source_root(source_root_id); 163 let source_root = db.source_root(source_root_id);
150 let source = SourceItemId { 164 self.init_subtree(db, &source_root, None, file_id.into(), None);
151 file_id: file_id.into(),
152 item_id: None,
153 };
154 self.init_subtree(db, &source_root, None, source);
155 } 165 }
156 166
157 fn init_subtree( 167 fn init_subtree(
@@ -159,16 +169,21 @@ impl ModuleTree {
159 db: &impl HirDatabase, 169 db: &impl HirDatabase,
160 source_root: &SourceRoot, 170 source_root: &SourceRoot,
161 parent: Option<LinkId>, 171 parent: Option<LinkId>,
162 source: SourceItemId, 172 file_id: HirFileId,
173 decl_id: Option<SourceFileItemId>,
163 ) -> ModuleId { 174 ) -> ModuleId {
164 let id = self.alloc_mod(ModuleData { 175 let id = self.alloc_mod(ModuleData {
165 source, 176 file_id,
177 decl_id,
166 parent, 178 parent,
167 children: Vec::new(), 179 children: Vec::new(),
168 }); 180 });
169 for sub in db.submodules(source).iter() { 181 for sub in db.submodules(file_id, decl_id).iter() {
170 let link = self.alloc_link(LinkData { 182 let link = self.alloc_link(LinkData {
171 source: sub.source, 183 source: SourceItemId {
184 file_id,
185 item_id: sub.decl_id,
186 },
172 name: sub.name.clone(), 187 name: sub.name.clone(),
173 owner: id, 188 owner: id,
174 points_to: Vec::new(), 189 points_to: Vec::new(),
@@ -176,24 +191,17 @@ impl ModuleTree {
176 }); 191 });
177 192
178 let (points_to, problem) = if sub.is_declaration { 193 let (points_to, problem) = if sub.is_declaration {
179 let (points_to, problem) = resolve_submodule(db, source.file_id, &sub.name); 194 let (points_to, problem) = resolve_submodule(db, file_id, &sub.name);
180 let points_to = points_to 195 let points_to = points_to
181 .into_iter() 196 .into_iter()
182 .map(|file_id| { 197 .map(|file_id| {
183 self.init_subtree( 198 self.init_subtree(db, source_root, Some(link), file_id.into(), None)
184 db,
185 source_root,
186 Some(link),
187 SourceItemId {
188 file_id: file_id.into(),
189 item_id: None,
190 },
191 )
192 }) 199 })
193 .collect::<Vec<_>>(); 200 .collect::<Vec<_>>();
194 (points_to, problem) 201 (points_to, problem)
195 } else { 202 } else {
196 let points_to = self.init_subtree(db, source_root, Some(link), sub.source); 203 let points_to =
204 self.init_subtree(db, source_root, Some(link), file_id, Some(sub.decl_id));
197 (vec![points_to], None) 205 (vec![points_to], None)
198 }; 206 };
199 207
@@ -216,8 +224,11 @@ impl ModuleTree {
216} 224}
217 225
218impl ModuleId { 226impl ModuleId {
219 pub(crate) fn source(self, tree: &ModuleTree) -> SourceItemId { 227 pub(crate) fn file_id(self, tree: &ModuleTree) -> HirFileId {
220 tree.mods[self].source 228 tree.mods[self].file_id
229 }
230 pub(crate) fn decl_id(self, tree: &ModuleTree) -> Option<SourceFileItemId> {
231 tree.mods[self].decl_id
221 } 232 }
222 pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> { 233 pub(crate) fn parent_link(self, tree: &ModuleTree) -> Option<LinkId> {
223 tree.mods[self].parent 234 tree.mods[self].parent
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 5193900e0..97ce6c946 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -215,7 +215,7 @@ where
215 // Populate extern crates prelude 215 // Populate extern crates prelude
216 { 216 {
217 let root_id = module_id.crate_root(&self.module_tree); 217 let root_id = module_id.crate_root(&self.module_tree);
218 let file_id = root_id.source(&self.module_tree).file_id; 218 let file_id = root_id.file_id(&self.module_tree);
219 let crate_graph = self.db.crate_graph(); 219 let crate_graph = self.db.crate_graph();
220 if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file()) 220 if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file())
221 { 221 {
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs
index 1d77548f3..8df11a5f4 100644
--- a/crates/ra_hir/src/nameres/lower.rs
+++ b/crates/ra_hir/src/nameres/lower.rs
@@ -121,10 +121,7 @@ impl LoweredModule {
121 let item_id = file_items.id_of_unchecked(macro_call.syntax()); 121 let item_id = file_items.id_of_unchecked(macro_call.syntax());
122 let loc = MacroCallLoc { 122 let loc = MacroCallLoc {
123 module, 123 module,
124 source_item_id: SourceItemId { 124 source_item_id: SourceItemId { file_id, item_id },
125 file_id,
126 item_id: Some(item_id),
127 },
128 }; 125 };
129 let id = loc.id(db); 126 let id = loc.id(db);
130 let file_id = HirFileId::from(id); 127 let file_id = HirFileId::from(id);
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs
index 61c93a964..bf9ac0dfb 100644
--- a/crates/ra_hir/src/query_definitions.rs
+++ b/crates/ra_hir/src/query_definitions.rs
@@ -4,9 +4,7 @@ use std::{
4}; 4};
5 5
6use rustc_hash::FxHashMap; 6use rustc_hash::FxHashMap;
7use ra_syntax::{ 7use ra_syntax::{SyntaxNode, TreeArc};
8 AstNode, SyntaxNode, TreeArc,
9};
10use ra_db::{CrateId}; 8use ra_db::{CrateId};
11 9
12use crate::{ 10use crate::{
@@ -32,10 +30,10 @@ pub(super) fn file_item(
32 db: &impl HirDatabase, 30 db: &impl HirDatabase,
33 source_item_id: SourceItemId, 31 source_item_id: SourceItemId,
34) -> TreeArc<SyntaxNode> { 32) -> TreeArc<SyntaxNode> {
35 match source_item_id.item_id { 33 let source_file = db.hir_parse(source_item_id.file_id);
36 Some(id) => db.file_items(source_item_id.file_id)[id].to_owned(), 34 db.file_items(source_item_id.file_id)[source_item_id.item_id]
37 None => db.hir_parse(source_item_id.file_id).syntax().to_owned(), 35 .to_node(&source_file)
38 } 36 .to_owned()
39} 37}
40 38
41pub(super) fn item_map(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ItemMap> { 39pub(super) fn item_map(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ItemMap> {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index c0b3f1cd4..f523f0647 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -13,18 +13,14 @@ use ra_syntax::{
13}; 13};
14 14
15use crate::{ 15use crate::{
16 HirDatabase, Function, SourceItemId, ModuleDef, 16 HirDatabase, Function, ModuleDef,
17 AsName, Module, 17 AsName, Module, HirFileId,
18 ids::LocationCtx, 18 ids::{LocationCtx, SourceFileItemId},
19}; 19};
20 20
21/// Locates the module by `FileId`. Picks topmost module in the file. 21/// Locates the module by `FileId`. Picks topmost module in the file.
22pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Option<Module> { 22pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Option<Module> {
23 let module_source = SourceItemId { 23 module_from_source(db, file_id.into(), None)
24 file_id: file_id.into(),
25 item_id: None,
26 };
27 module_from_source(db, module_source)
28} 24}
29 25
30/// Locates the child module by `mod child;` declaration. 26/// Locates the child module by `mod child;` declaration.
@@ -59,11 +55,7 @@ fn module_from_inline(
59 let file_id = file_id.into(); 55 let file_id = file_id.into();
60 let file_items = db.file_items(file_id); 56 let file_items = db.file_items(file_id);
61 let item_id = file_items.id_of(file_id, module.syntax()); 57 let item_id = file_items.id_of(file_id, module.syntax());
62 let source = SourceItemId { 58 module_from_source(db, file_id, Some(item_id))
63 file_id,
64 item_id: Some(item_id),
65 };
66 module_from_source(db, source)
67} 59}
68 60
69/// Locates the module by child syntax element within the module 61/// Locates the module by child syntax element within the module
@@ -83,13 +75,17 @@ pub fn module_from_child_node(
83 } 75 }
84} 76}
85 77
86fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Option<Module> { 78fn module_from_source(
87 let source_root_id = db.file_source_root(source.file_id.as_original_file()); 79 db: &impl HirDatabase,
80 file_id: HirFileId,
81 decl_id: Option<SourceFileItemId>,
82) -> Option<Module> {
83 let source_root_id = db.file_source_root(file_id.as_original_file());
88 db.source_root_crates(source_root_id) 84 db.source_root_crates(source_root_id)
89 .iter() 85 .iter()
90 .find_map(|&krate| { 86 .find_map(|&krate| {
91 let module_tree = db.module_tree(krate); 87 let module_tree = db.module_tree(krate);
92 let module_id = module_tree.find_module_by_source(source)?; 88 let module_id = module_tree.find_module_by_source(file_id, decl_id)?;
93 Some(Module { krate, module_id }) 89 Some(Module { krate, module_id })
94 }) 90 })
95} 91}
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs
index 7ee32fa7c..1604d9b5a 100644
--- a/crates/ra_syntax/src/grammar/expressions.rs
+++ b/crates/ra_syntax/src/grammar/expressions.rs
@@ -423,7 +423,7 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
423 match p.current() { 423 match p.current() {
424 L_CURLY if !r.forbid_structs => { 424 L_CURLY if !r.forbid_structs => {
425 named_field_list(p); 425 named_field_list(p);
426 (m.complete(p, STRUCT_LIT), BlockLike::Block) 426 (m.complete(p, STRUCT_LIT), BlockLike::NotBlock)
427 } 427 }
428 EXCL => { 428 EXCL => {
429 let block_like = items::macro_call_after_excl(p); 429 let block_like = items::macro_call_after_excl(p);
diff --git a/crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.rs b/crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.rs
new file mode 100644
index 000000000..7e4a28bf7
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.rs
@@ -0,0 +1,8 @@
1// https://github.com/rust-analyzer/rust-analyzer/issues/674
2
3struct Repr { raw: [u8; 1] }
4
5fn abc() {
6 Repr { raw: [0] }.raw[0] = 0;
7 Repr{raw:[0]}();
8}
diff --git a/crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.txt b/crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.txt
new file mode 100644
index 000000000..2279c7966
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0043_complex_assignment.txt
@@ -0,0 +1,109 @@
1SOURCE_FILE@[0; 160)
2 COMMENT@[0; 60)
3 WHITESPACE@[60; 62)
4 STRUCT_DEF@[62; 90)
5 STRUCT_KW@[62; 68)
6 WHITESPACE@[68; 69)
7 NAME@[69; 73)
8 IDENT@[69; 73) "Repr"
9 WHITESPACE@[73; 74)
10 NAMED_FIELD_DEF_LIST@[74; 90)
11 L_CURLY@[74; 75)
12 WHITESPACE@[75; 76)
13 NAMED_FIELD_DEF@[76; 88)
14 NAME@[76; 79)
15 IDENT@[76; 79) "raw"
16 COLON@[79; 80)
17 WHITESPACE@[80; 81)
18 ARRAY_TYPE@[81; 88)
19 L_BRACK@[81; 82)
20 PATH_TYPE@[82; 84)
21 PATH@[82; 84)
22 PATH_SEGMENT@[82; 84)
23 NAME_REF@[82; 84)
24 IDENT@[82; 84) "u8"
25 SEMI@[84; 85)
26 WHITESPACE@[85; 86)
27 LITERAL@[86; 87)
28 INT_NUMBER@[86; 87) "1"
29 R_BRACK@[87; 88)
30 WHITESPACE@[88; 89)
31 R_CURLY@[89; 90)
32 WHITESPACE@[90; 92)
33 FN_DEF@[92; 159)
34 FN_KW@[92; 94)
35 WHITESPACE@[94; 95)
36 NAME@[95; 98)
37 IDENT@[95; 98) "abc"
38 PARAM_LIST@[98; 100)
39 L_PAREN@[98; 99)
40 R_PAREN@[99; 100)
41 WHITESPACE@[100; 101)
42 BLOCK@[101; 159)
43 L_CURLY@[101; 102)
44 WHITESPACE@[102; 107)
45 EXPR_STMT@[107; 136)
46 BIN_EXPR@[107; 135)
47 INDEX_EXPR@[107; 131)
48 FIELD_EXPR@[107; 128)
49 STRUCT_LIT@[107; 124)
50 PATH@[107; 111)
51 PATH_SEGMENT@[107; 111)
52 NAME_REF@[107; 111)
53 IDENT@[107; 111) "Repr"
54 WHITESPACE@[111; 112)
55 NAMED_FIELD_LIST@[112; 124)
56 L_CURLY@[112; 113)
57 WHITESPACE@[113; 114)
58 NAMED_FIELD@[114; 122)
59 NAME_REF@[114; 117)
60 IDENT@[114; 117) "raw"
61 COLON@[117; 118)
62 WHITESPACE@[118; 119)
63 ARRAY_EXPR@[119; 122)
64 L_BRACK@[119; 120)
65 LITERAL@[120; 121)
66 INT_NUMBER@[120; 121) "0"
67 R_BRACK@[121; 122)
68 WHITESPACE@[122; 123)
69 R_CURLY@[123; 124)
70 DOT@[124; 125)
71 NAME_REF@[125; 128)
72 IDENT@[125; 128) "raw"
73 L_BRACK@[128; 129)
74 LITERAL@[129; 130)
75 INT_NUMBER@[129; 130) "0"
76 R_BRACK@[130; 131)
77 WHITESPACE@[131; 132)
78 EQ@[132; 133)
79 WHITESPACE@[133; 134)
80 LITERAL@[134; 135)
81 INT_NUMBER@[134; 135) "0"
82 SEMI@[135; 136)
83 WHITESPACE@[136; 141)
84 EXPR_STMT@[141; 157)
85 CALL_EXPR@[141; 156)
86 STRUCT_LIT@[141; 154)
87 PATH@[141; 145)
88 PATH_SEGMENT@[141; 145)
89 NAME_REF@[141; 145)
90 IDENT@[141; 145) "Repr"
91 NAMED_FIELD_LIST@[145; 154)
92 L_CURLY@[145; 146)
93 NAMED_FIELD@[146; 153)
94 NAME_REF@[146; 149)
95 IDENT@[146; 149) "raw"
96 COLON@[149; 150)
97 ARRAY_EXPR@[150; 153)
98 L_BRACK@[150; 151)
99 LITERAL@[151; 152)
100 INT_NUMBER@[151; 152) "0"
101 R_BRACK@[152; 153)
102 R_CURLY@[153; 154)
103 ARG_LIST@[154; 156)
104 L_PAREN@[154; 155)
105 R_PAREN@[155; 156)
106 SEMI@[156; 157)
107 WHITESPACE@[157; 158)
108 R_CURLY@[158; 159)
109 WHITESPACE@[159; 160)