From ac216880f5d1a3e5727b96d7b22433beec10382b Mon Sep 17 00:00:00 2001 From: Marcus Klaas de Vries Date: Thu, 17 Jan 2019 00:08:10 +0100 Subject: Implement unlabeled struct field pattern inference --- crates/ra_hir/src/expr.rs | 11 ++++++----- crates/ra_hir/src/ty.rs | 15 ++++----------- crates/ra_hir/src/ty/tests.rs | 5 +++++ crates/ra_syntax/src/ast.rs | 42 +++++++++++------------------------------- 4 files changed, 26 insertions(+), 47 deletions(-) diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 893bad9cd..e7235c1a1 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -332,7 +332,7 @@ impl_arena_id!(PatId); #[derive(Debug, Clone, Eq, PartialEq)] pub struct FieldPat { pub(crate) name: Name, - pub(crate) pat: Option, + pub(crate) pat: PatId, } /// Close relative to rustc's hir::PatKind @@ -393,7 +393,7 @@ impl Pat { total_iter.map(|pat| *pat).for_each(f); } Pat::Struct { args, .. } => { - args.iter().filter_map(|a| a.pat).for_each(f); + args.iter().map(|f| f.pat).for_each(f); } } } @@ -821,9 +821,10 @@ impl ExprCollector { .expect("every struct should have a field list") .field_pats() .into_iter() - .map(|f| FieldPat { - name: Name::new(f.ident), - pat: f.pat.as_ref().map(|p| self.collect_pat(p)), + .map(|f| { + let name = Name::new(f.ident); + let pat = self.collect_pat(&*f.pat); + FieldPat { name, pat } }) .collect(); diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 6bad61a2a..66940ec30 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -937,19 +937,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }; for sub_pat in sub_pats { - let tyref = fields - .iter() - .find(|field| field.name == sub_pat.name) - .map(|field| &field.type_ref); + let matching_field = fields.iter().find(|field| field.name == sub_pat.name); - if let Some(typeref) = tyref { + if let Some(field) = matching_field { + let typeref = &field.type_ref; let sub_ty = Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), typeref); - - if let Some(pat) = sub_pat.pat { - self.infer_pat(pat, &Expectation::has_type(sub_ty)); - } else { - // TODO: deal with this case: S { x, y } - } + self.infer_pat(sub_pat.pat, &Expectation::has_type(sub_ty)); } } diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 75fe2cc6e..10842f967 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -389,6 +389,11 @@ fn test() { let S(y, z) = foo; let E::A { x: new_var } = e; + + match e { + E::A { x } => x, + E::B => 1, + }; } "#, "adt_pattern.txt", diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 3df23b16f..4b7edbbe7 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -664,36 +664,11 @@ impl LiteralExpr { } } -// STRUCT_PAT@[20; 42) -// PATH@[20; 26) -// PATH_SEGMENT@[20; 26) -// NAME_REF@[20; 26) -// IDENT@[20; 26) "Strukt" -// WHITESPACE@[26; 27) -// FIELD_PAT_LIST@[27; 42) -// L_CURLY@[27; 28) -// WHITESPACE@[28; 29) -// IDENT@[29; 30) "x" -// COLON@[30; 31) -// WHITESPACE@[31; 32) -// BIND_PAT@[32; 33) -// NAME@[32; 33) -// IDENT@[32; 33) "x" -// COMMA@[33; 34) -// WHITESPACE@[34; 35) -// BIND_PAT@[35; 36) -// NAME@[35; 36) -// IDENT@[35; 36) "y" -// COMMA@[36; 37) -// WHITESPACE@[37; 38) -// DOTDOT@[38; 40) -// WHITESPACE@[40; 41) -// R_CURLY@[41; 42) - #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct FieldPat { pub ident: SmolStr, - pub pat: Option>, + // FIXME: could we use a regular reference? + pub pat: TreeArc, } impl FieldPatList { @@ -704,12 +679,17 @@ impl FieldPatList { let mut pats = Vec::new(); while let Some(node) = child_iter.next() { - if node.kind() != IDENT { + let kind = node.kind(); + if kind != IDENT && kind != BIND_PAT { continue; } - let ident = node.leaf_text().unwrap().clone(); - let mut pat = None; + let ident = if let Some(text) = node.leaf_text() { + text.clone() + } else { + SmolStr::new(node.text().to_string()) + }; + let mut pat = Pat::cast(node).map(AstNode::to_owned); // get pat while let Some(node) = child_iter.next() { @@ -724,7 +704,7 @@ impl FieldPatList { let field_pat = FieldPat { ident: ident, - pat: pat, + pat: pat.unwrap(), }; pats.push(field_pat); } -- cgit v1.2.3