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.rs34
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs88
2 files changed, 94 insertions, 28 deletions
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs
index 89200255a..173ec59ed 100644
--- a/crates/ra_hir_ty/src/infer/coerce.rs
+++ b/crates/ra_hir_ty/src/infer/coerce.rs
@@ -20,21 +20,35 @@ impl<'a> InferenceContext<'a> {
20 self.coerce_inner(from_ty, &to_ty) 20 self.coerce_inner(from_ty, &to_ty)
21 } 21 }
22 22
23 /// Merge two types from different branches, with possible implicit coerce. 23 /// Merge two types from different branches, with possible coercion.
24 /// 24 ///
25 /// Note that it is only possible that one type are coerced to another. 25 /// Mostly this means trying to coerce one to the other, but
26 /// Coercing both types to another least upper bound type is not possible in rustc, 26 /// - if we have two function types for different functions, we need to
27 /// which will simply result in "incompatible types" error. 27 /// coerce both to function pointers;
28 /// - if we were concerned with lifetime subtyping, we'd need to look for a
29 /// least upper bound.
28 pub(super) fn coerce_merge_branch(&mut self, ty1: &Ty, ty2: &Ty) -> Ty { 30 pub(super) fn coerce_merge_branch(&mut self, ty1: &Ty, ty2: &Ty) -> Ty {
29 if self.coerce(ty1, ty2) { 31 if self.coerce(ty1, ty2) {
30 ty2.clone() 32 ty2.clone()
31 } else if self.coerce(ty2, ty1) { 33 } else if self.coerce(ty2, ty1) {
32 ty1.clone() 34 ty1.clone()
33 } else { 35 } else {
34 tested_by!(coerce_merge_fail_fallback); 36 if let (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnDef(_))) = (ty1, ty2) {
35 // For incompatible types, we use the latter one as result 37 tested_by!(coerce_fn_reification);
36 // to be better recovery for `if` without `else`. 38 // Special case: two function types. Try to coerce both to
37 ty2.clone() 39 // pointers to have a chance at getting a match. See
40 // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916
41 let sig1 = ty1.callable_sig(self.db).expect("FnDef without callable sig");
42 let sig2 = ty2.callable_sig(self.db).expect("FnDef without callable sig");
43 let ptr_ty1 = Ty::fn_ptr(sig1);
44 let ptr_ty2 = Ty::fn_ptr(sig2);
45 self.coerce_merge_branch(&ptr_ty1, &ptr_ty2)
46 } else {
47 tested_by!(coerce_merge_fail_fallback);
48 // For incompatible types, we use the latter one as result
49 // to be better recovery for `if` without `else`.
50 ty2.clone()
51 }
38 } 52 }
39 } 53 }
40 54
@@ -84,9 +98,7 @@ impl<'a> InferenceContext<'a> {
84 match from_ty.callable_sig(self.db) { 98 match from_ty.callable_sig(self.db) {
85 None => return false, 99 None => return false,
86 Some(sig) => { 100 Some(sig) => {
87 let num_args = sig.params_and_return.len() as u16 - 1; 101 from_ty = Ty::fn_ptr(sig);
88 from_ty =
89 Ty::apply(TypeCtor::FnPtr { num_args }, Substs(sig.params_and_return));
90 } 102 }
91 } 103 }
92 } 104 }
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 83f946eee..0b67d216a 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,11 +71,18 @@ 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 }
@@ -79,24 +93,43 @@ impl<'a> InferenceContext<'a> {
79 Ty::Unknown 93 Ty::Unknown
80 } 94 }
81 Expr::Loop { body } => { 95 Expr::Loop { body } => {
96 self.breakables.push(BreakableContext { may_break: false });
82 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 97 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
98
99 let ctxt = self.breakables.pop().expect("breakable stack broken");
100 if ctxt.may_break {
101 self.diverges = Diverges::Maybe;
102 }
83 // FIXME handle break with value 103 // FIXME handle break with value
84 Ty::simple(TypeCtor::Never) 104 if ctxt.may_break {
105 Ty::unit()
106 } else {
107 Ty::simple(TypeCtor::Never)
108 }
85 } 109 }
86 Expr::While { condition, body } => { 110 Expr::While { condition, body } => {
111 self.breakables.push(BreakableContext { may_break: false });
87 // while let is desugared to a match loop, so this is always simple while 112 // while let is desugared to a match loop, so this is always simple while
88 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); 113 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool)));
89 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 114 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
115 let _ctxt = self.breakables.pop().expect("breakable stack broken");
116 // the body may not run, so it diverging doesn't mean we diverge
117 self.diverges = Diverges::Maybe;
90 Ty::unit() 118 Ty::unit()
91 } 119 }
92 Expr::For { iterable, body, pat } => { 120 Expr::For { iterable, body, pat } => {
93 let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 121 let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
94 122
123 self.breakables.push(BreakableContext { may_break: false });
95 let pat_ty = 124 let pat_ty =
96 self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); 125 self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
97 126
98 self.infer_pat(*pat, &pat_ty, BindingMode::default()); 127 self.infer_pat(*pat, &pat_ty, BindingMode::default());
128
99 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 129 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
130 let _ctxt = self.breakables.pop().expect("breakable stack broken");
131 // the body may not run, so it diverging doesn't mean we diverge
132 self.diverges = Diverges::Maybe;
100 Ty::unit() 133 Ty::unit()
101 } 134 }
102 Expr::Lambda { body, args, ret_type, arg_types } => { 135 Expr::Lambda { body, args, ret_type, arg_types } => {
@@ -132,10 +165,12 @@ impl<'a> InferenceContext<'a> {
132 // infer the body. 165 // infer the body.
133 self.coerce(&closure_ty, &expected.ty); 166 self.coerce(&closure_ty, &expected.ty);
134 167
135 let prev_ret_ty = std::mem::replace(&mut self.return_ty, ret_ty.clone()); 168 let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
169 let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
136 170
137 self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty)); 171 self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
138 172
173 self.diverges = prev_diverges;
139 self.return_ty = prev_ret_ty; 174 self.return_ty = prev_ret_ty;
140 175
141 closure_ty 176 closure_ty
@@ -165,7 +200,11 @@ impl<'a> InferenceContext<'a> {
165 self.table.new_type_var() 200 self.table.new_type_var()
166 }; 201 };
167 202
203 let matchee_diverges = self.diverges;
204 let mut all_arms_diverge = Diverges::Always;
205
168 for arm in arms { 206 for arm in arms {
207 self.diverges = Diverges::Maybe;
169 let _pat_ty = self.infer_pat(arm.pat, &input_ty, BindingMode::default()); 208 let _pat_ty = self.infer_pat(arm.pat, &input_ty, BindingMode::default());
170 if let Some(guard_expr) = arm.guard { 209 if let Some(guard_expr) = arm.guard {
171 self.infer_expr( 210 self.infer_expr(
@@ -175,9 +214,12 @@ impl<'a> InferenceContext<'a> {
175 } 214 }
176 215
177 let arm_ty = self.infer_expr_inner(arm.expr, &expected); 216 let arm_ty = self.infer_expr_inner(arm.expr, &expected);
217 all_arms_diverge &= self.diverges;
178 result_ty = self.coerce_merge_branch(&result_ty, &arm_ty); 218 result_ty = self.coerce_merge_branch(&result_ty, &arm_ty);
179 } 219 }
180 220
221 self.diverges = matchee_diverges | all_arms_diverge;
222
181 result_ty 223 result_ty
182 } 224 }
183 Expr::Path(p) => { 225 Expr::Path(p) => {
@@ -191,6 +233,13 @@ impl<'a> InferenceContext<'a> {
191 // FIXME handle break with value 233 // FIXME handle break with value
192 self.infer_expr(*expr, &Expectation::none()); 234 self.infer_expr(*expr, &Expectation::none());
193 } 235 }
236 if let Some(ctxt) = self.breakables.last_mut() {
237 ctxt.may_break = true;
238 } else {
239 self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop {
240 expr: tgt_expr,
241 });
242 }
194 Ty::simple(TypeCtor::Never) 243 Ty::simple(TypeCtor::Never)
195 } 244 }
196 Expr::Return { expr } => { 245 Expr::Return { expr } => {
@@ -501,8 +550,8 @@ impl<'a> InferenceContext<'a> {
501 } 550 }
502 Literal::ByteString(..) => { 551 Literal::ByteString(..) => {
503 let byte_type = Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::u8()))); 552 let byte_type = Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::u8())));
504 let slice_type = Ty::apply_one(TypeCtor::Slice, byte_type); 553 let array_type = Ty::apply_one(TypeCtor::Array, byte_type);
505 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), slice_type) 554 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), array_type)
506 } 555 }
507 Literal::Char(..) => Ty::simple(TypeCtor::Char), 556 Literal::Char(..) => Ty::simple(TypeCtor::Char),
508 Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int((*ty).into())), 557 Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int((*ty).into())),
@@ -522,7 +571,6 @@ impl<'a> InferenceContext<'a> {
522 tail: Option<ExprId>, 571 tail: Option<ExprId>,
523 expected: &Expectation, 572 expected: &Expectation,
524 ) -> Ty { 573 ) -> Ty {
525 let mut diverges = false;
526 for stmt in statements { 574 for stmt in statements {
527 match stmt { 575 match stmt {
528 Statement::Let { pat, type_ref, initializer } => { 576 Statement::Let { pat, type_ref, initializer } => {
@@ -544,9 +592,7 @@ impl<'a> InferenceContext<'a> {
544 self.infer_pat(*pat, &ty, BindingMode::default()); 592 self.infer_pat(*pat, &ty, BindingMode::default());
545 } 593 }
546 Statement::Expr(expr) => { 594 Statement::Expr(expr) => {
547 if let ty_app!(TypeCtor::Never) = self.infer_expr(*expr, &Expectation::none()) { 595 self.infer_expr(*expr, &Expectation::none());
548 diverges = true;
549 }
550 } 596 }
551 } 597 }
552 } 598 }
@@ -554,14 +600,22 @@ impl<'a> InferenceContext<'a> {
554 let ty = if let Some(expr) = tail { 600 let ty = if let Some(expr) = tail {
555 self.infer_expr_coerce(expr, expected) 601 self.infer_expr_coerce(expr, expected)
556 } else { 602 } else {
557 self.coerce(&Ty::unit(), expected.coercion_target()); 603 // Citing rustc: if there is no explicit tail expression,
558 Ty::unit() 604 // that is typically equivalent to a tail expression
605 // of `()` -- except if the block diverges. In that
606 // case, there is no value supplied from the tail
607 // expression (assuming there are no other breaks,
608 // this implies that the type of the block will be
609 // `!`).
610 if self.diverges.is_always() {
611 // we don't even make an attempt at coercion
612 self.table.new_maybe_never_type_var()
613 } else {
614 self.coerce(&Ty::unit(), expected.coercion_target());
615 Ty::unit()
616 }
559 }; 617 };
560 if diverges { 618 ty
561 Ty::simple(TypeCtor::Never)
562 } else {
563 ty
564 }
565 } 619 }
566 620
567 fn infer_method_call( 621 fn infer_method_call(