From 44e9a9605b2b3916669182ba091599d59653c497 Mon Sep 17 00:00:00 2001 From: Marcus Klaas de Vries Date: Thu, 17 Jan 2019 13:40:45 +0100 Subject: Fixup annotated bindings --- .../ra_hir/src/code_model_impl/function/scope.rs | 15 ++++++++--- crates/ra_hir/src/expr.rs | 18 ++++++-------- crates/ra_hir/src/ty.rs | 29 ++++++++++++---------- crates/ra_hir/src/ty/tests.rs | 6 ++++- crates/ra_hir/src/ty/tests/data/adt_pattern.txt | 6 ++++- crates/ra_hir/src/ty/tests/data/pattern.txt | 10 +++++++- 6 files changed, 54 insertions(+), 30 deletions(-) (limited to 'crates') 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 { fn add_bindings(&mut self, body: &Body, scope: ScopeId, pat: PatId) { match &body[pat] { - Pat::Bind { name, .. } => self.scopes[scope].entries.push(ScopeEntry { - name: name.clone(), - pat, - }), + Pat::Bind { name, .. } => { + // bind can have a subpattern, but it's actually not allowed + // to bind to things in there + let entry = ScopeEntry { + name: name.clone(), + pat, + }; + self.scopes[scope].entries.push(entry) + } + // FIXME: isn't every call to add_binding starting an entirely new + // tree walk!? p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)), } } 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 { Bind { mode: BindingAnnotation, name: Name, - sub_pat: Option, + subpat: Option, }, TupleStruct { path: Option, @@ -413,12 +413,10 @@ pub enum Pat { impl Pat { pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) { match self { - Pat::Range { .. } - | Pat::Lit(..) - | Pat::Path(..) - | Pat::Wild - | Pat::Missing - | Pat::Bind { .. } => {} + Pat::Range { .. } | Pat::Lit(..) | Pat::Path(..) | Pat::Wild | Pat::Missing => {} + Pat::Bind { subpat, .. } => { + subpat.iter().map(|pat| *pat).for_each(f); + } Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { args.iter().map(|pat| *pat).for_each(f); } @@ -833,11 +831,11 @@ impl ExprCollector { .map(|nr| nr.as_name()) .unwrap_or_else(Name::missing); let annotation = BindingAnnotation::new(bp.is_mutable(), bp.is_ref()); - let sub_pat = bp.pat().map(|subpat| self.collect_pat(subpat)); + let subpat = bp.pat().map(|subpat| self.collect_pat(subpat)); Pat::Bind { name, mode: annotation, - sub_pat, + subpat, } } ast::PatKind::TupleStructPat(p) => { @@ -928,7 +926,7 @@ pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping { Pat::Bind { name: Name::self_param(), mode: BindingAnnotation::Unannotated, - sub_pat: None, + subpat: None, }, self_param, ); 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> { } } - fn infer_tuple_struct(&mut self, path: Option<&Path>, sub_pats: &[PatId]) -> Ty { + fn infer_tuple_struct(&mut self, path: Option<&Path>, subpats: &[PatId]) -> Ty { let (ty, fields) = if let Some(x) = self.resolve_fields(path) { x } else { return Ty::Unknown; }; - if fields.len() != sub_pats.len() { + if fields.len() != subpats.len() { return Ty::Unknown; } - for (&sub_pat, field) in sub_pats.iter().zip(fields.iter()) { + for (&subpat, field) in subpats.iter().zip(fields.iter()) { let sub_ty = self.make_ty(&field.type_ref); - self.infer_pat(sub_pat, &Expectation::has_type(sub_ty)); + self.infer_pat(subpat, &Expectation::has_type(sub_ty)); } ty } - fn infer_struct(&mut self, path: Option<&Path>, sub_pats: &[FieldPat]) -> Ty { + fn infer_struct(&mut self, path: Option<&Path>, subpats: &[FieldPat]) -> Ty { let (ty, fields) = if let Some(x) = self.resolve_fields(path) { x } else { return Ty::Unknown; }; - for sub_pat in sub_pats { - let matching_field = fields.iter().find(|field| field.name == sub_pat.name); + for subpat in subpats { + let matching_field = fields.iter().find(|field| field.name == subpat.name); if let Some(field) = matching_field { let typeref = &field.type_ref; let sub_ty = self.make_ty(typeref); - self.infer_pat(sub_pat.pat, &Expectation::has_type(sub_ty)); + self.infer_pat(subpat.pat, &Expectation::has_type(sub_ty)); } } @@ -979,8 +979,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } Pat::TupleStruct { path: ref p, - args: ref sub_pats, - } => self.infer_tuple_struct(p.as_ref(), sub_pats), + args: ref subpats, + } => self.infer_tuple_struct(p.as_ref(), subpats), Pat::Struct { path: ref p, args: ref fields, @@ -995,12 +995,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Pat::Bind { mode, name: _name, - sub_pat, + subpat, } => { - let subty = if let Some(subpat) = sub_pat { + let subty = if let Some(subpat) = subpat { self.infer_pat(*subpat, expected) } else { - Ty::Unknown + let ty = self.new_type_var(); + self.unify(&ty, &expected.ty); + let ty = self.resolve_ty_as_possible(ty); + ty }; 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) { } #[test] -fn infer_simple_pattern() { +fn infer_pattern() { check_inference( r#" fn test(x: &i32) { @@ -381,6 +381,7 @@ fn test(x: &i32) { let ref ref_to_x = x; let mut mut_x = x; let ref mut mut_ref_to_x = x; + let k = mut_ref_to_x; } "#, "pattern.txt", @@ -408,6 +409,9 @@ fn test() { E::A { x } => x, E::B => 1, }; + + let ref d @ E::A { .. } = e; + d; } "#, "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 @@ -[68; 221) '{ ... }; }': () +[68; 262) '{ ... d; }': () [78; 79) 'e': E [82; 95) 'E::A { x: 3 }': E [92; 93) '3': usize @@ -16,3 +16,7 @@ [191; 192) 'x': usize [202; 206) 'E::B': E [210; 211) '1': usize +[229; 248) 'ref d ...{ .. }': &E +[237; 248) 'E::A { .. }': E +[251; 252) 'e': E +[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 @@ [9; 10) 'x': &i32 -[18; 259) '{ ...c }; }': () +[18; 369) '{ ...o_x; }': () [28; 29) 'y': &i32 [32; 33) 'x': &i32 [43; 45) '&z': &i32 @@ -37,3 +37,11 @@ [246; 251) 'a + b': u64 [250; 251) 'b': u64 [253; 254) 'c': i32 +[267; 279) 'ref ref_to_x': &&i32 +[282; 283) 'x': &i32 +[293; 302) 'mut mut_x': &i32 +[305; 306) 'x': &i32 +[316; 336) 'ref mu...f_to_x': &mut &i32 +[339; 340) 'x': &i32 +[350; 351) 'k': &mut &i32 +[354; 366) 'mut_ref_to_x': &mut &i32 -- cgit v1.2.3