aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/infer/expr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/infer/expr.rs')
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs35
1 files changed, 25 insertions, 10 deletions
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 924ad3e81..3af05394c 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -8,7 +8,7 @@ use hir_def::{
8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
9 path::{GenericArg, GenericArgs}, 9 path::{GenericArg, GenericArgs},
10 resolver::resolver_for_expr, 10 resolver::resolver_for_expr,
11 AdtId, ContainerId, Lookup, StructFieldId, 11 AdtId, AssocContainerId, Lookup, StructFieldId,
12}; 12};
13use hir_expand::name::{name, Name}; 13use hir_expand::name::{name, Name};
14use ra_syntax::ast::RangeOp; 14use ra_syntax::ast::RangeOp;
@@ -41,7 +41,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
41 41
42 /// Infer type of expression with possibly implicit coerce to the expected type. 42 /// Infer type of expression with possibly implicit coerce to the expected type.
43 /// Return the type after possible coercion. 43 /// Return the type after possible coercion.
44 fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty { 44 pub(super) fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
45 let ty = self.infer_expr_inner(expr, &expected); 45 let ty = self.infer_expr_inner(expr, &expected);
46 let ty = if !self.coerce(&ty, &expected.ty) { 46 let ty = if !self.coerce(&ty, &expected.ty) {
47 self.result 47 self.result
@@ -102,7 +102,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
102 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 102 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
103 Ty::unit() 103 Ty::unit()
104 } 104 }
105 Expr::Lambda { body, args, arg_types } => { 105 Expr::Lambda { body, args, ret_type, arg_types } => {
106 assert_eq!(args.len(), arg_types.len()); 106 assert_eq!(args.len(), arg_types.len());
107 107
108 let mut sig_tys = Vec::new(); 108 let mut sig_tys = Vec::new();
@@ -118,7 +118,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
118 } 118 }
119 119
120 // add return type 120 // add return type
121 let ret_ty = self.table.new_type_var(); 121 let ret_ty = match ret_type {
122 Some(type_ref) => self.make_ty(type_ref),
123 None => self.table.new_type_var(),
124 };
122 sig_tys.push(ret_ty.clone()); 125 sig_tys.push(ret_ty.clone());
123 let sig_ty = Ty::apply( 126 let sig_ty = Ty::apply(
124 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, 127 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
@@ -134,7 +137,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
134 // infer the body. 137 // infer the body.
135 self.coerce(&closure_ty, &expected.ty); 138 self.coerce(&closure_ty, &expected.ty);
136 139
137 self.infer_expr(*body, &Expectation::has_type(ret_ty)); 140 let prev_ret_ty = std::mem::replace(&mut self.return_ty, ret_ty.clone());
141
142 self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
143
144 self.return_ty = prev_ret_ty;
145
138 closure_ty 146 closure_ty
139 } 147 }
140 Expr::Call { callee, args } => { 148 Expr::Call { callee, args } => {
@@ -192,6 +200,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
192 Expr::Return { expr } => { 200 Expr::Return { expr } => {
193 if let Some(expr) = expr { 201 if let Some(expr) = expr {
194 self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone())); 202 self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone()));
203 } else {
204 let unit = Ty::unit();
205 self.coerce(&unit, &self.return_ty.clone());
195 } 206 }
196 Ty::simple(TypeCtor::Never) 207 Ty::simple(TypeCtor::Never)
197 } 208 }
@@ -422,10 +433,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
422 } 433 }
423 } 434 }
424 Expr::Index { base, index } => { 435 Expr::Index { base, index } => {
425 let _base_ty = self.infer_expr_inner(*base, &Expectation::none()); 436 let base_ty = self.infer_expr_inner(*base, &Expectation::none());
426 let _index_ty = self.infer_expr(*index, &Expectation::none()); 437 let index_ty = self.infer_expr(*index, &Expectation::none());
427 // FIXME: use `std::ops::Index::Output` to figure out the real return type 438
428 Ty::Unknown 439 self.resolve_associated_type_with_params(
440 base_ty,
441 self.resolve_ops_index_output(),
442 &[index_ty],
443 )
429 } 444 }
430 Expr::Tuple { exprs } => { 445 Expr::Tuple { exprs } => {
431 let mut tys = match &expected.ty { 446 let mut tys = match &expected.ty {
@@ -672,7 +687,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
672 // add obligation for trait implementation, if this is a trait method 687 // add obligation for trait implementation, if this is a trait method
673 match def { 688 match def {
674 CallableDef::FunctionId(f) => { 689 CallableDef::FunctionId(f) => {
675 if let ContainerId::TraitId(trait_) = f.lookup(self.db).container { 690 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db).container {
676 // construct a TraitDef 691 // construct a TraitDef
677 let substs = 692 let substs =
678 a_ty.parameters.prefix(generics(self.db, trait_.into()).len()); 693 a_ty.parameters.prefix(generics(self.db, trait_.into()).len());