diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-12-23 19:50:04 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-12-23 19:50:04 +0000 |
commit | a82c2445be5fbd9ef6ff8a60326d60ae97c122bb (patch) | |
tree | 8877d4fd3916b28a801a6fa247640138636f72d9 | |
parent | 01a3fd960089d562dac328221c93875cabad1d51 (diff) | |
parent | a142beaf013a016a48eb9f193b55e0cbcb80b6a9 (diff) |
Merge #7020
7020: Implement const pat and expr inference r=flodiebold a=Veykril
Co-authored-by: Lukas Wirth <[email protected]>
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 16 | ||||
-rw-r--r-- | crates/hir_def/src/expr.rs | 16 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/patterns.rs | 30 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/simple.rs | 13 | ||||
-rw-r--r-- | crates/syntax/src/ast/expr_ext.rs | 4 |
7 files changed, 76 insertions, 11 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 978c3a324..1b98504bb 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -246,6 +246,10 @@ impl ExprCollector<'_> { | |||
246 | let body = self.collect_block_opt(e.block_expr()); | 246 | let body = self.collect_block_opt(e.block_expr()); |
247 | self.alloc_expr(Expr::Async { body }, syntax_ptr) | 247 | self.alloc_expr(Expr::Async { body }, syntax_ptr) |
248 | } | 248 | } |
249 | ast::Effect::Const(_) => { | ||
250 | let body = self.collect_block_opt(e.block_expr()); | ||
251 | self.alloc_expr(Expr::Const { body }, syntax_ptr) | ||
252 | } | ||
249 | }, | 253 | }, |
250 | ast::Expr::BlockExpr(e) => self.collect_block(e), | 254 | ast::Expr::BlockExpr(e) => self.collect_block(e), |
251 | ast::Expr::LoopExpr(e) => { | 255 | ast::Expr::LoopExpr(e) => { |
@@ -932,10 +936,16 @@ impl ExprCollector<'_> { | |||
932 | let inner = self.collect_pat_opt(boxpat.pat()); | 936 | let inner = self.collect_pat_opt(boxpat.pat()); |
933 | Pat::Box { inner } | 937 | Pat::Box { inner } |
934 | } | 938 | } |
935 | // FIXME: implement | 939 | ast::Pat::ConstBlockPat(const_block_pat) => { |
936 | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) | ast::Pat::ConstBlockPat(_) => { | 940 | if let Some(expr) = const_block_pat.block_expr() { |
937 | Pat::Missing | 941 | let expr_id = self.collect_block(expr); |
942 | Pat::ConstBlock(expr_id) | ||
943 | } else { | ||
944 | Pat::Missing | ||
945 | } | ||
938 | } | 946 | } |
947 | // FIXME: implement | ||
948 | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, | ||
939 | }; | 949 | }; |
940 | let ptr = AstPtr::new(&pat); | 950 | let ptr = AstPtr::new(&pat); |
941 | self.alloc_pat(pattern, Either::Left(ptr)) | 951 | 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..3bba30397 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs | |||
@@ -114,6 +114,9 @@ pub enum Expr { | |||
114 | Async { | 114 | Async { |
115 | body: ExprId, | 115 | body: ExprId, |
116 | }, | 116 | }, |
117 | Const { | ||
118 | body: ExprId, | ||
119 | }, | ||
117 | Cast { | 120 | Cast { |
118 | expr: ExprId, | 121 | expr: ExprId, |
119 | type_ref: TypeRef, | 122 | type_ref: TypeRef, |
@@ -253,7 +256,10 @@ impl Expr { | |||
253 | f(*expr); | 256 | f(*expr); |
254 | } | 257 | } |
255 | } | 258 | } |
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), | ||
257 | Expr::Loop { body, .. } => f(*body), | 263 | Expr::Loop { body, .. } => f(*body), |
258 | Expr::While { condition, body, .. } => { | 264 | Expr::While { condition, body, .. } => { |
259 | f(*condition); | 265 | f(*condition); |
@@ -399,12 +405,18 @@ pub enum Pat { | |||
399 | TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, | 405 | TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, |
400 | Ref { pat: PatId, mutability: Mutability }, | 406 | Ref { pat: PatId, mutability: Mutability }, |
401 | Box { inner: PatId }, | 407 | Box { inner: PatId }, |
408 | ConstBlock(ExprId), | ||
402 | } | 409 | } |
403 | 410 | ||
404 | impl Pat { | 411 | impl Pat { |
405 | pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) { | 412 | pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) { |
406 | match self { | 413 | 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 => {} | ||
408 | Pat::Bind { subpat, .. } => { | 420 | Pat::Bind { subpat, .. } => { |
409 | subpat.iter().copied().for_each(f); | 421 | subpat.iter().copied().for_each(f); |
410 | } | 422 | } |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 2cdce2cef..744569e6e 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -155,7 +155,7 @@ impl<'a> InferenceContext<'a> { | |||
155 | } | 155 | } |
156 | None => self.infer_block(statements, *tail, expected), | 156 | None => self.infer_block(statements, *tail, expected), |
157 | }, | 157 | }, |
158 | Expr::Unsafe { body } => self.infer_expr(*body, expected), | 158 | Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected), |
159 | Expr::TryBlock { body } => { | 159 | Expr::TryBlock { body } => { |
160 | let _inner = self.infer_expr(*body, expected); | 160 | let _inner = self.infer_expr(*body, expected); |
161 | // FIXME should be std::result::Result<{inner}, _> | 161 | // FIXME should be std::result::Result<{inner}, _> |
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] | ||
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 | } | ||
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index a569223b4..a61282d5a 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs | |||
@@ -1894,6 +1894,7 @@ fn effects_smoke_test() { | |||
1894 | let x = unsafe { 92 }; | 1894 | let x = unsafe { 92 }; |
1895 | let y = async { async { () }.await }; | 1895 | let y = async { async { () }.await }; |
1896 | let z = try { () }; | 1896 | let z = try { () }; |
1897 | let w = const { 92 }; | ||
1897 | let t = 'a: { 92 }; | 1898 | let t = 'a: { 92 }; |
1898 | } | 1899 | } |
1899 | 1900 | ||
@@ -1905,7 +1906,7 @@ fn effects_smoke_test() { | |||
1905 | } | 1906 | } |
1906 | "#, | 1907 | "#, |
1907 | expect![[r#" | 1908 | expect![[r#" |
1908 | 16..136 '{ ...2 }; }': () | 1909 | 16..162 '{ ...2 }; }': () |
1909 | 26..27 'x': i32 | 1910 | 26..27 'x': i32 |
1910 | 30..43 'unsafe { 92 }': i32 | 1911 | 30..43 'unsafe { 92 }': i32 |
1911 | 37..43 '{ 92 }': i32 | 1912 | 37..43 '{ 92 }': i32 |
@@ -1921,9 +1922,13 @@ fn effects_smoke_test() { | |||
1921 | 99..109 'try { () }': {unknown} | 1922 | 99..109 'try { () }': {unknown} |
1922 | 103..109 '{ () }': () | 1923 | 103..109 '{ () }': () |
1923 | 105..107 '()': () | 1924 | 105..107 '()': () |
1924 | 119..120 't': i32 | 1925 | 119..120 'w': i32 |
1925 | 127..133 '{ 92 }': i32 | 1926 | 123..135 'const { 92 }': i32 |
1926 | 129..131 '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 | ||
1927 | "#]], | 1932 | "#]], |
1928 | ) | 1933 | ) |
1929 | } | 1934 | } |
diff --git a/crates/syntax/src/ast/expr_ext.rs b/crates/syntax/src/ast/expr_ext.rs index e4a9b945c..636ce166d 100644 --- a/crates/syntax/src/ast/expr_ext.rs +++ b/crates/syntax/src/ast/expr_ext.rs | |||
@@ -358,6 +358,7 @@ pub enum Effect { | |||
358 | Async(SyntaxToken), | 358 | Async(SyntaxToken), |
359 | Unsafe(SyntaxToken), | 359 | Unsafe(SyntaxToken), |
360 | Try(SyntaxToken), | 360 | Try(SyntaxToken), |
361 | Const(SyntaxToken), | ||
361 | // Very much not an effect, but we stuff it into this node anyway | 362 | // Very much not an effect, but we stuff it into this node anyway |
362 | Label(ast::Label), | 363 | Label(ast::Label), |
363 | } | 364 | } |
@@ -373,6 +374,9 @@ impl ast::EffectExpr { | |||
373 | if let Some(token) = self.try_token() { | 374 | if let Some(token) = self.try_token() { |
374 | return Effect::Try(token); | 375 | return Effect::Try(token); |
375 | } | 376 | } |
377 | if let Some(token) = self.const_token() { | ||
378 | return Effect::Const(token); | ||
379 | } | ||
376 | if let Some(label) = self.label() { | 380 | if let Some(label) = self.label() { |
377 | return Effect::Label(label); | 381 | return Effect::Label(label); |
378 | } | 382 | } |