Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions crates/hir_def/src/body/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,10 @@ impl ExprCollector<'_> {
let body = self.collect_block_opt(e.block_expr());
self.alloc_expr(Expr::Async { body }, syntax_ptr)
}
ast::Effect::Const(_) => {
let body = self.collect_block_opt(e.block_expr());
self.alloc_expr(Expr::Const { body }, syntax_ptr)
}
},
ast::Expr::BlockExpr(e) => self.collect_block(e),
ast::Expr::LoopExpr(e) => {
Expand Down Expand Up @@ -932,10 +936,16 @@ impl ExprCollector<'_> {
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))
Expand Down
16 changes: 14 additions & 2 deletions crates/hir_def/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ pub enum Expr {
Async {
body: ExprId,
},
Const {
body: ExprId,
},
Cast {
expr: ExprId,
type_ref: TypeRef,
Expand Down Expand Up @@ -253,7 +256,10 @@ impl Expr {
f(*expr);
}
}
Expr::TryBlock { body } | Expr::Unsafe { body } | Expr::Async { body } => f(*body),
Expr::TryBlock { body }
| Expr::Unsafe { body }
| Expr::Async { body }
| Expr::Const { body } => f(*body),
Expr::Loop { body, .. } => f(*body),
Expr::While { condition, body, .. } => {
f(*condition);
Expand Down Expand Up @@ -399,12 +405,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);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/hir_ty/src/infer/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ impl<'a> InferenceContext<'a> {
}
None => self.infer_block(statements, *tail, expected),
},
Expr::Unsafe { body } => self.infer_expr(*body, expected),
Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected),
Expr::TryBlock { body } => {
let _inner = self.infer_expr(*body, expected);
// FIXME should be std::result::Result<{inner}, _>
Expand Down
6 changes: 5 additions & 1 deletion crates/hir_ty/src/infer/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ impl<'a> InferenceContext<'a> {
}
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
Expand All @@ -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,
Expand Down
30 changes: 30 additions & 0 deletions crates/hir_ty/src/tests/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 '{}': ()
"#]],
);
}
13 changes: 9 additions & 4 deletions crates/hir_ty/src/tests/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1894,6 +1894,7 @@ fn effects_smoke_test() {
let x = unsafe { 92 };
let y = async { async { () }.await };
let z = try { () };
let w = const { 92 };
let t = 'a: { 92 };
}
Expand All @@ -1905,7 +1906,7 @@ fn effects_smoke_test() {
}
"#,
expect![[r#"
16..136 '{ ...2 }; }': ()
16..162 '{ ...2 }; }': ()
26..27 'x': i32
30..43 'unsafe { 92 }': i32
37..43 '{ 92 }': i32
Expand All @@ -1921,9 +1922,13 @@ fn effects_smoke_test() {
99..109 'try { () }': {unknown}
103..109 '{ () }': ()
105..107 '()': ()
119..120 't': i32
127..133 '{ 92 }': i32
129..131 '92': i32
119..120 'w': i32
123..135 'const { 92 }': i32
129..135 '{ 92 }': i32
131..133 '92': i32
145..146 't': i32
153..159 '{ 92 }': i32
155..157 '92': i32
"#]],
)
}
Expand Down
4 changes: 4 additions & 0 deletions crates/syntax/src/ast/expr_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ pub enum Effect {
Async(SyntaxToken),
Unsafe(SyntaxToken),
Try(SyntaxToken),
Const(SyntaxToken),
// Very much not an effect, but we stuff it into this node anyway
Label(ast::Label),
}
Expand All @@ -373,6 +374,9 @@ impl ast::EffectExpr {
if let Some(token) = self.try_token() {
return Effect::Try(token);
}
if let Some(token) = self.const_token() {
return Effect::Const(token);
}
if let Some(label) = self.label() {
return Effect::Label(label);
}
Expand Down