Skip to content

Commit a82c244

Browse files
bors[bot]Veykril
andauthored
Merge #7020
7020: Implement const pat and expr inference r=flodiebold a=Veykril Co-authored-by: Lukas Wirth <[email protected]>
2 parents 01a3fd9 + a142bea commit a82c244

File tree

7 files changed

+76
-11
lines changed

7 files changed

+76
-11
lines changed

crates/hir_def/src/body/lower.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@ impl ExprCollector<'_> {
246246
let body = self.collect_block_opt(e.block_expr());
247247
self.alloc_expr(Expr::Async { body }, syntax_ptr)
248248
}
249+
ast::Effect::Const(_) => {
250+
let body = self.collect_block_opt(e.block_expr());
251+
self.alloc_expr(Expr::Const { body }, syntax_ptr)
252+
}
249253
},
250254
ast::Expr::BlockExpr(e) => self.collect_block(e),
251255
ast::Expr::LoopExpr(e) => {
@@ -932,10 +936,16 @@ impl ExprCollector<'_> {
932936
let inner = self.collect_pat_opt(boxpat.pat());
933937
Pat::Box { inner }
934938
}
935-
// FIXME: implement
936-
ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) | ast::Pat::ConstBlockPat(_) => {
937-
Pat::Missing
939+
ast::Pat::ConstBlockPat(const_block_pat) => {
940+
if let Some(expr) = const_block_pat.block_expr() {
941+
let expr_id = self.collect_block(expr);
942+
Pat::ConstBlock(expr_id)
943+
} else {
944+
Pat::Missing
945+
}
938946
}
947+
// FIXME: implement
948+
ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing,
939949
};
940950
let ptr = AstPtr::new(&pat);
941951
self.alloc_pat(pattern, Either::Left(ptr))

crates/hir_def/src/expr.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ pub enum Expr {
114114
Async {
115115
body: ExprId,
116116
},
117+
Const {
118+
body: ExprId,
119+
},
117120
Cast {
118121
expr: ExprId,
119122
type_ref: TypeRef,
@@ -253,7 +256,10 @@ impl Expr {
253256
f(*expr);
254257
}
255258
}
256-
Expr::TryBlock { body } | Expr::Unsafe { body } | Expr::Async { body } => f(*body),
259+
Expr::TryBlock { body }
260+
| Expr::Unsafe { body }
261+
| Expr::Async { body }
262+
| Expr::Const { body } => f(*body),
257263
Expr::Loop { body, .. } => f(*body),
258264
Expr::While { condition, body, .. } => {
259265
f(*condition);
@@ -399,12 +405,18 @@ pub enum Pat {
399405
TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> },
400406
Ref { pat: PatId, mutability: Mutability },
401407
Box { inner: PatId },
408+
ConstBlock(ExprId),
402409
}
403410

404411
impl Pat {
405412
pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) {
406413
match self {
407-
Pat::Range { .. } | Pat::Lit(..) | Pat::Path(..) | Pat::Wild | Pat::Missing => {}
414+
Pat::Range { .. }
415+
| Pat::Lit(..)
416+
| Pat::Path(..)
417+
| Pat::ConstBlock(..)
418+
| Pat::Wild
419+
| Pat::Missing => {}
408420
Pat::Bind { subpat, .. } => {
409421
subpat.iter().copied().for_each(f);
410422
}

crates/hir_ty/src/infer/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ impl<'a> InferenceContext<'a> {
155155
}
156156
None => self.infer_block(statements, *tail, expected),
157157
},
158-
Expr::Unsafe { body } => self.infer_expr(*body, expected),
158+
Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected),
159159
Expr::TryBlock { body } => {
160160
let _inner = self.infer_expr(*body, expected);
161161
// FIXME should be std::result::Result<{inner}, _>

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+
}

crates/hir_ty/src/tests/simple.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1894,6 +1894,7 @@ fn effects_smoke_test() {
18941894
let x = unsafe { 92 };
18951895
let y = async { async { () }.await };
18961896
let z = try { () };
1897+
let w = const { 92 };
18971898
let t = 'a: { 92 };
18981899
}
18991900
@@ -1905,7 +1906,7 @@ fn effects_smoke_test() {
19051906
}
19061907
"#,
19071908
expect![[r#"
1908-
16..136 '{ ...2 }; }': ()
1909+
16..162 '{ ...2 }; }': ()
19091910
26..27 'x': i32
19101911
30..43 'unsafe { 92 }': i32
19111912
37..43 '{ 92 }': i32
@@ -1921,9 +1922,13 @@ fn effects_smoke_test() {
19211922
99..109 'try { () }': {unknown}
19221923
103..109 '{ () }': ()
19231924
105..107 '()': ()
1924-
119..120 't': i32
1925-
127..133 '{ 92 }': i32
1926-
129..131 '92': i32
1925+
119..120 'w': i32
1926+
123..135 'const { 92 }': i32
1927+
129..135 '{ 92 }': i32
1928+
131..133 '92': i32
1929+
145..146 't': i32
1930+
153..159 '{ 92 }': i32
1931+
155..157 '92': i32
19271932
"#]],
19281933
)
19291934
}

crates/syntax/src/ast/expr_ext.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ pub enum Effect {
358358
Async(SyntaxToken),
359359
Unsafe(SyntaxToken),
360360
Try(SyntaxToken),
361+
Const(SyntaxToken),
361362
// Very much not an effect, but we stuff it into this node anyway
362363
Label(ast::Label),
363364
}
@@ -373,6 +374,9 @@ impl ast::EffectExpr {
373374
if let Some(token) = self.try_token() {
374375
return Effect::Try(token);
375376
}
377+
if let Some(token) = self.const_token() {
378+
return Effect::Const(token);
379+
}
376380
if let Some(label) = self.label() {
377381
return Effect::Label(label);
378382
}

0 commit comments

Comments
 (0)