diff options
author | Florian Diebold <[email protected]> | 2019-12-05 22:02:31 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-12-06 14:15:26 +0000 |
commit | f86fe3d891ab295e9e394a1338da86524a6205d3 (patch) | |
tree | 891cf4be4893c79598800928e7c0b669d9d2a9c2 /crates/ra_hir_ty/src/infer | |
parent | d2b210a02e3e8ee1cf38909411fa8945aec99f4e (diff) |
Don't unify within a reference
If we are expecting a `&Foo` and get a `&something`, when checking the
`something`, we are *expecting* a `Foo`, but we shouldn't try to unify whatever
we get with that expectation, because it could actually be a `&Foo`, and `&&Foo`
coerces to `&Foo`. So this fixes quite a few false type mismatches.
Diffstat (limited to 'crates/ra_hir_ty/src/infer')
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 21 |
1 files changed, 10 insertions, 11 deletions
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 1e78f6efd..b8df27706 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -201,7 +201,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
201 | } | 201 | } |
202 | Expr::Return { expr } => { | 202 | Expr::Return { expr } => { |
203 | if let Some(expr) = expr { | 203 | if let Some(expr) = expr { |
204 | self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone())); | 204 | self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone())); |
205 | } | 205 | } |
206 | Ty::simple(TypeCtor::Never) | 206 | Ty::simple(TypeCtor::Never) |
207 | } | 207 | } |
@@ -245,7 +245,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
245 | ty | 245 | ty |
246 | } | 246 | } |
247 | Expr::Field { expr, name } => { | 247 | Expr::Field { expr, name } => { |
248 | let receiver_ty = self.infer_expr(*expr, &Expectation::none()); | 248 | let receiver_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
249 | let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); | 249 | let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); |
250 | let ty = autoderef::autoderef( | 250 | let ty = autoderef::autoderef( |
251 | self.db, | 251 | self.db, |
@@ -280,7 +280,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
280 | self.normalize_associated_types_in(ty) | 280 | self.normalize_associated_types_in(ty) |
281 | } | 281 | } |
282 | Expr::Await { expr } => { | 282 | Expr::Await { expr } => { |
283 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 283 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
284 | let ty = match self.resolve_future_future_output() { | 284 | let ty = match self.resolve_future_future_output() { |
285 | Some(future_future_output_alias) => { | 285 | Some(future_future_output_alias) => { |
286 | let ty = self.table.new_type_var(); | 286 | let ty = self.table.new_type_var(); |
@@ -299,7 +299,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
299 | ty | 299 | ty |
300 | } | 300 | } |
301 | Expr::Try { expr } => { | 301 | Expr::Try { expr } => { |
302 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 302 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
303 | let ty = match self.resolve_ops_try_ok() { | 303 | let ty = match self.resolve_ops_try_ok() { |
304 | Some(ops_try_ok_alias) => { | 304 | Some(ops_try_ok_alias) => { |
305 | let ty = self.table.new_type_var(); | 305 | let ty = self.table.new_type_var(); |
@@ -318,7 +318,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
318 | ty | 318 | ty |
319 | } | 319 | } |
320 | Expr::Cast { expr, type_ref } => { | 320 | Expr::Cast { expr, type_ref } => { |
321 | let _inner_ty = self.infer_expr(*expr, &Expectation::none()); | 321 | let _inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
322 | let cast_ty = self.make_ty(type_ref); | 322 | let cast_ty = self.make_ty(type_ref); |
323 | // FIXME check the cast... | 323 | // FIXME check the cast... |
324 | cast_ty | 324 | cast_ty |
@@ -334,12 +334,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
334 | } else { | 334 | } else { |
335 | Expectation::none() | 335 | Expectation::none() |
336 | }; | 336 | }; |
337 | // FIXME reference coercions etc. | 337 | let inner_ty = self.infer_expr_inner(*expr, &expectation); |
338 | let inner_ty = self.infer_expr(*expr, &expectation); | ||
339 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) | 338 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) |
340 | } | 339 | } |
341 | Expr::Box { expr } => { | 340 | Expr::Box { expr } => { |
342 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 341 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
343 | if let Some(box_) = self.resolve_boxed_box() { | 342 | if let Some(box_) = self.resolve_boxed_box() { |
344 | Ty::apply_one(TypeCtor::Adt(box_), inner_ty) | 343 | Ty::apply_one(TypeCtor::Adt(box_), inner_ty) |
345 | } else { | 344 | } else { |
@@ -347,7 +346,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
347 | } | 346 | } |
348 | } | 347 | } |
349 | Expr::UnaryOp { expr, op } => { | 348 | Expr::UnaryOp { expr, op } => { |
350 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 349 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
351 | match op { | 350 | match op { |
352 | UnaryOp::Deref => match self.resolver.krate() { | 351 | UnaryOp::Deref => match self.resolver.krate() { |
353 | Some(krate) => { | 352 | Some(krate) => { |
@@ -417,7 +416,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
417 | _ => Ty::Unknown, | 416 | _ => Ty::Unknown, |
418 | }, | 417 | }, |
419 | Expr::Range { lhs, rhs, range_type } => { | 418 | Expr::Range { lhs, rhs, range_type } => { |
420 | let lhs_ty = lhs.map(|e| self.infer_expr(e, &Expectation::none())); | 419 | let lhs_ty = lhs.map(|e| self.infer_expr_inner(e, &Expectation::none())); |
421 | let rhs_expect = lhs_ty | 420 | let rhs_expect = lhs_ty |
422 | .as_ref() | 421 | .as_ref() |
423 | .map_or_else(Expectation::none, |ty| Expectation::has_type(ty.clone())); | 422 | .map_or_else(Expectation::none, |ty| Expectation::has_type(ty.clone())); |
@@ -455,7 +454,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
455 | } | 454 | } |
456 | } | 455 | } |
457 | Expr::Index { base, index } => { | 456 | Expr::Index { base, index } => { |
458 | let _base_ty = self.infer_expr(*base, &Expectation::none()); | 457 | let _base_ty = self.infer_expr_inner(*base, &Expectation::none()); |
459 | let _index_ty = self.infer_expr(*index, &Expectation::none()); | 458 | let _index_ty = self.infer_expr(*index, &Expectation::none()); |
460 | // FIXME: use `std::ops::Index::Output` to figure out the real return type | 459 | // FIXME: use `std::ops::Index::Output` to figure out the real return type |
461 | Ty::Unknown | 460 | Ty::Unknown |