diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 79bbc5dabaa..24deff70732 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -513,10 +513,10 @@ impl<'a> InferenceContext<'a> {
                 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
                 if let Some(box_) = self.resolve_boxed_box() {
                     let mut sb =
-                        Substitution::builder(generics(self.db.upcast(), box_.into()).len());
+                        Substitution::build_for_generics(&generics(self.db.upcast(), box_.into()));
                     sb = sb.push(inner_ty);
-                    match self.db.generic_defaults(box_.into()).as_ref() {
-                        [_, alloc_ty, ..] if !alloc_ty.value.is_unknown() => {
+                    match self.db.generic_defaults(box_.into()).get(1) {
+                        Some(alloc_ty) if !alloc_ty.value.is_unknown() && sb.remaining() > 0 => {
                             sb = sb.push(alloc_ty.value.clone());
                         }
                         _ => (),
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index ec491648fe9..474363709ba 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -13,7 +13,9 @@ use hir_expand::name::Name;
 
 use super::{BindingMode, Expectation, InferenceContext};
 use crate::{
-    lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyKind,
+    lower::lower_to_chalk_mutability,
+    utils::{generics, variant_data},
+    Interner, Substitution, Ty, TyKind,
 };
 
 impl<'a> InferenceContext<'a> {
@@ -233,13 +235,31 @@ impl<'a> InferenceContext<'a> {
             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().clone(),
-                        _ => self.result.standard_types.unknown.clone(),
+                    let (inner_ty, alloc_ty) = match expected.as_adt() {
+                        Some((adt, subst)) if adt == box_adt => {
+                            (subst[0].clone(), subst.get(1).cloned())
+                        }
+                        _ => (self.result.standard_types.unknown.clone(), None),
                     };
 
-                    let inner_ty = self.infer_pat(*inner, &inner_expected, default_bm);
-                    Ty::adt_ty(box_adt, Substitution::single(inner_ty))
+                    let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm);
+                    let mut sb = Substitution::build_for_generics(&generics(
+                        self.db.upcast(),
+                        box_adt.into(),
+                    ));
+                    sb = sb.push(inner_ty);
+                    if sb.remaining() == 1 {
+                        sb = sb.push(match alloc_ty {
+                            Some(alloc_ty) if !alloc_ty.is_unknown() => alloc_ty,
+                            _ => match self.db.generic_defaults(box_adt.into()).get(1) {
+                                Some(alloc_ty) if !alloc_ty.value.is_unknown() => {
+                                    alloc_ty.value.clone()
+                                }
+                                _ => self.table.new_type_var(),
+                            },
+                        });
+                    }
+                    Ty::adt_ty(box_adt, sb.build())
                 }
                 None => self.err_ty(),
             },
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs
index 5da19ba5f01..85a28e76b23 100644
--- a/crates/hir_ty/src/tests/patterns.rs
+++ b/crates/hir_ty/src/tests/patterns.rs
@@ -656,6 +656,28 @@ fn slice_tail_pattern() {
 
 #[test]
 fn box_pattern() {
+    check_infer(
+        r#"
+        pub struct Global;
+        #[lang = "owned_box"]
+        pub struct Box<T, A = Global>(T);
+
+        fn foo(params: Box<i32>) {
+            match params {
+                box integer => {}
+            }
+        }
+        "#,
+        expect![[r#"
+            83..89 'params': Box<i32, Global>
+            101..155 '{     ...   } }': ()
+            107..153 'match ...     }': ()
+            113..119 'params': Box<i32, Global>
+            130..141 'box integer': Box<i32, Global>
+            134..141 'integer': i32
+            145..147 '{}': ()
+        "#]],
+    );
     check_infer(
         r#"
         #[lang = "owned_box"]