diff options
Diffstat (limited to 'crates/hir_ty/src/infer/pat.rs')
-rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index befa0d69b..474363709 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; | |||
13 | 13 | ||
14 | use super::{BindingMode, Expectation, InferenceContext}; | 14 | use super::{BindingMode, Expectation, InferenceContext}; |
15 | use crate::{ | 15 | use crate::{ |
16 | lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyKind, | 16 | lower::lower_to_chalk_mutability, |
17 | utils::{generics, variant_data}, | ||
18 | Interner, Substitution, Ty, TyKind, | ||
17 | }; | 19 | }; |
18 | 20 | ||
19 | impl<'a> InferenceContext<'a> { | 21 | impl<'a> InferenceContext<'a> { |
@@ -38,7 +40,7 @@ impl<'a> InferenceContext<'a> { | |||
38 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); | 40 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); |
39 | let (pre, post) = match ellipsis { | 41 | let (pre, post) = match ellipsis { |
40 | Some(idx) => subpats.split_at(idx), | 42 | Some(idx) => subpats.split_at(idx), |
41 | None => (&subpats[..], &[][..]), | 43 | None => (subpats, &[][..]), |
42 | }; | 44 | }; |
43 | let post_idx_offset = field_tys.iter().count() - post.len(); | 45 | let post_idx_offset = field_tys.iter().count() - post.len(); |
44 | 46 | ||
@@ -233,13 +235,31 @@ impl<'a> InferenceContext<'a> { | |||
233 | Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), | 235 | Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), |
234 | Pat::Box { inner } => match self.resolve_boxed_box() { | 236 | Pat::Box { inner } => match self.resolve_boxed_box() { |
235 | Some(box_adt) => { | 237 | Some(box_adt) => { |
236 | let inner_expected = match expected.as_adt() { | 238 | let (inner_ty, alloc_ty) = match expected.as_adt() { |
237 | Some((adt, substs)) if adt == box_adt => substs.as_single().clone(), | 239 | Some((adt, subst)) if adt == box_adt => { |
238 | _ => self.result.standard_types.unknown.clone(), | 240 | (subst[0].clone(), subst.get(1).cloned()) |
241 | } | ||
242 | _ => (self.result.standard_types.unknown.clone(), None), | ||
239 | }; | 243 | }; |
240 | 244 | ||
241 | let inner_ty = self.infer_pat(*inner, &inner_expected, default_bm); | 245 | let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm); |
242 | Ty::adt_ty(box_adt, Substitution::single(inner_ty)) | 246 | let mut sb = Substitution::build_for_generics(&generics( |
247 | self.db.upcast(), | ||
248 | box_adt.into(), | ||
249 | )); | ||
250 | sb = sb.push(inner_ty); | ||
251 | if sb.remaining() == 1 { | ||
252 | sb = sb.push(match alloc_ty { | ||
253 | Some(alloc_ty) if !alloc_ty.is_unknown() => alloc_ty, | ||
254 | _ => match self.db.generic_defaults(box_adt.into()).get(1) { | ||
255 | Some(alloc_ty) if !alloc_ty.value.is_unknown() => { | ||
256 | alloc_ty.value.clone() | ||
257 | } | ||
258 | _ => self.table.new_type_var(), | ||
259 | }, | ||
260 | }); | ||
261 | } | ||
262 | Ty::adt_ty(box_adt, sb.build()) | ||
243 | } | 263 | } |
244 | None => self.err_ty(), | 264 | None => self.err_ty(), |
245 | }, | 265 | }, |