aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2020-12-23 11:15:38 +0000
committerLukas Wirth <[email protected]>2020-12-23 11:15:38 +0000
commit0a780c0ab3869d92fb56ae3b2ddc7636fb169314 (patch)
tree9323c15986fdb61054e972fcebf88717f1ebb277 /crates
parentfd1fcf2c2e90ab04103a6aa9d033ec64dcc8d555 (diff)
Implement const pat inference
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_def/src/body/lower.rs12
-rw-r--r--crates/hir_def/src/expr.rs8
-rw-r--r--crates/hir_ty/src/infer/pat.rs6
-rw-r--r--crates/hir_ty/src/tests/patterns.rs30
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
404impl Pat { 405impl 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]
779fn const_block_pattern() {
780 check_infer(
781 r#"
782struct Foo(usize);
783fn 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}