aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-12-23 19:50:04 +0000
committerGitHub <[email protected]>2020-12-23 19:50:04 +0000
commita82c2445be5fbd9ef6ff8a60326d60ae97c122bb (patch)
tree8877d4fd3916b28a801a6fa247640138636f72d9
parent01a3fd960089d562dac328221c93875cabad1d51 (diff)
parenta142beaf013a016a48eb9f193b55e0cbcb80b6a9 (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.rs16
-rw-r--r--crates/hir_def/src/expr.rs16
-rw-r--r--crates/hir_ty/src/infer/expr.rs2
-rw-r--r--crates/hir_ty/src/infer/pat.rs6
-rw-r--r--crates/hir_ty/src/tests/patterns.rs30
-rw-r--r--crates/hir_ty/src/tests/simple.rs13
-rw-r--r--crates/syntax/src/ast/expr_ext.rs4
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
404impl Pat { 411impl 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]
779fn const_block_pattern() {
780 check_infer(
781 r#"
782struct Foo(usize);
783fn 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 }