diff options
author | Marcus Klaas de Vries <[email protected]> | 2019-01-17 12:40:45 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-01-19 12:37:26 +0000 |
commit | 44e9a9605b2b3916669182ba091599d59653c497 (patch) | |
tree | 0bdeef63c2a1523ca69dda856226979f9a78f606 | |
parent | d48d5b8b6ca59b462b3a84dad9868daff2eddb6d (diff) |
Fixup annotated bindings
-rw-r--r-- | crates/ra_hir/src/code_model_impl/function/scope.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir/src/expr.rs | 18 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 29 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/adt_pattern.txt | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/pattern.txt | 10 |
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 { | |||
413 | impl Pat { | 413 | impl 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] |
362 | fn infer_simple_pattern() { | 362 | fn infer_pattern() { |
363 | check_inference( | 363 | check_inference( |
364 | r#" | 364 | r#" |
365 | fn test(x: &i32) { | 365 | fn 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 | ||