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.rs116
1 files changed, 95 insertions, 21 deletions
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index efc60986b..b28724f0e 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -1,7 +1,7 @@
1//! Type inference for expressions. 1//! Type inference for expressions.
2 2
3use std::iter::{repeat, repeat_with}; 3use std::iter::{repeat, repeat_with};
4use std::sync::Arc; 4use std::{mem, sync::Arc};
5 5
6use hir_def::{ 6use hir_def::{
7 builtin_type::Signedness, 7 builtin_type::Signedness,
@@ -21,11 +21,18 @@ use crate::{
21 Ty, TypeCtor, Uncertain, 21 Ty, TypeCtor, Uncertain,
22}; 22};
23 23
24use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; 24use super::{
25 BindingMode, BreakableContext, Diverges, Expectation, InferenceContext, InferenceDiagnostic,
26 TypeMismatch,
27};
25 28
26impl<'a> InferenceContext<'a> { 29impl<'a> InferenceContext<'a> {
27 pub(super) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 30 pub(super) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
28 let ty = self.infer_expr_inner(tgt_expr, expected); 31 let ty = self.infer_expr_inner(tgt_expr, expected);
32 if ty.is_never() {
33 // Any expression that produces a value of type `!` must have diverged
34 self.diverges = Diverges::Always;
35 }
29 let could_unify = self.unify(&ty, &expected.ty); 36 let could_unify = self.unify(&ty, &expected.ty);
30 if !could_unify { 37 if !could_unify {
31 self.result.type_mismatches.insert( 38 self.result.type_mismatches.insert(
@@ -64,34 +71,68 @@ impl<'a> InferenceContext<'a> {
64 // if let is desugared to match, so this is always simple if 71 // if let is desugared to match, so this is always simple if
65 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); 72 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool)));
66 73
74 let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
75 let mut both_arms_diverge = Diverges::Always;
76
67 let then_ty = self.infer_expr_inner(*then_branch, &expected); 77 let then_ty = self.infer_expr_inner(*then_branch, &expected);
78 both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe);
68 let else_ty = match else_branch { 79 let else_ty = match else_branch {
69 Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), 80 Some(else_branch) => self.infer_expr_inner(*else_branch, &expected),
70 None => Ty::unit(), 81 None => Ty::unit(),
71 }; 82 };
83 both_arms_diverge &= self.diverges;
84
85 self.diverges = condition_diverges | both_arms_diverge;
72 86
73 self.coerce_merge_branch(&then_ty, &else_ty) 87 self.coerce_merge_branch(&then_ty, &else_ty)
74 } 88 }
75 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), 89 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected),
90 Expr::TryBlock { body } => {
91 let _inner = self.infer_expr(*body, expected);
92 // FIXME should be std::result::Result<{inner}, _>
93 Ty::Unknown
94 }
76 Expr::Loop { body } => { 95 Expr::Loop { body } => {
96 self.breakables.push(BreakableContext {
97 may_break: false,
98 break_ty: self.table.new_type_var(),
99 });
77 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 100 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
78 // FIXME handle break with value 101
79 Ty::simple(TypeCtor::Never) 102 let ctxt = self.breakables.pop().expect("breakable stack broken");
103 if ctxt.may_break {
104 self.diverges = Diverges::Maybe;
105 }
106
107 if ctxt.may_break {
108 ctxt.break_ty
109 } else {
110 Ty::simple(TypeCtor::Never)
111 }
80 } 112 }
81 Expr::While { condition, body } => { 113 Expr::While { condition, body } => {
114 self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown });
82 // while let is desugared to a match loop, so this is always simple while 115 // while let is desugared to a match loop, so this is always simple while
83 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); 116 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool)));
84 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 117 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
118 let _ctxt = self.breakables.pop().expect("breakable stack broken");
119 // the body may not run, so it diverging doesn't mean we diverge
120 self.diverges = Diverges::Maybe;
85 Ty::unit() 121 Ty::unit()
86 } 122 }
87 Expr::For { iterable, body, pat } => { 123 Expr::For { iterable, body, pat } => {
88 let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 124 let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
89 125
126 self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown });
90 let pat_ty = 127 let pat_ty =
91 self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); 128 self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
92 129
93 self.infer_pat(*pat, &pat_ty, BindingMode::default()); 130 self.infer_pat(*pat, &pat_ty, BindingMode::default());
131
94 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 132 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
133 let _ctxt = self.breakables.pop().expect("breakable stack broken");
134 // the body may not run, so it diverging doesn't mean we diverge
135 self.diverges = Diverges::Maybe;
95 Ty::unit() 136 Ty::unit()
96 } 137 }
97 Expr::Lambda { body, args, ret_type, arg_types } => { 138 Expr::Lambda { body, args, ret_type, arg_types } => {
@@ -127,10 +168,12 @@ impl<'a> InferenceContext<'a> {
127 // infer the body. 168 // infer the body.
128 self.coerce(&closure_ty, &expected.ty); 169 self.coerce(&closure_ty, &expected.ty);
129 170
130 let prev_ret_ty = std::mem::replace(&mut self.return_ty, ret_ty.clone()); 171 let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
172 let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
131 173
132 self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty)); 174 self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
133 175
176 self.diverges = prev_diverges;
134 self.return_ty = prev_ret_ty; 177 self.return_ty = prev_ret_ty;
135 178
136 closure_ty 179 closure_ty
@@ -160,7 +203,11 @@ impl<'a> InferenceContext<'a> {
160 self.table.new_type_var() 203 self.table.new_type_var()
161 }; 204 };
162 205
206 let matchee_diverges = self.diverges;
207 let mut all_arms_diverge = Diverges::Always;
208
163 for arm in arms { 209 for arm in arms {
210 self.diverges = Diverges::Maybe;
164 let _pat_ty = self.infer_pat(arm.pat, &input_ty, BindingMode::default()); 211 let _pat_ty = self.infer_pat(arm.pat, &input_ty, BindingMode::default());
165 if let Some(guard_expr) = arm.guard { 212 if let Some(guard_expr) = arm.guard {
166 self.infer_expr( 213 self.infer_expr(
@@ -170,9 +217,12 @@ impl<'a> InferenceContext<'a> {
170 } 217 }
171 218
172 let arm_ty = self.infer_expr_inner(arm.expr, &expected); 219 let arm_ty = self.infer_expr_inner(arm.expr, &expected);
220 all_arms_diverge &= self.diverges;
173 result_ty = self.coerce_merge_branch(&result_ty, &arm_ty); 221 result_ty = self.coerce_merge_branch(&result_ty, &arm_ty);
174 } 222 }
175 223
224 self.diverges = matchee_diverges | all_arms_diverge;
225
176 result_ty 226 result_ty
177 } 227 }
178 Expr::Path(p) => { 228 Expr::Path(p) => {
@@ -182,10 +232,29 @@ impl<'a> InferenceContext<'a> {
182 } 232 }
183 Expr::Continue => Ty::simple(TypeCtor::Never), 233 Expr::Continue => Ty::simple(TypeCtor::Never),
184 Expr::Break { expr } => { 234 Expr::Break { expr } => {
185 if let Some(expr) = expr { 235 let val_ty = if let Some(expr) = expr {
186 // FIXME handle break with value 236 self.infer_expr(*expr, &Expectation::none())
187 self.infer_expr(*expr, &Expectation::none()); 237 } else {
238 Ty::unit()
239 };
240
241 let last_ty = if let Some(ctxt) = self.breakables.last() {
242 ctxt.break_ty.clone()
243 } else {
244 Ty::Unknown
245 };
246
247 let merged_type = self.coerce_merge_branch(&last_ty, &val_ty);
248
249 if let Some(ctxt) = self.breakables.last_mut() {
250 ctxt.break_ty = merged_type;
251 ctxt.may_break = true;
252 } else {
253 self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop {
254 expr: tgt_expr,
255 });
188 } 256 }
257
189 Ty::simple(TypeCtor::Never) 258 Ty::simple(TypeCtor::Never)
190 } 259 }
191 Expr::Return { expr } => { 260 Expr::Return { expr } => {
@@ -496,8 +565,8 @@ impl<'a> InferenceContext<'a> {
496 } 565 }
497 Literal::ByteString(..) => { 566 Literal::ByteString(..) => {
498 let byte_type = Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::u8()))); 567 let byte_type = Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::u8())));
499 let slice_type = Ty::apply_one(TypeCtor::Slice, byte_type); 568 let array_type = Ty::apply_one(TypeCtor::Array, byte_type);
500 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), slice_type) 569 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), array_type)
501 } 570 }
502 Literal::Char(..) => Ty::simple(TypeCtor::Char), 571 Literal::Char(..) => Ty::simple(TypeCtor::Char),
503 Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int((*ty).into())), 572 Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int((*ty).into())),
@@ -517,7 +586,6 @@ impl<'a> InferenceContext<'a> {
517 tail: Option<ExprId>, 586 tail: Option<ExprId>,
518 expected: &Expectation, 587 expected: &Expectation,
519 ) -> Ty { 588 ) -> Ty {
520 let mut diverges = false;
521 for stmt in statements { 589 for stmt in statements {
522 match stmt { 590 match stmt {
523 Statement::Let { pat, type_ref, initializer } => { 591 Statement::Let { pat, type_ref, initializer } => {
@@ -539,9 +607,7 @@ impl<'a> InferenceContext<'a> {
539 self.infer_pat(*pat, &ty, BindingMode::default()); 607 self.infer_pat(*pat, &ty, BindingMode::default());
540 } 608 }
541 Statement::Expr(expr) => { 609 Statement::Expr(expr) => {
542 if let ty_app!(TypeCtor::Never) = self.infer_expr(*expr, &Expectation::none()) { 610 self.infer_expr(*expr, &Expectation::none());
543 diverges = true;
544 }
545 } 611 }
546 } 612 }
547 } 613 }
@@ -549,14 +615,22 @@ impl<'a> InferenceContext<'a> {
549 let ty = if let Some(expr) = tail { 615 let ty = if let Some(expr) = tail {
550 self.infer_expr_coerce(expr, expected) 616 self.infer_expr_coerce(expr, expected)
551 } else { 617 } else {
552 self.coerce(&Ty::unit(), expected.coercion_target()); 618 // Citing rustc: if there is no explicit tail expression,
553 Ty::unit() 619 // that is typically equivalent to a tail expression
620 // of `()` -- except if the block diverges. In that
621 // case, there is no value supplied from the tail
622 // expression (assuming there are no other breaks,
623 // this implies that the type of the block will be
624 // `!`).
625 if self.diverges.is_always() {
626 // we don't even make an attempt at coercion
627 self.table.new_maybe_never_type_var()
628 } else {
629 self.coerce(&Ty::unit(), expected.coercion_target());
630 Ty::unit()
631 }
554 }; 632 };
555 if diverges { 633 ty
556 Ty::simple(TypeCtor::Never)
557 } else {
558 ty
559 }
560 } 634 }
561 635
562 fn infer_method_call( 636 fn infer_method_call(