diff options
author | Lukas Wirth <[email protected]> | 2020-12-23 11:15:38 +0000 |
---|---|---|
committer | Lukas Wirth <[email protected]> | 2020-12-23 11:15:38 +0000 |
commit | 0a780c0ab3869d92fb56ae3b2ddc7636fb169314 (patch) | |
tree | 9323c15986fdb61054e972fcebf88717f1ebb277 /crates | |
parent | fd1fcf2c2e90ab04103a6aa9d033ec64dcc8d555 (diff) |
Implement const pat inference
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 12 | ||||
-rw-r--r-- | crates/hir_def/src/expr.rs | 8 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/patterns.rs | 30 |
4 files changed, 51 insertions, 5 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 978c3a324..4492a7d77 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -932,10 +932,16 @@ impl ExprCollector<'_> { | |||
932 | let inner = self.collect_pat_opt(boxpat.pat()); | 932 | let inner = self.collect_pat_opt(boxpat.pat()); |
933 | Pat::Box { inner } | 933 | Pat::Box { inner } |
934 | } | 934 | } |
935 | // FIXME: implement | 935 | ast::Pat::ConstBlockPat(const_block_pat) => { |
936 | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) | ast::Pat::ConstBlockPat(_) => { | 936 | if let Some(expr) = const_block_pat.block_expr() { |
937 | Pat::Missing | 937 | let expr_id = self.collect_block(expr); |
938 | Pat::ConstBlock(expr_id) | ||
939 | } else { | ||
940 | Pat::Missing | ||
941 | } | ||
938 | } | 942 | } |
943 | // FIXME: implement | ||
944 | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, | ||
939 | }; | 945 | }; |
940 | let ptr = AstPtr::new(&pat); | 946 | let ptr = AstPtr::new(&pat); |
941 | self.alloc_pat(pattern, Either::Left(ptr)) | 947 | self.alloc_pat(pattern, Either::Left(ptr)) |
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs index e5d740a36..b1e57c693 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs | |||
@@ -399,12 +399,18 @@ pub enum Pat { | |||
399 | TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, | 399 | TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, |
400 | Ref { pat: PatId, mutability: Mutability }, | 400 | Ref { pat: PatId, mutability: Mutability }, |
401 | Box { inner: PatId }, | 401 | Box { inner: PatId }, |
402 | ConstBlock(ExprId), | ||
402 | } | 403 | } |
403 | 404 | ||
404 | impl Pat { | 405 | impl Pat { |
405 | pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) { | 406 | pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) { |
406 | match self { | 407 | match self { |
407 | Pat::Range { .. } | Pat::Lit(..) | Pat::Path(..) | Pat::Wild | Pat::Missing => {} | 408 | Pat::Range { .. } |
409 | | Pat::Lit(..) | ||
410 | | Pat::Path(..) | ||
411 | | Pat::ConstBlock(..) | ||
412 | | Pat::Wild | ||
413 | | Pat::Missing => {} | ||
408 | Pat::Bind { subpat, .. } => { | 414 | Pat::Bind { subpat, .. } => { |
409 | subpat.iter().copied().for_each(f); | 415 | subpat.iter().copied().for_each(f); |
410 | } | 416 | } |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index b70ec55eb..d974f805b 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -243,6 +243,9 @@ impl<'a> InferenceContext<'a> { | |||
243 | } | 243 | } |
244 | None => Ty::Unknown, | 244 | None => Ty::Unknown, |
245 | }, | 245 | }, |
246 | Pat::ConstBlock(expr) => { | ||
247 | self.infer_expr(*expr, &Expectation::has_type(expected.clone())) | ||
248 | } | ||
246 | Pat::Missing => Ty::Unknown, | 249 | Pat::Missing => Ty::Unknown, |
247 | }; | 250 | }; |
248 | // use a new type variable if we got Ty::Unknown here | 251 | // use a new type variable if we got Ty::Unknown here |
@@ -264,8 +267,9 @@ fn is_non_ref_pat(body: &hir_def::body::Body, pat: PatId) -> bool { | |||
264 | | Pat::Range { .. } | 267 | | Pat::Range { .. } |
265 | | Pat::Slice { .. } => true, | 268 | | Pat::Slice { .. } => true, |
266 | Pat::Or(pats) => pats.iter().all(|p| is_non_ref_pat(body, *p)), | 269 | Pat::Or(pats) => pats.iter().all(|p| is_non_ref_pat(body, *p)), |
267 | // FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented. | 270 | // FIXME: ConstBlock/Path/Lit might actually evaluate to ref, but inference is unimplemented. |
268 | Pat::Path(..) => true, | 271 | Pat::Path(..) => true, |
272 | Pat::ConstBlock(..) => true, | ||
269 | Pat::Lit(expr) => match body[*expr] { | 273 | Pat::Lit(expr) => match body[*expr] { |
270 | Expr::Literal(Literal::String(..)) => false, | 274 | Expr::Literal(Literal::String(..)) => false, |
271 | _ => true, | 275 | _ => true, |
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs index 5a5f48fd0..2053d8f56 100644 --- a/crates/hir_ty/src/tests/patterns.rs +++ b/crates/hir_ty/src/tests/patterns.rs | |||
@@ -774,3 +774,33 @@ fn foo(tuple: Tuple) { | |||
774 | "#]], | 774 | "#]], |
775 | ); | 775 | ); |
776 | } | 776 | } |
777 | |||
778 | #[test] | ||
779 | fn const_block_pattern() { | ||
780 | check_infer( | ||
781 | r#" | ||
782 | struct Foo(usize); | ||
783 | fn foo(foo: Foo) { | ||
784 | match foo { | ||
785 | const { Foo(15 + 32) } => {}, | ||
786 | _ => {} | ||
787 | } | ||
788 | }"#, | ||
789 | expect![[r#" | ||
790 | 26..29 'foo': Foo | ||
791 | 36..115 '{ ... } }': () | ||
792 | 42..113 'match ... }': () | ||
793 | 48..51 'foo': Foo | ||
794 | 62..84 'const ... 32) }': Foo | ||
795 | 68..84 '{ Foo(... 32) }': Foo | ||
796 | 70..73 'Foo': Foo(usize) -> Foo | ||
797 | 70..82 'Foo(15 + 32)': Foo | ||
798 | 74..76 '15': usize | ||
799 | 74..81 '15 + 32': usize | ||
800 | 79..81 '32': usize | ||
801 | 88..90 '{}': () | ||
802 | 100..101 '_': Foo | ||
803 | 105..107 '{}': () | ||
804 | "#]], | ||
805 | ); | ||
806 | } | ||