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 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 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 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 @@ pub(super) fn infer_pat( 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 foo(params: &[i32]) { #[test] fn box_pattern() { + check_infer( + r#" + pub struct Global; + #[lang = "owned_box"] + pub struct Box(T); + + fn foo(params: Box) { + match params { + box integer => {} + } + } + "#, + expect![[r#" + 83..89 'params': Box + 101..155 '{ ... } }': () + 107..153 'match ... }': () + 113..119 'params': Box + 130..141 'box integer': Box + 134..141 'integer': i32 + 145..147 '{}': () + "#]], + ); check_infer( r#" #[lang = "owned_box"]