From f86fe3d891ab295e9e394a1338da86524a6205d3 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 5 Dec 2019 23:02:31 +0100 Subject: 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. --- crates/ra_hir_ty/src/infer/expr.rs | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'crates/ra_hir_ty/src/infer') 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> { } Expr::Return { expr } => { if let Some(expr) = expr { - self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone())); + self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone())); } Ty::simple(TypeCtor::Never) } @@ -245,7 +245,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty } Expr::Field { expr, name } => { - let receiver_ty = self.infer_expr(*expr, &Expectation::none()); + let receiver_ty = self.infer_expr_inner(*expr, &Expectation::none()); let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); let ty = autoderef::autoderef( self.db, @@ -280,7 +280,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.normalize_associated_types_in(ty) } Expr::Await { expr } => { - let inner_ty = self.infer_expr(*expr, &Expectation::none()); + let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); let ty = match self.resolve_future_future_output() { Some(future_future_output_alias) => { let ty = self.table.new_type_var(); @@ -299,7 +299,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty } Expr::Try { expr } => { - let inner_ty = self.infer_expr(*expr, &Expectation::none()); + let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); let ty = match self.resolve_ops_try_ok() { Some(ops_try_ok_alias) => { let ty = self.table.new_type_var(); @@ -318,7 +318,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty } Expr::Cast { expr, type_ref } => { - let _inner_ty = self.infer_expr(*expr, &Expectation::none()); + let _inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); let cast_ty = self.make_ty(type_ref); // FIXME check the cast... cast_ty @@ -334,12 +334,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } else { Expectation::none() }; - // FIXME reference coercions etc. - let inner_ty = self.infer_expr(*expr, &expectation); + let inner_ty = self.infer_expr_inner(*expr, &expectation); Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) } Expr::Box { expr } => { - let inner_ty = self.infer_expr(*expr, &Expectation::none()); + let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); if let Some(box_) = self.resolve_boxed_box() { Ty::apply_one(TypeCtor::Adt(box_), inner_ty) } else { @@ -347,7 +346,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } } Expr::UnaryOp { expr, op } => { - let inner_ty = self.infer_expr(*expr, &Expectation::none()); + let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); match op { UnaryOp::Deref => match self.resolver.krate() { Some(krate) => { @@ -417,7 +416,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { _ => Ty::Unknown, }, Expr::Range { lhs, rhs, range_type } => { - let lhs_ty = lhs.map(|e| self.infer_expr(e, &Expectation::none())); + let lhs_ty = lhs.map(|e| self.infer_expr_inner(e, &Expectation::none())); let rhs_expect = lhs_ty .as_ref() .map_or_else(Expectation::none, |ty| Expectation::has_type(ty.clone())); @@ -455,7 +454,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } } Expr::Index { base, index } => { - let _base_ty = self.infer_expr(*base, &Expectation::none()); + let _base_ty = self.infer_expr_inner(*base, &Expectation::none()); let _index_ty = self.infer_expr(*index, &Expectation::none()); // FIXME: use `std::ops::Index::Output` to figure out the real return type Ty::Unknown -- cgit v1.2.3