aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/infer
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/infer')
-rw-r--r--crates/ra_hir_ty/src/infer/coerce.rs4
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs98
2 files changed, 64 insertions, 38 deletions
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs
index 2ee9adb16..32c7c57cd 100644
--- a/crates/ra_hir_ty/src/infer/coerce.rs
+++ b/crates/ra_hir_ty/src/infer/coerce.rs
@@ -45,9 +45,7 @@ impl<'a> InferenceContext<'a> {
45 self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) 45 self.coerce_merge_branch(&ptr_ty1, &ptr_ty2)
46 } else { 46 } else {
47 mark::hit!(coerce_merge_fail_fallback); 47 mark::hit!(coerce_merge_fail_fallback);
48 // For incompatible types, we use the latter one as result 48 ty1.clone()
49 // to be better recovery for `if` without `else`.
50 ty2.clone()
51 } 49 }
52 } 50 }
53 } 51 }
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index b28724f0e..4a98e2deb 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -17,13 +17,13 @@ use crate::{
17 autoderef, method_resolution, op, 17 autoderef, method_resolution, op,
18 traits::InEnvironment, 18 traits::InEnvironment,
19 utils::{generics, variant_data, Generics}, 19 utils::{generics, variant_data, Generics},
20 ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, 20 ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs,
21 Ty, TypeCtor, Uncertain, 21 TraitRef, Ty, TypeCtor, Uncertain,
22}; 22};
23 23
24use super::{ 24use 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
29impl<'a> InferenceContext<'a> { 29impl<'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 {
@@ -350,19 +369,28 @@ impl<'a> InferenceContext<'a> {
350 // FIXME check the cast... 369 // FIXME check the cast...
351 cast_ty 370 cast_ty
352 } 371 }
353 Expr::Ref { expr, mutability } => { 372 Expr::Ref { expr, rawness, mutability } => {
354 let expectation = 373 let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) =
355 if let Some((exp_inner, exp_mutability)) = &expected.ty.as_reference() { 374 &expected.ty.as_reference_or_ptr()
356 if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { 375 {
357 // FIXME: throw type error - expected mut reference but found shared ref, 376 if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared {
358 // which cannot be coerced 377 // FIXME: throw type error - expected mut reference but found shared ref,
359 } 378 // which cannot be coerced
360 Expectation::rvalue_hint(Ty::clone(exp_inner)) 379 }
361 } else { 380 if *exp_rawness == Rawness::Ref && *rawness == Rawness::RawPtr {
362 Expectation::none() 381 // FIXME: throw type error - expected reference but found ptr,
363 }; 382 // which cannot be coerced
383 }
384 Expectation::rvalue_hint(Ty::clone(exp_inner))
385 } else {
386 Expectation::none()
387 };
364 let inner_ty = self.infer_expr_inner(*expr, &expectation); 388 let inner_ty = self.infer_expr_inner(*expr, &expectation);
365 Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) 389 let ty = match rawness {
390 Rawness::RawPtr => TypeCtor::RawPtr(*mutability),
391 Rawness::Ref => TypeCtor::Ref(*mutability),
392 };
393 Ty::apply_one(ty, inner_ty)
366 } 394 }
367 Expr::Box { expr } => { 395 Expr::Box { expr } => {
368 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); 396 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());