diff options
Diffstat (limited to 'crates/hir_ty/src/infer/pat.rs')
-rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 37 |
1 files changed, 17 insertions, 20 deletions
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index d974f805b..a0ac8d80f 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -3,17 +3,16 @@ | |||
3 | use std::iter::repeat; | 3 | use std::iter::repeat; |
4 | use std::sync::Arc; | 4 | use std::sync::Arc; |
5 | 5 | ||
6 | use chalk_ir::Mutability; | ||
6 | use hir_def::{ | 7 | use hir_def::{ |
7 | expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, | 8 | expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, |
8 | path::Path, | 9 | path::Path, |
9 | type_ref::Mutability, | ||
10 | FieldId, | 10 | FieldId, |
11 | }; | 11 | }; |
12 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
13 | use test_utils::mark; | ||
14 | 13 | ||
15 | use super::{BindingMode, Expectation, InferenceContext}; | 14 | use super::{BindingMode, Expectation, InferenceContext}; |
16 | use crate::{utils::variant_data, Substs, Ty, TypeCtor}; | 15 | use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Substs, Ty}; |
17 | 16 | ||
18 | impl<'a> InferenceContext<'a> { | 17 | impl<'a> InferenceContext<'a> { |
19 | fn infer_tuple_struct_pat( | 18 | fn infer_tuple_struct_pat( |
@@ -32,7 +31,7 @@ impl<'a> InferenceContext<'a> { | |||
32 | } | 31 | } |
33 | self.unify(&ty, expected); | 32 | self.unify(&ty, expected); |
34 | 33 | ||
35 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 34 | let substs = ty.substs().cloned().unwrap_or_else(Substs::empty); |
36 | 35 | ||
37 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); | 36 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); |
38 | let (pre, post) = match ellipsis { | 37 | let (pre, post) = match ellipsis { |
@@ -71,7 +70,7 @@ impl<'a> InferenceContext<'a> { | |||
71 | 70 | ||
72 | self.unify(&ty, expected); | 71 | self.unify(&ty, expected); |
73 | 72 | ||
74 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 73 | let substs = ty.substs().cloned().unwrap_or_else(Substs::empty); |
75 | 74 | ||
76 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); | 75 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); |
77 | for subpat in subpats { | 76 | for subpat in subpats { |
@@ -103,12 +102,12 @@ impl<'a> InferenceContext<'a> { | |||
103 | expected = inner; | 102 | expected = inner; |
104 | default_bm = match default_bm { | 103 | default_bm = match default_bm { |
105 | BindingMode::Move => BindingMode::Ref(mutability), | 104 | BindingMode::Move => BindingMode::Ref(mutability), |
106 | BindingMode::Ref(Mutability::Shared) => BindingMode::Ref(Mutability::Shared), | 105 | BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not), |
107 | BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability), | 106 | BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability), |
108 | } | 107 | } |
109 | } | 108 | } |
110 | } else if let Pat::Ref { .. } = &body[pat] { | 109 | } else if let Pat::Ref { .. } = &body[pat] { |
111 | mark::hit!(match_ergonomics_ref); | 110 | cov_mark::hit!(match_ergonomics_ref); |
112 | // When you encounter a `&pat` pattern, reset to Move. | 111 | // When you encounter a `&pat` pattern, reset to Move. |
113 | // This is so that `w` is by value: `let (_, &w) = &(1, &2);` | 112 | // This is so that `w` is by value: `let (_, &w) = &(1, &2);` |
114 | default_bm = BindingMode::Move; | 113 | default_bm = BindingMode::Move; |
@@ -138,10 +137,7 @@ impl<'a> InferenceContext<'a> { | |||
138 | inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); | 137 | inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); |
139 | inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); | 138 | inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); |
140 | 139 | ||
141 | Ty::apply( | 140 | Ty::Tuple(inner_tys.len(), Substs(inner_tys.into())) |
142 | TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, | ||
143 | Substs(inner_tys.into()), | ||
144 | ) | ||
145 | } | 141 | } |
146 | Pat::Or(ref pats) => { | 142 | Pat::Or(ref pats) => { |
147 | if let Some((first_pat, rest)) = pats.split_first() { | 143 | if let Some((first_pat, rest)) = pats.split_first() { |
@@ -155,9 +151,10 @@ impl<'a> InferenceContext<'a> { | |||
155 | } | 151 | } |
156 | } | 152 | } |
157 | Pat::Ref { pat, mutability } => { | 153 | Pat::Ref { pat, mutability } => { |
154 | let mutability = lower_to_chalk_mutability(*mutability); | ||
158 | let expectation = match expected.as_reference() { | 155 | let expectation = match expected.as_reference() { |
159 | Some((inner_ty, exp_mut)) => { | 156 | Some((inner_ty, exp_mut)) => { |
160 | if *mutability != exp_mut { | 157 | if mutability != exp_mut { |
161 | // FIXME: emit type error? | 158 | // FIXME: emit type error? |
162 | } | 159 | } |
163 | inner_ty | 160 | inner_ty |
@@ -165,7 +162,7 @@ impl<'a> InferenceContext<'a> { | |||
165 | _ => &Ty::Unknown, | 162 | _ => &Ty::Unknown, |
166 | }; | 163 | }; |
167 | let subty = self.infer_pat(*pat, expectation, default_bm); | 164 | let subty = self.infer_pat(*pat, expectation, default_bm); |
168 | Ty::apply_one(TypeCtor::Ref(*mutability), subty) | 165 | Ty::Ref(mutability, Substs::single(subty)) |
169 | } | 166 | } |
170 | Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( | 167 | Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( |
171 | p.as_ref(), | 168 | p.as_ref(), |
@@ -198,7 +195,7 @@ impl<'a> InferenceContext<'a> { | |||
198 | 195 | ||
199 | let bound_ty = match mode { | 196 | let bound_ty = match mode { |
200 | BindingMode::Ref(mutability) => { | 197 | BindingMode::Ref(mutability) => { |
201 | Ty::apply_one(TypeCtor::Ref(mutability), inner_ty.clone()) | 198 | Ty::Ref(mutability, Substs::single(inner_ty.clone())) |
202 | } | 199 | } |
203 | BindingMode::Move => inner_ty.clone(), | 200 | BindingMode::Move => inner_ty.clone(), |
204 | }; | 201 | }; |
@@ -207,17 +204,17 @@ impl<'a> InferenceContext<'a> { | |||
207 | return inner_ty; | 204 | return inner_ty; |
208 | } | 205 | } |
209 | Pat::Slice { prefix, slice, suffix } => { | 206 | Pat::Slice { prefix, slice, suffix } => { |
210 | let (container_ty, elem_ty) = match &expected { | 207 | let (container_ty, elem_ty): (fn(_) -> _, _) = match &expected { |
211 | ty_app!(TypeCtor::Array, st) => (TypeCtor::Array, st.as_single().clone()), | 208 | Ty::Array(st) => (Ty::Array, st.as_single().clone()), |
212 | ty_app!(TypeCtor::Slice, st) => (TypeCtor::Slice, st.as_single().clone()), | 209 | Ty::Slice(st) => (Ty::Slice, st.as_single().clone()), |
213 | _ => (TypeCtor::Slice, Ty::Unknown), | 210 | _ => (Ty::Slice, Ty::Unknown), |
214 | }; | 211 | }; |
215 | 212 | ||
216 | for pat_id in prefix.iter().chain(suffix) { | 213 | for pat_id in prefix.iter().chain(suffix) { |
217 | self.infer_pat(*pat_id, &elem_ty, default_bm); | 214 | self.infer_pat(*pat_id, &elem_ty, default_bm); |
218 | } | 215 | } |
219 | 216 | ||
220 | let pat_ty = Ty::apply_one(container_ty, elem_ty); | 217 | let pat_ty = container_ty(Substs::single(elem_ty)); |
221 | if let Some(slice_pat_id) = slice { | 218 | if let Some(slice_pat_id) = slice { |
222 | self.infer_pat(*slice_pat_id, &pat_ty, default_bm); | 219 | self.infer_pat(*slice_pat_id, &pat_ty, default_bm); |
223 | } | 220 | } |
@@ -239,7 +236,7 @@ impl<'a> InferenceContext<'a> { | |||
239 | }; | 236 | }; |
240 | 237 | ||
241 | let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); | 238 | let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); |
242 | Ty::apply_one(TypeCtor::Adt(box_adt), inner_ty) | 239 | Ty::adt_ty(box_adt, Substs::single(inner_ty)) |
243 | } | 240 | } |
244 | None => Ty::Unknown, | 241 | None => Ty::Unknown, |
245 | }, | 242 | }, |