Implement const pat inference
This commit is contained in:
parent
fd1fcf2c2e
commit
0a780c0ab3
@ -932,10 +932,16 @@ fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
|
||||
let inner = self.collect_pat_opt(boxpat.pat());
|
||||
Pat::Box { inner }
|
||||
}
|
||||
// FIXME: implement
|
||||
ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) | ast::Pat::ConstBlockPat(_) => {
|
||||
Pat::Missing
|
||||
ast::Pat::ConstBlockPat(const_block_pat) => {
|
||||
if let Some(expr) = const_block_pat.block_expr() {
|
||||
let expr_id = self.collect_block(expr);
|
||||
Pat::ConstBlock(expr_id)
|
||||
} else {
|
||||
Pat::Missing
|
||||
}
|
||||
}
|
||||
// FIXME: implement
|
||||
ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing,
|
||||
};
|
||||
let ptr = AstPtr::new(&pat);
|
||||
self.alloc_pat(pattern, Either::Left(ptr))
|
||||
|
@ -399,12 +399,18 @@ pub enum Pat {
|
||||
TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> },
|
||||
Ref { pat: PatId, mutability: Mutability },
|
||||
Box { inner: PatId },
|
||||
ConstBlock(ExprId),
|
||||
}
|
||||
|
||||
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::Range { .. }
|
||||
| Pat::Lit(..)
|
||||
| Pat::Path(..)
|
||||
| Pat::ConstBlock(..)
|
||||
| Pat::Wild
|
||||
| Pat::Missing => {}
|
||||
Pat::Bind { subpat, .. } => {
|
||||
subpat.iter().copied().for_each(f);
|
||||
}
|
||||
|
@ -243,6 +243,9 @@ pub(super) fn infer_pat(
|
||||
}
|
||||
None => Ty::Unknown,
|
||||
},
|
||||
Pat::ConstBlock(expr) => {
|
||||
self.infer_expr(*expr, &Expectation::has_type(expected.clone()))
|
||||
}
|
||||
Pat::Missing => Ty::Unknown,
|
||||
};
|
||||
// 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 {
|
||||
| Pat::Range { .. }
|
||||
| Pat::Slice { .. } => true,
|
||||
Pat::Or(pats) => pats.iter().all(|p| is_non_ref_pat(body, *p)),
|
||||
// FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented.
|
||||
// FIXME: ConstBlock/Path/Lit might actually evaluate to ref, but inference is unimplemented.
|
||||
Pat::Path(..) => true,
|
||||
Pat::ConstBlock(..) => true,
|
||||
Pat::Lit(expr) => match body[*expr] {
|
||||
Expr::Literal(Literal::String(..)) => false,
|
||||
_ => true,
|
||||
|
@ -774,3 +774,33 @@ fn foo(tuple: Tuple) {
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn const_block_pattern() {
|
||||
check_infer(
|
||||
r#"
|
||||
struct Foo(usize);
|
||||
fn foo(foo: Foo) {
|
||||
match foo {
|
||||
const { Foo(15 + 32) } => {},
|
||||
_ => {}
|
||||
}
|
||||
}"#,
|
||||
expect![[r#"
|
||||
26..29 'foo': Foo
|
||||
36..115 '{ ... } }': ()
|
||||
42..113 'match ... }': ()
|
||||
48..51 'foo': Foo
|
||||
62..84 'const ... 32) }': Foo
|
||||
68..84 '{ Foo(... 32) }': Foo
|
||||
70..73 'Foo': Foo(usize) -> Foo
|
||||
70..82 'Foo(15 + 32)': Foo
|
||||
74..76 '15': usize
|
||||
74..81 '15 + 32': usize
|
||||
79..81 '32': usize
|
||||
88..90 '{}': ()
|
||||
100..101 '_': Foo
|
||||
105..107 '{}': ()
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user