aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/code_model_impl/function/scope.rs15
-rw-r--r--crates/ra_hir/src/expr.rs18
-rw-r--r--crates/ra_hir/src/ty.rs29
-rw-r--r--crates/ra_hir/src/ty/tests.rs6
-rw-r--r--crates/ra_hir/src/ty/tests/data/adt_pattern.txt6
-rw-r--r--crates/ra_hir/src/ty/tests/data/pattern.txt10
6 files changed, 54 insertions, 30 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 7e8eb7704..220c71f74 100644
--- a/crates/ra_hir/src/code_model_impl/function/scope.rs
+++ b/crates/ra_hir/src/code_model_impl/function/scope.rs
@@ -88,10 +88,17 @@ impl FnScopes {
88 88
89 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { 89 fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) {
90 match &body[pat] { 90 match &body[pat] {
91 Pat::Bind { name, .. } => self.scopes[scope].entries.push(ScopeEntry { 91 Pat::Bind { name, .. } => {
92 name: name.clone(), 92 // bind can have a subpattern, but it's actually not allowed
93 pat, 93 // to bind to things in there
94 }), 94 let entry = ScopeEntry {
95 name: name.clone(),
96 pat,
97 };
98 self.scopes[scope].entries.push(entry)
99 }
100 // FIXME: isn't every call to add_binding starting an entirely new
101 // tree walk!?
95 p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)), 102 p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)),
96 } 103 }
97 } 104 }
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 4d372c97b..c05bbc442 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -398,7 +398,7 @@ pub enum Pat {
398 Bind { 398 Bind {
399 mode: BindingAnnotation, 399 mode: BindingAnnotation,
400 name: Name, 400 name: Name,
401 sub_pat: Option<PatId>, 401 subpat: Option<PatId>,
402 }, 402 },
403 TupleStruct { 403 TupleStruct {
404 path: Option<Path>, 404 path: Option<Path>,
@@ -413,12 +413,10 @@ pub enum Pat {
413impl Pat { 413impl Pat {
414 pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) { 414 pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) {
415 match self { 415 match self {
416 Pat::Range { .. } 416 Pat::Range { .. } | Pat::Lit(..) | Pat::Path(..) | Pat::Wild | Pat::Missing => {}
417 | Pat::Lit(..) 417 Pat::Bind { subpat, .. } => {
418 | Pat::Path(..) 418 subpat.iter().map(|pat| *pat).for_each(f);
419 | Pat::Wild 419 }
420 | Pat::Missing
421 | Pat::Bind { .. } => {}
422 Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { 420 Pat::Tuple(args) | Pat::TupleStruct { args, .. } => {
423 args.iter().map(|pat| *pat).for_each(f); 421 args.iter().map(|pat| *pat).for_each(f);
424 } 422 }
@@ -833,11 +831,11 @@ impl ExprCollector {
833 .map(|nr| nr.as_name()) 831 .map(|nr| nr.as_name())
834 .unwrap_or_else(Name::missing); 832 .unwrap_or_else(Name::missing);
835 let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref()); 833 let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref());
836 let sub_pat = bp.pat().map(|subpat| self.collect_pat(subpat)); 834 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat));
837 Pat::Bind { 835 Pat::Bind {
838 name, 836 name,
839 mode: annotation, 837 mode: annotation,
840 sub_pat, 838 subpat,
841 } 839 }
842 } 840 }
843 ast::PatKind::TupleStructPat(p) => { 841 ast::PatKind::TupleStructPat(p) => {
@@ -928,7 +926,7 @@ pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping {
928 Pat::Bind { 926 Pat::Bind {
929 name: Name::self_param(), 927 name: Name::self_param(),
930 mode: BindingAnnotation::Unannotated, 928 mode: BindingAnnotation::Unannotated,
931 sub_pat: None, 929 subpat: None,
932 }, 930 },
933 self_param, 931 self_param,
934 ); 932 );
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index bc842dd26..57fd1ed2a 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -904,39 +904,39 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
904 } 904 }
905 } 905 }
906 906
907 fn infer_tuple_struct(&mut self, path: Option<&Path>, sub_pats: &[PatId]) -> Ty { 907 fn infer_tuple_struct(&mut self, path: Option<&Path>, subpats: &[PatId]) -> Ty {
908 let (ty, fields) = if let Some(x) = self.resolve_fields(path) { 908 let (ty, fields) = if let Some(x) = self.resolve_fields(path) {
909 x 909 x
910 } else { 910 } else {
911 return Ty::Unknown; 911 return Ty::Unknown;
912 }; 912 };
913 913
914 if fields.len() != sub_pats.len() { 914 if fields.len() != subpats.len() {
915 return Ty::Unknown; 915 return Ty::Unknown;
916 } 916 }
917 917
918 for (&sub_pat, field) in sub_pats.iter().zip(fields.iter()) { 918 for (&subpat, field) in subpats.iter().zip(fields.iter()) {
919 let sub_ty = self.make_ty(&field.type_ref); 919 let sub_ty = self.make_ty(&field.type_ref);
920 self.infer_pat(sub_pat, &Expectation::has_type(sub_ty)); 920 self.infer_pat(subpat, &Expectation::has_type(sub_ty));
921 } 921 }
922 922
923 ty 923 ty
924 } 924 }
925 925
926 fn infer_struct(&mut self, path: Option<&Path>, sub_pats: &[FieldPat]) -> Ty { 926 fn infer_struct(&mut self, path: Option<&Path>, subpats: &[FieldPat]) -> Ty {
927 let (ty, fields) = if let Some(x) = self.resolve_fields(path) { 927 let (ty, fields) = if let Some(x) = self.resolve_fields(path) {
928 x 928 x
929 } else { 929 } else {
930 return Ty::Unknown; 930 return Ty::Unknown;
931 }; 931 };
932 932
933 for sub_pat in sub_pats { 933 for subpat in subpats {
934 let matching_field = fields.iter().find(|field| field.name == sub_pat.name); 934 let matching_field = fields.iter().find(|field| field.name == subpat.name);
935 935
936 if let Some(field) = matching_field { 936 if let Some(field) = matching_field {
937 let typeref = &field.type_ref; 937 let typeref = &field.type_ref;
938 let sub_ty = self.make_ty(typeref); 938 let sub_ty = self.make_ty(typeref);
939 self.infer_pat(sub_pat.pat, &Expectation::has_type(sub_ty)); 939 self.infer_pat(subpat.pat, &Expectation::has_type(sub_ty));
940 } 940 }
941 } 941 }
942 942
@@ -979,8 +979,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
979 } 979 }
980 Pat::TupleStruct { 980 Pat::TupleStruct {
981 path: ref p, 981 path: ref p,
982 args: ref sub_pats, 982 args: ref subpats,
983 } => self.infer_tuple_struct(p.as_ref(), sub_pats), 983 } => self.infer_tuple_struct(p.as_ref(), subpats),
984 Pat::Struct { 984 Pat::Struct {
985 path: ref p, 985 path: ref p,
986 args: ref fields, 986 args: ref fields,
@@ -995,12 +995,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
995 Pat::Bind { 995 Pat::Bind {
996 mode, 996 mode,
997 name: _name, 997 name: _name,
998 sub_pat, 998 subpat,
999 } => { 999 } => {
1000 let subty = if let Some(subpat) = sub_pat { 1000 let subty = if let Some(subpat) = subpat {
1001 self.infer_pat(*subpat, expected) 1001 self.infer_pat(*subpat, expected)
1002 } else { 1002 } else {
1003 Ty::Unknown 1003 let ty = self.new_type_var();
1004 self.unify(&ty, &expected.ty);
1005 let ty = self.resolve_ty_as_possible(ty);
1006 ty
1004 }; 1007 };
1005 1008
1006 match mode { 1009 match mode {
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index e817a8da9..fc4054159 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -359,7 +359,7 @@ fn test(x: &str, y: isize) {
359} 359}
360 360
361#[test] 361#[test]
362fn infer_simple_pattern() { 362fn infer_pattern() {
363 check_inference( 363 check_inference(
364 r#" 364 r#"
365fn test(x: &i32) { 365fn test(x: &i32) {
@@ -381,6 +381,7 @@ fn test(x: &i32) {
381 let ref ref_to_x = x; 381 let ref ref_to_x = x;
382 let mut mut_x = x; 382 let mut mut_x = x;
383 let ref mut mut_ref_to_x = x; 383 let ref mut mut_ref_to_x = x;
384 let k = mut_ref_to_x;
384} 385}
385"#, 386"#,
386 "pattern.txt", 387 "pattern.txt",
@@ -408,6 +409,9 @@ fn test() {
408 E::A { x } => x, 409 E::A { x } => x,
409 E::B => 1, 410 E::B => 1,
410 }; 411 };
412
413 let ref d @ E::A { .. } = e;
414 d;
411} 415}
412"#, 416"#,
413 "adt_pattern.txt", 417 "adt_pattern.txt",
diff --git a/crates/ra_hir/src/ty/tests/data/adt_pattern.txt b/crates/ra_hir/src/ty/tests/data/adt_pattern.txt
index 3b9b9a078..2daf9647b 100644
--- a/crates/ra_hir/src/ty/tests/data/adt_pattern.txt
+++ b/crates/ra_hir/src/ty/tests/data/adt_pattern.txt
@@ -1,4 +1,4 @@
1[68; 221) '{ ... }; }': () 1[68; 262) '{ ... d; }': ()
2[78; 79) 'e': E 2[78; 79) 'e': E
3[82; 95) 'E::A { x: 3 }': E 3[82; 95) 'E::A { x: 3 }': E
4[92; 93) '3': usize 4[92; 93) '3': usize
@@ -16,3 +16,7 @@
16[191; 192) 'x': usize 16[191; 192) 'x': usize
17[202; 206) 'E::B': E 17[202; 206) 'E::B': E
18[210; 211) '1': usize 18[210; 211) '1': usize
19[229; 248) 'ref d ...{ .. }': &E
20[237; 248) 'E::A { .. }': E
21[251; 252) 'e': E
22[258; 259) 'd': &E
diff --git a/crates/ra_hir/src/ty/tests/data/pattern.txt b/crates/ra_hir/src/ty/tests/data/pattern.txt
index 8b7c967c4..966289aaf 100644
--- a/crates/ra_hir/src/ty/tests/data/pattern.txt
+++ b/crates/ra_hir/src/ty/tests/data/pattern.txt
@@ -1,5 +1,5 @@
1[9; 10) 'x': &i32 1[9; 10) 'x': &i32
2[18; 259) '{ ...c }; }': () 2[18; 369) '{ ...o_x; }': ()
3[28; 29) 'y': &i32 3[28; 29) 'y': &i32
4[32; 33) 'x': &i32 4[32; 33) 'x': &i32
5[43; 45) '&z': &i32 5[43; 45) '&z': &i32
@@ -37,3 +37,11 @@
37[246; 251) 'a + b': u64 37[246; 251) 'a + b': u64
38[250; 251) 'b': u64 38[250; 251) 'b': u64
39[253; 254) 'c': i32 39[253; 254) 'c': i32
40[267; 279) 'ref ref_to_x': &&i32
41[282; 283) 'x': &i32
42[293; 302) 'mut mut_x': &i32
43[305; 306) 'x': &i32
44[316; 336) 'ref mu...f_to_x': &mut &i32
45[339; 340) 'x': &i32
46[350; 351) 'k': &mut &i32
47[354; 366) 'mut_ref_to_x': &mut &i32