Skip to content

Commit 0a780c0

Browse files
committed
Implement const pat inference
1 parent fd1fcf2 commit 0a780c0

File tree

4 files changed

+51
-5
lines changed

4 files changed

+51
-5
lines changed

crates/hir_def/src/body/lower.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -932,10 +932,16 @@ impl ExprCollector<'_> {
932932
let inner = self.collect_pat_opt(boxpat.pat());
933933
Pat::Box { inner }
934934
}
935-
// FIXME: implement
936-
ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) | ast::Pat::ConstBlockPat(_) => {
937-
Pat::Missing
935+
ast::Pat::ConstBlockPat(const_block_pat) => {
936+
if let Some(expr) = const_block_pat.block_expr() {
937+
let expr_id = self.collect_block(expr);
938+
Pat::ConstBlock(expr_id)
939+
} else {
940+
Pat::Missing
941+
}
938942
}
943+
// FIXME: implement
944+
ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing,
939945
};
940946
let ptr = AstPtr::new(&pat);
941947
self.alloc_pat(pattern, Either::Left(ptr))

crates/hir_def/src/expr.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,12 +399,18 @@ pub enum Pat {
399399
TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> },
400400
Ref { pat: PatId, mutability: Mutability },
401401
Box { inner: PatId },
402+
ConstBlock(ExprId),
402403
}
403404

404405
impl Pat {
405406
pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) {
406407
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 => {}
408414
Pat::Bind { subpat, .. } => {
409415
subpat.iter().copied().for_each(f);
410416
}

crates/hir_ty/src/infer/pat.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,9 @@ impl<'a> InferenceContext<'a> {
243243
}
244244
None => Ty::Unknown,
245245
},
246+
Pat::ConstBlock(expr) => {
247+
self.infer_expr(*expr, &Expectation::has_type(expected.clone()))
248+
}
246249
Pat::Missing => Ty::Unknown,
247250
};
248251
// 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 {
264267
| Pat::Range { .. }
265268
| Pat::Slice { .. } => true,
266269
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.
268271
Pat::Path(..) => true,
272+
Pat::ConstBlock(..) => true,
269273
Pat::Lit(expr) => match body[*expr] {
270274
Expr::Literal(Literal::String(..)) => false,
271275
_ => true,

crates/hir_ty/src/tests/patterns.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,3 +774,33 @@ fn foo(tuple: Tuple) {
774774
"#]],
775775
);
776776
}
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+
}

0 commit comments

Comments
 (0)