about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-12-23 19:50:04 +0000
committerGitHub <noreply@github.com>2020-12-23 19:50:04 +0000
commita82c2445be5fbd9ef6ff8a60326d60ae97c122bb (patch)
tree8877d4fd3916b28a801a6fa247640138636f72d9
parent01a3fd960089d562dac328221c93875cabad1d51 (diff)
parenta142beaf013a016a48eb9f193b55e0cbcb80b6a9 (diff)
downloadrust-a82c2445be5fbd9ef6ff8a60326d60ae97c122bb.tar.gz
rust-a82c2445be5fbd9ef6ff8a60326d60ae97c122bb.zip
Merge #7020
7020: Implement const pat and expr inference r=flodiebold a=Veykril



Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
-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 978c3a32498..1b98504bb36 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -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) => {
@@ -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))
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs
index e5d740a3653..3bba30397ee 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -114,6 +114,9 @@ pub enum Expr {
     Async {
         body: ExprId,
     },
+    Const {
+        body: ExprId,
+    },
     Cast {
         expr: ExprId,
         type_ref: TypeRef,
@@ -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);
@@ -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);
             }
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 2cdce2cefce..744569e6ef2 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> {
                 }
                 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}, _>
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index b70ec55eb5c..d974f805b5b 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> {
                 }
                 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,
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs
index 5a5f48fd05b..2053d8f56ee 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) {
         "#]],
     );
 }
+
+#[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 '{}': ()
+        "#]],
+    );
+}
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index a569223b4b2..a61282d5a74 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() {
             let x = unsafe { 92 };
             let y = async { async { () }.await };
             let z = try { () };
+            let w = const { 92 };
             let t = 'a: { 92 };
         }
 
@@ -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
@@ -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
         "#]],
     )
 }
diff --git a/crates/syntax/src/ast/expr_ext.rs b/crates/syntax/src/ast/expr_ext.rs
index e4a9b945c98..636ce166d74 100644
--- a/crates/syntax/src/ast/expr_ext.rs
+++ b/crates/syntax/src/ast/expr_ext.rs
@@ -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),
 }
@@ -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);
         }