aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_db/src/input.rs82
-rw-r--r--crates/ra_hir/src/code_model_impl/function/scope.rs31
-rw-r--r--crates/ra_hir/src/expr.rs12
-rw-r--r--crates/ra_hir/src/nameres/tests.rs12
-rw-r--r--crates/ra_lsp_server/src/server_world.rs25
-rw-r--r--crates/ra_syntax/src/ast.rs6
-rw-r--r--crates/ra_syntax/src/ast/generated.rs6
-rw-r--r--crates/ra_syntax/src/grammar.ron2
8 files changed, 124 insertions, 52 deletions
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index 023183e29..2b761ea0c 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -53,6 +53,9 @@ pub struct CrateGraph {
53 arena: FxHashMap<CrateId, CrateData>, 53 arena: FxHashMap<CrateId, CrateData>,
54} 54}
55 55
56#[derive(Debug)]
57pub struct CyclicDependencies;
58
56#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 59#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
57pub struct CrateId(pub u32); 60pub struct CrateId(pub u32);
58 61
@@ -94,12 +97,16 @@ impl CrateGraph {
94 assert!(prev.is_none()); 97 assert!(prev.is_none());
95 crate_id 98 crate_id
96 } 99 }
97 pub fn add_dep(&mut self, from: CrateId, name: SmolStr, to: CrateId) { 100 pub fn add_dep(
98 let mut visited = FxHashSet::default(); 101 &mut self,
99 if self.dfs_find(from, to, &mut visited) { 102 from: CrateId,
100 panic!("Cycle dependencies found.") 103 name: SmolStr,
104 to: CrateId,
105 ) -> Result<(), CyclicDependencies> {
106 if self.dfs_find(from, to, &mut FxHashSet::default()) {
107 return Err(CyclicDependencies);
101 } 108 }
102 self.arena.get_mut(&from).unwrap().add_dep(name, to) 109 Ok(self.arena.get_mut(&from).unwrap().add_dep(name, to))
103 } 110 }
104 pub fn is_empty(&self) -> bool { 111 pub fn is_empty(&self) -> bool {
105 self.arena.is_empty() 112 self.arena.is_empty()
@@ -139,35 +146,6 @@ impl CrateGraph {
139 } 146 }
140} 147}
141 148
142#[cfg(test)]
143mod tests {
144 use super::{CrateGraph, FxHashMap, FileId, SmolStr};
145
146 #[test]
147 #[should_panic]
148 fn it_should_painc_because_of_cycle_dependencies() {
149 let mut graph = CrateGraph::default();
150 let crate1 = graph.add_crate_root(FileId(1u32));
151 let crate2 = graph.add_crate_root(FileId(2u32));
152 let crate3 = graph.add_crate_root(FileId(3u32));
153 graph.add_dep(crate1, SmolStr::new("crate2"), crate2);
154 graph.add_dep(crate2, SmolStr::new("crate3"), crate3);
155 graph.add_dep(crate3, SmolStr::new("crate1"), crate1);
156 }
157
158 #[test]
159 fn it_works() {
160 let mut graph = CrateGraph {
161 arena: FxHashMap::default(),
162 };
163 let crate1 = graph.add_crate_root(FileId(1u32));
164 let crate2 = graph.add_crate_root(FileId(2u32));
165 let crate3 = graph.add_crate_root(FileId(3u32));
166 graph.add_dep(crate1, SmolStr::new("crate2"), crate2);
167 graph.add_dep(crate2, SmolStr::new("crate3"), crate3);
168 }
169}
170
171salsa::query_group! { 149salsa::query_group! {
172 pub trait FilesDatabase: salsa::Database { 150 pub trait FilesDatabase: salsa::Database {
173 /// Text of the file. 151 /// Text of the file.
@@ -209,3 +187,39 @@ salsa::query_group! {
209 } 187 }
210 } 188 }
211} 189}
190
191#[cfg(test)]
192mod tests {
193 use super::{CrateGraph, FileId, SmolStr};
194
195 #[test]
196 fn it_should_painc_because_of_cycle_dependencies() {
197 let mut graph = CrateGraph::default();
198 let crate1 = graph.add_crate_root(FileId(1u32));
199 let crate2 = graph.add_crate_root(FileId(2u32));
200 let crate3 = graph.add_crate_root(FileId(3u32));
201 assert!(graph
202 .add_dep(crate1, SmolStr::new("crate2"), crate2)
203 .is_ok());
204 assert!(graph
205 .add_dep(crate2, SmolStr::new("crate3"), crate3)
206 .is_ok());
207 assert!(graph
208 .add_dep(crate3, SmolStr::new("crate1"), crate1)
209 .is_err());
210 }
211
212 #[test]
213 fn it_works() {
214 let mut graph = CrateGraph::default();
215 let crate1 = graph.add_crate_root(FileId(1u32));
216 let crate2 = graph.add_crate_root(FileId(2u32));
217 let crate3 = graph.add_crate_root(FileId(3u32));
218 assert!(graph
219 .add_dep(crate1, SmolStr::new("crate2"), crate2)
220 .is_ok());
221 assert!(graph
222 .add_dep(crate2, SmolStr::new("crate3"), crate3)
223 .is_ok());
224 }
225}
diff --git a/crates/ra_hir/src/code_model_impl/function/scope.rs b/crates/ra_hir/src/code_model_impl/function/scope.rs
index 7d938c0dd..afca1e9f8 100644
--- a/crates/ra_hir/src/code_model_impl/function/scope.rs
+++ b/crates/ra_hir/src/code_model_impl/function/scope.rs
@@ -422,6 +422,9 @@ mod tests {
422 fn do_check_local_name(code: &str, expected_offset: u32) { 422 fn do_check_local_name(code: &str, expected_offset: u32) {
423 let (off, code) = extract_offset(code); 423 let (off, code) = extract_offset(code);
424 let file = SourceFile::parse(&code); 424 let file = SourceFile::parse(&code);
425 let expected_name = find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into())
426 .expect("failed to find a name at the target offset");
427
425 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 428 let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
426 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); 429 let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
427 430
@@ -431,11 +434,8 @@ mod tests {
431 scopes: Arc::new(scopes), 434 scopes: Arc::new(scopes),
432 syntax_mapping: Arc::new(body_hir), 435 syntax_mapping: Arc::new(body_hir),
433 }; 436 };
434
435 let local_name_entry = scopes.resolve_local_name(name_ref).unwrap(); 437 let local_name_entry = scopes.resolve_local_name(name_ref).unwrap();
436 let local_name = local_name_entry.ptr(); 438 let local_name = local_name_entry.ptr();
437 let expected_name =
438 find_node_at_offset::<ast::Name>(file.syntax(), expected_offset.into()).unwrap();
439 assert_eq!(local_name.range(), expected_name.syntax().range()); 439 assert_eq!(local_name.range(), expected_name.syntax().range());
440 } 440 }
441 441
@@ -470,11 +470,26 @@ mod tests {
470 fn test_resolve_local_name_shadow() { 470 fn test_resolve_local_name_shadow() {
471 do_check_local_name( 471 do_check_local_name(
472 r" 472 r"
473 fn foo(x: String) { 473 fn foo(x: String) {
474 let x : &str = &x; 474 let x : &str = &x;
475 x<|> 475 x<|>
476 }", 476 }
477 46, 477 ",
478 53,
479 );
480 }
481
482 #[test]
483 fn ref_patterns_contribute_bindings() {
484 do_check_local_name(
485 r"
486 fn foo() {
487 if let Some(&from) = bar() {
488 from<|>;
489 }
490 }
491 ",
492 53,
478 ); 493 );
479 } 494 }
480} 495}
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 67e123e4d..593fe1598 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -315,15 +315,20 @@ pub enum Pat {
315 path: Option<Path>, 315 path: Option<Path>,
316 args: Vec<PatId>, 316 args: Vec<PatId>,
317 }, 317 },
318 Ref {
319 pat: PatId,
320 mutability: Mutability,
321 },
318} 322}
319 323
320impl Pat { 324impl Pat {
321 pub fn walk_child_pats(&self, f: impl FnMut(PatId)) { 325 pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) {
322 match self { 326 match self {
323 Pat::Missing | Pat::Bind { .. } => {} 327 Pat::Missing | Pat::Bind { .. } => {}
324 Pat::TupleStruct { args, .. } => { 328 Pat::TupleStruct { args, .. } => {
325 args.iter().map(|pat| *pat).for_each(f); 329 args.iter().map(|pat| *pat).for_each(f);
326 } 330 }
331 Pat::Ref { pat, .. } => f(*pat),
327 } 332 }
328 } 333 }
329} 334}
@@ -684,6 +689,11 @@ impl ExprCollector {
684 let args = p.args().map(|p| self.collect_pat(p)).collect(); 689 let args = p.args().map(|p| self.collect_pat(p)).collect();
685 self.alloc_pat(Pat::TupleStruct { path, args }, syntax_ptr) 690 self.alloc_pat(Pat::TupleStruct { path, args }, syntax_ptr)
686 } 691 }
692 ast::PatKind::RefPat(p) => {
693 let pat = self.collect_pat_opt(p.pat());
694 let mutability = Mutability::from_mutable(p.is_mut());
695 self.alloc_pat(Pat::Ref { pat, mutability }, syntax_ptr)
696 }
687 _ => { 697 _ => {
688 // TODO 698 // TODO
689 self.alloc_pat(Pat::Missing, syntax_ptr) 699 self.alloc_pat(Pat::Missing, syntax_ptr)
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index ba9fcb3d1..647fd92aa 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -235,7 +235,9 @@ fn item_map_across_crates() {
235 let mut crate_graph = CrateGraph::default(); 235 let mut crate_graph = CrateGraph::default();
236 let main_crate = crate_graph.add_crate_root(main_id); 236 let main_crate = crate_graph.add_crate_root(main_id);
237 let lib_crate = crate_graph.add_crate_root(lib_id); 237 let lib_crate = crate_graph.add_crate_root(lib_id);
238 crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate); 238 crate_graph
239 .add_dep(main_crate, "test_crate".into(), lib_crate)
240 .unwrap();
239 241
240 db.set_crate_graph(crate_graph); 242 db.set_crate_graph(crate_graph);
241 243
@@ -288,7 +290,9 @@ fn import_across_source_roots() {
288 let mut crate_graph = CrateGraph::default(); 290 let mut crate_graph = CrateGraph::default();
289 let main_crate = crate_graph.add_crate_root(main_id); 291 let main_crate = crate_graph.add_crate_root(main_id);
290 let lib_crate = crate_graph.add_crate_root(lib_id); 292 let lib_crate = crate_graph.add_crate_root(lib_id);
291 crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate); 293 crate_graph
294 .add_dep(main_crate, "test_crate".into(), lib_crate)
295 .unwrap();
292 296
293 db.set_crate_graph(crate_graph); 297 db.set_crate_graph(crate_graph);
294 298
@@ -330,7 +334,9 @@ fn reexport_across_crates() {
330 let mut crate_graph = CrateGraph::default(); 334 let mut crate_graph = CrateGraph::default();
331 let main_crate = crate_graph.add_crate_root(main_id); 335 let main_crate = crate_graph.add_crate_root(main_id);
332 let lib_crate = crate_graph.add_crate_root(lib_id); 336 let lib_crate = crate_graph.add_crate_root(lib_id);
333 crate_graph.add_dep(main_crate, "test_crate".into(), lib_crate); 337 crate_graph
338 .add_dep(main_crate, "test_crate".into(), lib_crate)
339 .unwrap();
334 340
335 db.set_crate_graph(crate_graph); 341 db.set_crate_graph(crate_graph);
336 342
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs
index 4f3c231d3..d5dbf999f 100644
--- a/crates/ra_lsp_server/src/server_world.rs
+++ b/crates/ra_lsp_server/src/server_world.rs
@@ -73,7 +73,9 @@ impl ServerWorldState {
73 if let (Some(&from), Some(&to)) = 73 if let (Some(&from), Some(&to)) =
74 (sysroot_crates.get(&from), sysroot_crates.get(&to)) 74 (sysroot_crates.get(&from), sysroot_crates.get(&to))
75 { 75 {
76 crate_graph.add_dep(from, name.clone(), to); 76 if let Err(_) = crate_graph.add_dep(from, name.clone(), to) {
77 log::error!("cyclic dependency between sysroot crates")
78 }
77 } 79 }
78 } 80 }
79 } 81 }
@@ -108,11 +110,20 @@ impl ServerWorldState {
108 for &from in pkg_crates.get(&pkg).into_iter().flatten() { 110 for &from in pkg_crates.get(&pkg).into_iter().flatten() {
109 if let Some(to) = lib_tgt { 111 if let Some(to) = lib_tgt {
110 if to != from { 112 if to != from {
111 crate_graph.add_dep(from, pkg.name(&ws.cargo).into(), to); 113 if let Err(_) =
114 crate_graph.add_dep(from, pkg.name(&ws.cargo).into(), to)
115 {
116 log::error!(
117 "cyclic dependency between targets of {}",
118 pkg.name(&ws.cargo)
119 )
120 }
112 } 121 }
113 } 122 }
114 if let Some(std) = libstd { 123 if let Some(std) = libstd {
115 crate_graph.add_dep(from, "std".into(), std); 124 if let Err(_) = crate_graph.add_dep(from, "std".into(), std) {
125 log::error!("cyclic dependency on std for {}", pkg.name(&ws.cargo))
126 }
116 } 127 }
117 } 128 }
118 } 129 }
@@ -123,7 +134,13 @@ impl ServerWorldState {
123 for dep in pkg.dependencies(&ws.cargo) { 134 for dep in pkg.dependencies(&ws.cargo) {
124 if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { 135 if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
125 for &from in pkg_crates.get(&pkg).into_iter().flatten() { 136 for &from in pkg_crates.get(&pkg).into_iter().flatten() {
126 crate_graph.add_dep(from, dep.name.clone(), to); 137 if let Err(_) = crate_graph.add_dep(from, dep.name.clone(), to) {
138 log::error!(
139 "cyclic dependency {} -> {}",
140 pkg.name(&ws.cargo),
141 dep.pkg.name(&ws.cargo)
142 )
143 }
127 } 144 }
128 } 145 }
129 } 146 }
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 123a7a6b9..8bf439b60 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -348,6 +348,12 @@ impl UseTreeList {
348 } 348 }
349} 349}
350 350
351impl RefPat {
352 pub fn is_mut(&self) -> bool {
353 self.syntax().children().any(|n| n.kind() == MUT_KW)
354 }
355}
356
351fn child_opt<P: AstNode, C: AstNode>(parent: &P) -> Option<&C> { 357fn child_opt<P: AstNode, C: AstNode>(parent: &P) -> Option<&C> {
352 children(parent).next() 358 children(parent).next()
353} 359}
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 1f6055115..f745cb1cb 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -2456,7 +2456,11 @@ impl AstNode for RefPat {
2456} 2456}
2457 2457
2458 2458
2459impl RefPat {} 2459impl RefPat {
2460 pub fn pat(&self) -> Option<&Pat> {
2461 super::child_opt(self)
2462 }
2463}
2460 2464
2461// ReferenceType 2465// ReferenceType
2462#[derive(Debug, PartialEq, Eq, Hash)] 2466#[derive(Debug, PartialEq, Eq, Hash)]
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index bddd96a5c..bac62fa04 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -462,7 +462,7 @@ Grammar(
462 ], 462 ],
463 ), 463 ),
464 464
465 "RefPat": (), 465 "RefPat": ( options: [ "Pat" ]),
466 "BindPat": ( traits: ["NameOwner"] ), 466 "BindPat": ( traits: ["NameOwner"] ),
467 "PlaceholderPat": (), 467 "PlaceholderPat": (),
468 "PathPat": (), 468 "PathPat": (),