diff options
Diffstat (limited to 'crates/ra_hir_ty/src/infer')
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 61 |
1 files changed, 40 insertions, 21 deletions
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 54bab3476..4a98e2deb 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -22,8 +22,8 @@ use crate::{ | |||
22 | }; | 22 | }; |
23 | 23 | ||
24 | use super::{ | 24 | use super::{ |
25 | BindingMode, BreakableContext, Diverges, Expectation, InferenceContext, InferenceDiagnostic, | 25 | find_breakable, BindingMode, BreakableContext, Diverges, Expectation, InferenceContext, |
26 | TypeMismatch, | 26 | InferenceDiagnostic, TypeMismatch, |
27 | }; | 27 | }; |
28 | 28 | ||
29 | impl<'a> InferenceContext<'a> { | 29 | impl<'a> InferenceContext<'a> { |
@@ -86,16 +86,20 @@ impl<'a> InferenceContext<'a> { | |||
86 | 86 | ||
87 | self.coerce_merge_branch(&then_ty, &else_ty) | 87 | self.coerce_merge_branch(&then_ty, &else_ty) |
88 | } | 88 | } |
89 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), | 89 | Expr::Block { statements, tail, .. } => { |
90 | // FIXME: Breakable block inference | ||
91 | self.infer_block(statements, *tail, expected) | ||
92 | } | ||
90 | Expr::TryBlock { body } => { | 93 | Expr::TryBlock { body } => { |
91 | let _inner = self.infer_expr(*body, expected); | 94 | let _inner = self.infer_expr(*body, expected); |
92 | // FIXME should be std::result::Result<{inner}, _> | 95 | // FIXME should be std::result::Result<{inner}, _> |
93 | Ty::Unknown | 96 | Ty::Unknown |
94 | } | 97 | } |
95 | Expr::Loop { body } => { | 98 | Expr::Loop { body, label } => { |
96 | self.breakables.push(BreakableContext { | 99 | self.breakables.push(BreakableContext { |
97 | may_break: false, | 100 | may_break: false, |
98 | break_ty: self.table.new_type_var(), | 101 | break_ty: self.table.new_type_var(), |
102 | label: label.clone(), | ||
99 | }); | 103 | }); |
100 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 104 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
101 | 105 | ||
@@ -110,8 +114,12 @@ impl<'a> InferenceContext<'a> { | |||
110 | Ty::simple(TypeCtor::Never) | 114 | Ty::simple(TypeCtor::Never) |
111 | } | 115 | } |
112 | } | 116 | } |
113 | Expr::While { condition, body } => { | 117 | Expr::While { condition, body, label } => { |
114 | self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown }); | 118 | self.breakables.push(BreakableContext { |
119 | may_break: false, | ||
120 | break_ty: Ty::Unknown, | ||
121 | label: label.clone(), | ||
122 | }); | ||
115 | // while let is desugared to a match loop, so this is always simple while | 123 | // while let is desugared to a match loop, so this is always simple while |
116 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); | 124 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); |
117 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 125 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
@@ -120,10 +128,14 @@ impl<'a> InferenceContext<'a> { | |||
120 | self.diverges = Diverges::Maybe; | 128 | self.diverges = Diverges::Maybe; |
121 | Ty::unit() | 129 | Ty::unit() |
122 | } | 130 | } |
123 | Expr::For { iterable, body, pat } => { | 131 | Expr::For { iterable, body, pat, label } => { |
124 | let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); | 132 | let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); |
125 | 133 | ||
126 | self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown }); | 134 | self.breakables.push(BreakableContext { |
135 | may_break: false, | ||
136 | break_ty: Ty::Unknown, | ||
137 | label: label.clone(), | ||
138 | }); | ||
127 | let pat_ty = | 139 | let pat_ty = |
128 | self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); | 140 | self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); |
129 | 141 | ||
@@ -140,13 +152,13 @@ impl<'a> InferenceContext<'a> { | |||
140 | 152 | ||
141 | let mut sig_tys = Vec::new(); | 153 | let mut sig_tys = Vec::new(); |
142 | 154 | ||
143 | for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { | 155 | // collect explicitly written argument types |
144 | let expected = if let Some(type_ref) = arg_type { | 156 | for arg_type in arg_types.iter() { |
157 | let arg_ty = if let Some(type_ref) = arg_type { | ||
145 | self.make_ty(type_ref) | 158 | self.make_ty(type_ref) |
146 | } else { | 159 | } else { |
147 | Ty::Unknown | 160 | self.table.new_type_var() |
148 | }; | 161 | }; |
149 | let arg_ty = self.infer_pat(*arg_pat, &expected, BindingMode::default()); | ||
150 | sig_tys.push(arg_ty); | 162 | sig_tys.push(arg_ty); |
151 | } | 163 | } |
152 | 164 | ||
@@ -158,7 +170,7 @@ impl<'a> InferenceContext<'a> { | |||
158 | sig_tys.push(ret_ty.clone()); | 170 | sig_tys.push(ret_ty.clone()); |
159 | let sig_ty = Ty::apply( | 171 | let sig_ty = Ty::apply( |
160 | TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, | 172 | TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, |
161 | Substs(sig_tys.into()), | 173 | Substs(sig_tys.clone().into()), |
162 | ); | 174 | ); |
163 | let closure_ty = | 175 | let closure_ty = |
164 | Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); | 176 | Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); |
@@ -168,6 +180,12 @@ impl<'a> InferenceContext<'a> { | |||
168 | // infer the body. | 180 | // infer the body. |
169 | self.coerce(&closure_ty, &expected.ty); | 181 | self.coerce(&closure_ty, &expected.ty); |
170 | 182 | ||
183 | // Now go through the argument patterns | ||
184 | for (arg_pat, arg_ty) in args.iter().zip(sig_tys) { | ||
185 | let resolved = self.resolve_ty_as_possible(arg_ty); | ||
186 | self.infer_pat(*arg_pat, &resolved, BindingMode::default()); | ||
187 | } | ||
188 | |||
171 | let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); | 189 | let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); |
172 | let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); | 190 | let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); |
173 | 191 | ||
@@ -230,23 +248,24 @@ impl<'a> InferenceContext<'a> { | |||
230 | let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); | 248 | let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); |
231 | self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) | 249 | self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) |
232 | } | 250 | } |
233 | Expr::Continue => Ty::simple(TypeCtor::Never), | 251 | Expr::Continue { .. } => Ty::simple(TypeCtor::Never), |
234 | Expr::Break { expr } => { | 252 | Expr::Break { expr, label } => { |
235 | let val_ty = if let Some(expr) = expr { | 253 | let val_ty = if let Some(expr) = expr { |
236 | self.infer_expr(*expr, &Expectation::none()) | 254 | self.infer_expr(*expr, &Expectation::none()) |
237 | } else { | 255 | } else { |
238 | Ty::unit() | 256 | Ty::unit() |
239 | }; | 257 | }; |
240 | 258 | ||
241 | let last_ty = if let Some(ctxt) = self.breakables.last() { | 259 | let last_ty = |
242 | ctxt.break_ty.clone() | 260 | if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { |
243 | } else { | 261 | ctxt.break_ty.clone() |
244 | Ty::Unknown | 262 | } else { |
245 | }; | 263 | Ty::Unknown |
264 | }; | ||
246 | 265 | ||
247 | let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); | 266 | let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); |
248 | 267 | ||
249 | if let Some(ctxt) = self.breakables.last_mut() { | 268 | if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { |
250 | ctxt.break_ty = merged_type; | 269 | ctxt.break_ty = merged_type; |
251 | ctxt.may_break = true; | 270 | ctxt.may_break = true; |
252 | } else { | 271 | } else { |