From 07a704e31cf74deb28a15859b5adfe65ed709bf4 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 12 Sep 2020 21:18:57 +0200 Subject: [PATCH] Implement box pattern inference --- crates/hir_def/src/body/lower.rs | 6 +++++- crates/hir_def/src/expr.rs | 2 ++ crates/hir_ty/src/infer/pat.rs | 14 +++++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 30ac12a12e4..9ea3d529153 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs @@ -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)) diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs index c94b3a36f57..dc975d42f82 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs @@ -395,6 +395,7 @@ pub enum Pat { Bind { mode: BindingAnnotation, name: Name, subpat: Option }, TupleStruct { path: Option, args: Vec, ellipsis: Option }, 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), } } } diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index dde38bc397b..cde2ab82b65 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs @@ -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, } } -- 2.44.0