aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/infer/pat.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/infer/pat.rs')
-rw-r--r--crates/hir_ty/src/infer/pat.rs50
1 files changed, 25 insertions, 25 deletions
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index 252ae914a..aea354cde 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -7,14 +7,13 @@ use chalk_ir::Mutability;
7use hir_def::{ 7use hir_def::{
8 expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, 8 expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat},
9 path::Path, 9 path::Path,
10 FieldId,
11}; 10};
12use hir_expand::name::Name; 11use hir_expand::name::Name;
13 12
14use super::{BindingMode, Expectation, InferenceContext}; 13use super::{BindingMode, Expectation, InferenceContext};
15use crate::{ 14use crate::{
16 lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyBuilder, 15 lower::lower_to_chalk_mutability, static_lifetime, Interner, Substitution, Ty, TyBuilder,
17 TyKind, 16 TyExt, TyKind,
18}; 17};
19 18
20impl<'a> InferenceContext<'a> { 19impl<'a> InferenceContext<'a> {
@@ -28,13 +27,14 @@ impl<'a> InferenceContext<'a> {
28 ellipsis: Option<usize>, 27 ellipsis: Option<usize>,
29 ) -> Ty { 28 ) -> Ty {
30 let (ty, def) = self.resolve_variant(path); 29 let (ty, def) = self.resolve_variant(path);
31 let var_data = def.map(|it| variant_data(self.db.upcast(), it)); 30 let var_data = def.map(|it| it.variant_data(self.db.upcast()));
32 if let Some(variant) = def { 31 if let Some(variant) = def {
33 self.write_variant_resolution(id.into(), variant); 32 self.write_variant_resolution(id.into(), variant);
34 } 33 }
35 self.unify(&ty, expected); 34 self.unify(&ty, expected);
36 35
37 let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); 36 let substs =
37 ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(&Interner));
38 38
39 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); 39 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
40 let (pre, post) = match ellipsis { 40 let (pre, post) = match ellipsis {
@@ -68,23 +68,19 @@ impl<'a> InferenceContext<'a> {
68 id: PatId, 68 id: PatId,
69 ) -> Ty { 69 ) -> Ty {
70 let (ty, def) = self.resolve_variant(path); 70 let (ty, def) = self.resolve_variant(path);
71 let var_data = def.map(|it| variant_data(self.db.upcast(), it)); 71 let var_data = def.map(|it| it.variant_data(self.db.upcast()));
72 if let Some(variant) = def { 72 if let Some(variant) = def {
73 self.write_variant_resolution(id.into(), variant); 73 self.write_variant_resolution(id.into(), variant);
74 } 74 }
75 75
76 self.unify(&ty, expected); 76 self.unify(&ty, expected);
77 77
78 let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); 78 let substs =
79 ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(&Interner));
79 80
80 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); 81 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
81 for subpat in subpats { 82 for subpat in subpats {
82 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); 83 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name));
83 if let Some(local_id) = matching_field {
84 let field_def = FieldId { parent: def.unwrap(), local_id };
85 self.result.record_pat_field_resolutions.insert(subpat.pat, field_def);
86 }
87
88 let expected_ty = matching_field.map_or(self.err_ty(), |field| { 84 let expected_ty = matching_field.map_or(self.err_ty(), |field| {
89 field_tys[field].clone().substitute(&Interner, &substs) 85 field_tys[field].clone().substitute(&Interner, &substs)
90 }); 86 });
@@ -104,7 +100,7 @@ impl<'a> InferenceContext<'a> {
104 let body = Arc::clone(&self.body); // avoid borrow checker problem 100 let body = Arc::clone(&self.body); // avoid borrow checker problem
105 101
106 if is_non_ref_pat(&body, pat) { 102 if is_non_ref_pat(&body, pat) {
107 while let Some((inner, mutability)) = expected.as_reference() { 103 while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
108 expected = inner; 104 expected = inner;
109 default_bm = match default_bm { 105 default_bm = match default_bm {
110 BindingMode::Move => BindingMode::Ref(mutability), 106 BindingMode::Move => BindingMode::Ref(mutability),
@@ -126,7 +122,7 @@ impl<'a> InferenceContext<'a> {
126 let ty = match &body[pat] { 122 let ty = match &body[pat] {
127 &Pat::Tuple { ref args, ellipsis } => { 123 &Pat::Tuple { ref args, ellipsis } => {
128 let expectations = match expected.as_tuple() { 124 let expectations = match expected.as_tuple() {
129 Some(parameters) => &*parameters.interned(), 125 Some(parameters) => &*parameters.as_slice(&Interner),
130 _ => &[], 126 _ => &[],
131 }; 127 };
132 128
@@ -162,7 +158,7 @@ impl<'a> InferenceContext<'a> {
162 Pat::Ref { pat, mutability } => { 158 Pat::Ref { pat, mutability } => {
163 let mutability = lower_to_chalk_mutability(*mutability); 159 let mutability = lower_to_chalk_mutability(*mutability);
164 let expectation = match expected.as_reference() { 160 let expectation = match expected.as_reference() {
165 Some((inner_ty, exp_mut)) => { 161 Some((inner_ty, _lifetime, exp_mut)) => {
166 if mutability != exp_mut { 162 if mutability != exp_mut {
167 // FIXME: emit type error? 163 // FIXME: emit type error?
168 } 164 }
@@ -171,10 +167,10 @@ impl<'a> InferenceContext<'a> {
171 _ => self.result.standard_types.unknown.clone(), 167 _ => self.result.standard_types.unknown.clone(),
172 }; 168 };
173 let subty = self.infer_pat(*pat, &expectation, default_bm); 169 let subty = self.infer_pat(*pat, &expectation, default_bm);
174 TyKind::Ref(mutability, subty).intern(&Interner) 170 TyKind::Ref(mutability, static_lifetime(), subty).intern(&Interner)
175 } 171 }
176 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( 172 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
177 p.as_ref(), 173 p.as_deref(),
178 subpats, 174 subpats,
179 expected, 175 expected,
180 default_bm, 176 default_bm,
@@ -182,7 +178,7 @@ impl<'a> InferenceContext<'a> {
182 *ellipsis, 178 *ellipsis,
183 ), 179 ),
184 Pat::Record { path: p, args: fields, ellipsis: _ } => { 180 Pat::Record { path: p, args: fields, ellipsis: _ } => {
185 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) 181 self.infer_record_pat(p.as_deref(), fields, expected, default_bm, pat)
186 } 182 }
187 Pat::Path(path) => { 183 Pat::Path(path) => {
188 // FIXME use correct resolver for the surrounding expression 184 // FIXME use correct resolver for the surrounding expression
@@ -204,7 +200,8 @@ impl<'a> InferenceContext<'a> {
204 200
205 let bound_ty = match mode { 201 let bound_ty = match mode {
206 BindingMode::Ref(mutability) => { 202 BindingMode::Ref(mutability) => {
207 TyKind::Ref(mutability, inner_ty.clone()).intern(&Interner) 203 TyKind::Ref(mutability, static_lifetime(), inner_ty.clone())
204 .intern(&Interner)
208 } 205 }
209 BindingMode::Move => inner_ty.clone(), 206 BindingMode::Move => inner_ty.clone(),
210 }; 207 };
@@ -213,17 +210,20 @@ impl<'a> InferenceContext<'a> {
213 return inner_ty; 210 return inner_ty;
214 } 211 }
215 Pat::Slice { prefix, slice, suffix } => { 212 Pat::Slice { prefix, slice, suffix } => {
216 let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.kind(&Interner) { 213 let elem_ty = match expected.kind(&Interner) {
217 TyKind::Array(st) => (TyKind::Array, st.clone()), 214 TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
218 TyKind::Slice(st) => (TyKind::Slice, st.clone()), 215 _ => self.err_ty(),
219 _ => (TyKind::Slice, self.err_ty()),
220 }; 216 };
221 217
222 for pat_id in prefix.iter().chain(suffix) { 218 for pat_id in prefix.iter().chain(suffix) {
223 self.infer_pat(*pat_id, &elem_ty, default_bm); 219 self.infer_pat(*pat_id, &elem_ty, default_bm);
224 } 220 }
225 221
226 let pat_ty = container_ty(elem_ty).intern(&Interner); 222 let pat_ty = match expected.kind(&Interner) {
223 TyKind::Array(_, const_) => TyKind::Array(elem_ty, const_.clone()),
224 _ => TyKind::Slice(elem_ty),
225 }
226 .intern(&Interner);
227 if let Some(slice_pat_id) = slice { 227 if let Some(slice_pat_id) = slice {
228 self.infer_pat(*slice_pat_id, &pat_ty, default_bm); 228 self.infer_pat(*slice_pat_id, &pat_ty, default_bm);
229 } 229 }
@@ -242,7 +242,7 @@ impl<'a> InferenceContext<'a> {
242 let (inner_ty, alloc_ty) = match expected.as_adt() { 242 let (inner_ty, alloc_ty) = match expected.as_adt() {
243 Some((adt, subst)) if adt == box_adt => ( 243 Some((adt, subst)) if adt == box_adt => (
244 subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), 244 subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(),
245 subst.interned().get(1).and_then(|a| a.ty(&Interner).cloned()), 245 subst.as_slice(&Interner).get(1).and_then(|a| a.ty(&Interner).cloned()),
246 ), 246 ),
247 _ => (self.result.standard_types.unknown.clone(), None), 247 _ => (self.result.standard_types.unknown.clone(), None),
248 }; 248 };