]> git.lizzy.rs Git - rust.git/commitdiff
Implement box pattern inference
authorJonas Schievink <jonasschievink@gmail.com>
Sat, 12 Sep 2020 19:18:57 +0000 (21:18 +0200)
committerJonas Schievink <jonasschievink@gmail.com>
Sat, 12 Sep 2020 19:18:57 +0000 (21:18 +0200)
crates/hir_def/src/body/lower.rs
crates/hir_def/src/expr.rs
crates/hir_ty/src/infer/pat.rs

index 30ac12a12e431369112ad294b514db88c393c2f6..9ea3d529153b2df0046e4590441747fc846f3690 100644 (file)
@@ -835,8 +835,12 @@ fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
 
                 Pat::Missing
             }
+            ast::Pat::BoxPat(boxpat) => {
+                let inner = self.collect_pat_opt(boxpat.pat());
+                Pat::Box { inner }
+            }
             // FIXME: implement
-            ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing,
+            ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing,
         };
         let ptr = AstPtr::new(&pat);
         self.alloc_pat(pattern, Either::Left(ptr))
index c94b3a36f57c73f9bfe767dc9ae0f4d1d5ad732f..dc975d42f825ddcb26aaadd249964f8eb7ebfe8d 100644 (file)
@@ -395,6 +395,7 @@ pub enum Pat {
     Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> },
     TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> },
     Ref { pat: PatId, mutability: Mutability },
+    Box { inner: PatId },
 }
 
 impl Pat {
@@ -415,6 +416,7 @@ pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) {
             Pat::Record { args, .. } => {
                 args.iter().map(|f| f.pat).for_each(f);
             }
+            Pat::Box { inner } => f(*inner),
         }
     }
 }
index dde38bc397b6eb184e342760001496badb8e3e58..cde2ab82b6516068e55d534c6d580b0942ea5f72 100644 (file)
@@ -209,6 +209,18 @@ pub(super) fn infer_pat(
                 end_ty
             }
             Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())),
+            Pat::Box { inner } => match self.resolve_boxed_box() {
+                Some(box_adt) => {
+                    let inner_expected = match expected.as_adt() {
+                        Some((adt, substs)) if adt == box_adt => substs.as_single(),
+                        _ => &Ty::Unknown,
+                    };
+
+                    let inner_ty = self.infer_pat(*inner, inner_expected, default_bm);
+                    Ty::apply_one(TypeCtor::Adt(box_adt), inner_ty)
+                }
+                None => Ty::Unknown,
+            },
             Pat::Missing => Ty::Unknown,
         };
         // use a new type variable if we got Ty::Unknown here
@@ -236,6 +248,6 @@ fn is_non_ref_pat(body: &hir_def::body::Body, pat: PatId) -> bool {
             Expr::Literal(Literal::String(..)) => false,
             _ => true,
         },
-        Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Missing => false,
+        Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Box { .. } | Pat::Missing => false,
     }
 }