diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/code_model_impl/function/scope.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir/src/expr.rs | 67 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 15 |
4 files changed, 85 insertions, 13 deletions
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 afca1e9f8..c551e445a 100644 --- a/crates/ra_hir/src/code_model_impl/function/scope.rs +++ b/crates/ra_hir/src/code_model_impl/function/scope.rs | |||
@@ -47,9 +47,11 @@ impl FnScopes { | |||
47 | compute_expr_scopes(body.body_expr(), &body, &mut scopes, root); | 47 | compute_expr_scopes(body.body_expr(), &body, &mut scopes, root); |
48 | scopes | 48 | scopes |
49 | } | 49 | } |
50 | |||
50 | pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { | 51 | pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { |
51 | &self.scopes[scope].entries | 52 | &self.scopes[scope].entries |
52 | } | 53 | } |
54 | |||
53 | pub fn scope_chain_for<'a>(&'a self, expr: ExprId) -> impl Iterator<Item = ScopeId> + 'a { | 55 | pub fn scope_chain_for<'a>(&'a self, expr: ExprId) -> impl Iterator<Item = ScopeId> + 'a { |
54 | generate(self.scope_for(expr), move |&scope| { | 56 | generate(self.scope_for(expr), move |&scope| { |
55 | self.scopes[scope].parent | 57 | self.scopes[scope].parent |
@@ -76,12 +78,14 @@ impl FnScopes { | |||
76 | entries: vec![], | 78 | entries: vec![], |
77 | }) | 79 | }) |
78 | } | 80 | } |
81 | |||
79 | fn new_scope(&mut self, parent: ScopeId) -> ScopeId { | 82 | fn new_scope(&mut self, parent: ScopeId) -> ScopeId { |
80 | self.scopes.alloc(ScopeData { | 83 | self.scopes.alloc(ScopeData { |
81 | parent: Some(parent), | 84 | parent: Some(parent), |
82 | entries: vec![], | 85 | entries: vec![], |
83 | }) | 86 | }) |
84 | } | 87 | } |
88 | |||
85 | fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { | 89 | fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { |
86 | match &body[pat] { | 90 | match &body[pat] { |
87 | Pat::Bind { name } => self.scopes[scope].entries.push(ScopeEntry { | 91 | Pat::Bind { name } => self.scopes[scope].entries.push(ScopeEntry { |
@@ -91,15 +95,18 @@ impl FnScopes { | |||
91 | p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)), | 95 | p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)), |
92 | } | 96 | } |
93 | } | 97 | } |
98 | |||
94 | fn add_params_bindings(&mut self, scope: ScopeId, params: &[PatId]) { | 99 | fn add_params_bindings(&mut self, scope: ScopeId, params: &[PatId]) { |
95 | let body = Arc::clone(&self.body); | 100 | let body = Arc::clone(&self.body); |
96 | params | 101 | params |
97 | .into_iter() | 102 | .into_iter() |
98 | .for_each(|pat| self.add_bindings(&body, scope, *pat)); | 103 | .for_each(|pat| self.add_bindings(&body, scope, *pat)); |
99 | } | 104 | } |
105 | |||
100 | fn set_scope(&mut self, node: ExprId, scope: ScopeId) { | 106 | fn set_scope(&mut self, node: ExprId, scope: ScopeId) { |
101 | self.scope_for.insert(node, scope); | 107 | self.scope_for.insert(node, scope); |
102 | } | 108 | } |
109 | |||
103 | fn scope_for(&self, expr: ExprId) -> Option<ScopeId> { | 110 | fn scope_for(&self, expr: ExprId) -> Option<ScopeId> { |
104 | self.scope_for.get(&expr).map(|&scope| scope) | 111 | self.scope_for.get(&expr).map(|&scope| scope) |
105 | } | 112 | } |
@@ -121,6 +128,7 @@ impl ScopeEntryWithSyntax { | |||
121 | pub fn name(&self) -> &Name { | 128 | pub fn name(&self) -> &Name { |
122 | &self.name | 129 | &self.name |
123 | } | 130 | } |
131 | |||
124 | pub fn ptr(&self) -> LocalSyntaxPtr { | 132 | pub fn ptr(&self) -> LocalSyntaxPtr { |
125 | self.ptr | 133 | self.ptr |
126 | } | 134 | } |
@@ -132,6 +140,7 @@ impl ScopesWithSyntaxMapping { | |||
132 | self.scopes.scopes[scope].parent | 140 | self.scopes.scopes[scope].parent |
133 | }) | 141 | }) |
134 | } | 142 | } |
143 | |||
135 | pub fn scope_chain_for_offset<'a>( | 144 | pub fn scope_chain_for_offset<'a>( |
136 | &'a self, | 145 | &'a self, |
137 | offset: TextUnit, | 146 | offset: TextUnit, |
@@ -152,6 +161,7 @@ impl ScopesWithSyntaxMapping { | |||
152 | 161 | ||
153 | generate(scope, move |&scope| self.scopes.scopes[scope].parent) | 162 | generate(scope, move |&scope| self.scopes.scopes[scope].parent) |
154 | } | 163 | } |
164 | |||
155 | // XXX: during completion, cursor might be outside of any particular | 165 | // XXX: during completion, cursor might be outside of any particular |
156 | // expression. Try to figure out the correct scope... | 166 | // expression. Try to figure out the correct scope... |
157 | fn adjust(&self, ptr: LocalSyntaxPtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId { | 167 | fn adjust(&self, ptr: LocalSyntaxPtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId { |
@@ -225,6 +235,7 @@ impl ScopeEntry { | |||
225 | pub fn name(&self) -> &Name { | 235 | pub fn name(&self) -> &Name { |
226 | &self.name | 236 | &self.name |
227 | } | 237 | } |
238 | |||
228 | pub fn pat(&self) -> PatId { | 239 | pub fn pat(&self) -> PatId { |
229 | self.pat | 240 | self.pat |
230 | } | 241 | } |
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 6e98ebc69..8f7e75309 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -329,9 +329,25 @@ impl Expr { | |||
329 | pub struct PatId(RawId); | 329 | pub struct PatId(RawId); |
330 | impl_arena_id!(PatId); | 330 | impl_arena_id!(PatId); |
331 | 331 | ||
332 | /// Close relative to rustc's hir::PatKind | ||
332 | #[derive(Debug, Clone, Eq, PartialEq)] | 333 | #[derive(Debug, Clone, Eq, PartialEq)] |
333 | pub enum Pat { | 334 | pub enum Pat { |
334 | Missing, | 335 | Missing, // do we need this? |
336 | Wild, | ||
337 | Tuple(Vec<PatId>), | ||
338 | Struct, // TODO | ||
339 | Range { | ||
340 | start: ExprId, | ||
341 | end: ExprId, | ||
342 | }, | ||
343 | Box(PatId), | ||
344 | Slice { | ||
345 | prefix: Vec<PatId>, | ||
346 | rest: Option<PatId>, | ||
347 | suffix: Vec<PatId>, | ||
348 | }, | ||
349 | Path(Path), | ||
350 | Lit(ExprId), | ||
335 | Bind { | 351 | Bind { |
336 | name: Name, | 352 | name: Name, |
337 | }, | 353 | }, |
@@ -348,11 +364,25 @@ pub enum Pat { | |||
348 | impl Pat { | 364 | impl Pat { |
349 | pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) { | 365 | pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) { |
350 | match self { | 366 | match self { |
351 | Pat::Missing | Pat::Bind { .. } => {} | 367 | Pat::Range { .. } |
352 | Pat::TupleStruct { args, .. } => { | 368 | | Pat::Lit(..) |
369 | | Pat::Path(..) | ||
370 | | Pat::Wild | ||
371 | | Pat::Missing | ||
372 | | Pat::Bind { .. } => {} | ||
373 | Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { | ||
353 | args.iter().map(|pat| *pat).for_each(f); | 374 | args.iter().map(|pat| *pat).for_each(f); |
354 | } | 375 | } |
355 | Pat::Ref { pat, .. } => f(*pat), | 376 | Pat::Ref { pat, .. } | Pat::Box(pat) => f(*pat), |
377 | Pat::Slice { | ||
378 | prefix, | ||
379 | rest, | ||
380 | suffix, | ||
381 | } => { | ||
382 | let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter()); | ||
383 | total_iter.map(|pat| *pat).for_each(f); | ||
384 | } | ||
385 | Pat::Struct { .. } => {} // TODO | ||
356 | } | 386 | } |
357 | } | 387 | } |
358 | } | 388 | } |
@@ -745,30 +775,41 @@ impl ExprCollector { | |||
745 | } | 775 | } |
746 | 776 | ||
747 | fn collect_pat(&mut self, pat: &ast::Pat) -> PatId { | 777 | fn collect_pat(&mut self, pat: &ast::Pat) -> PatId { |
748 | let syntax_ptr = LocalSyntaxPtr::new(pat.syntax()); | 778 | let pattern = match pat.kind() { |
749 | match pat.kind() { | ||
750 | ast::PatKind::BindPat(bp) => { | 779 | ast::PatKind::BindPat(bp) => { |
751 | let name = bp | 780 | let name = bp |
752 | .name() | 781 | .name() |
753 | .map(|nr| nr.as_name()) | 782 | .map(|nr| nr.as_name()) |
754 | .unwrap_or_else(Name::missing); | 783 | .unwrap_or_else(Name::missing); |
755 | self.alloc_pat(Pat::Bind { name }, syntax_ptr) | 784 | Pat::Bind { name } |
756 | } | 785 | } |
757 | ast::PatKind::TupleStructPat(p) => { | 786 | ast::PatKind::TupleStructPat(p) => { |
758 | let path = p.path().and_then(Path::from_ast); | 787 | let path = p.path().and_then(Path::from_ast); |
759 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | 788 | let args = p.args().map(|p| self.collect_pat(p)).collect(); |
760 | self.alloc_pat(Pat::TupleStruct { path, args }, syntax_ptr) | 789 | Pat::TupleStruct { path, args } |
761 | } | 790 | } |
762 | ast::PatKind::RefPat(p) => { | 791 | ast::PatKind::RefPat(p) => { |
763 | let pat = self.collect_pat_opt(p.pat()); | 792 | let pat = self.collect_pat_opt(p.pat()); |
764 | let mutability = Mutability::from_mutable(p.is_mut()); | 793 | let mutability = Mutability::from_mutable(p.is_mut()); |
765 | self.alloc_pat(Pat::Ref { pat, mutability }, syntax_ptr) | 794 | Pat::Ref { pat, mutability } |
766 | } | 795 | } |
767 | _ => { | 796 | ast::PatKind::PathPat(p) => { |
768 | // TODO | 797 | let path = p.path().and_then(Path::from_ast); |
769 | self.alloc_pat(Pat::Missing, syntax_ptr) | 798 | path.map(|path| Pat::Path(path)).unwrap_or(Pat::Missing) |
770 | } | 799 | } |
771 | } | 800 | ast::PatKind::TuplePat(p) => { |
801 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | ||
802 | Pat::Tuple(args) | ||
803 | } | ||
804 | ast::PatKind::PlaceholderPat(_) => Pat::Wild, | ||
805 | // TODO: implement | ||
806 | ast::PatKind::FieldPatList(_) | ||
807 | | ast::PatKind::SlicePat(_) | ||
808 | | ast::PatKind::StructPat(_) | ||
809 | | ast::PatKind::RangePat(_) => Pat::Missing, | ||
810 | }; | ||
811 | let syntax_ptr = LocalSyntaxPtr::new(pat.syntax()); | ||
812 | self.alloc_pat(pattern, syntax_ptr) | ||
772 | } | 813 | } |
773 | 814 | ||
774 | fn collect_pat_opt(&mut self, pat: Option<&ast::Pat>) -> PatId { | 815 | fn collect_pat_opt(&mut self, pat: Option<&ast::Pat>) -> PatId { |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index c7c063601..854d3e3d9 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -1168,6 +1168,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1168 | decl_ty | 1168 | decl_ty |
1169 | }; | 1169 | }; |
1170 | 1170 | ||
1171 | // TODO: walk the pattern here? | ||
1172 | |||
1171 | self.write_pat_ty(*pat, ty); | 1173 | self.write_pat_ty(*pat, ty); |
1172 | } | 1174 | } |
1173 | Statement::Expr(expr) => { | 1175 | Statement::Expr(expr) => { |
@@ -1188,6 +1190,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1188 | for (type_ref, pat) in signature.params().iter().zip(body.params()) { | 1190 | for (type_ref, pat) in signature.params().iter().zip(body.params()) { |
1189 | let ty = self.make_ty(type_ref); | 1191 | let ty = self.make_ty(type_ref); |
1190 | let ty = self.insert_type_vars(ty); | 1192 | let ty = self.insert_type_vars(ty); |
1193 | |||
1194 | // TODO: walk pattern? | ||
1195 | |||
1191 | self.write_pat_ty(*pat, ty); | 1196 | self.write_pat_ty(*pat, ty); |
1192 | } | 1197 | } |
1193 | self.return_ty = { | 1198 | self.return_ty = { |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index a430cbe88..fc1e5b09c 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -358,6 +358,21 @@ fn test(x: &str, y: isize) { | |||
358 | ); | 358 | ); |
359 | } | 359 | } |
360 | 360 | ||
361 | #[test] | ||
362 | fn infer_pattern() { | ||
363 | check_inference( | ||
364 | r#" | ||
365 | fn test(x: &i32) { | ||
366 | let y = x; | ||
367 | let &z = x; | ||
368 | let a = z; | ||
369 | let (c, d) = (1, "hello"); | ||
370 | } | ||
371 | "#, | ||
372 | "pattern.txt", | ||
373 | ); | ||
374 | } | ||
375 | |||
361 | fn infer(content: &str) -> String { | 376 | fn infer(content: &str) -> String { |
362 | let (db, _, file_id) = MockDatabase::with_single_file(content); | 377 | let (db, _, file_id) = MockDatabase::with_single_file(content); |
363 | let source_file = db.source_file(file_id); | 378 | let source_file = db.source_file(file_id); |