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.rs6
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs33
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs4
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs8
4 files changed, 33 insertions, 18 deletions
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs
index 173ec59ed..2ee9adb16 100644
--- a/crates/ra_hir_ty/src/infer/coerce.rs
+++ b/crates/ra_hir_ty/src/infer/coerce.rs
@@ -5,7 +5,7 @@
5//! See: https://doc.rust-lang.org/nomicon/coercions.html 5//! See: https://doc.rust-lang.org/nomicon/coercions.html
6 6
7use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; 7use hir_def::{lang_item::LangItemTarget, type_ref::Mutability};
8use test_utils::tested_by; 8use test_utils::mark;
9 9
10use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor}; 10use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor};
11 11
@@ -34,7 +34,7 @@ impl<'a> InferenceContext<'a> {
34 ty1.clone() 34 ty1.clone()
35 } else { 35 } else {
36 if let (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnDef(_))) = (ty1, ty2) { 36 if let (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnDef(_))) = (ty1, ty2) {
37 tested_by!(coerce_fn_reification); 37 mark::hit!(coerce_fn_reification);
38 // Special case: two function types. Try to coerce both to 38 // Special case: two function types. Try to coerce both to
39 // pointers to have a chance at getting a match. See 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 40 // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916
@@ -44,7 +44,7 @@ impl<'a> InferenceContext<'a> {
44 let ptr_ty2 = Ty::fn_ptr(sig2); 44 let ptr_ty2 = Ty::fn_ptr(sig2);
45 self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) 45 self.coerce_merge_branch(&ptr_ty1, &ptr_ty2)
46 } else { 46 } else {
47 tested_by!(coerce_merge_fail_fallback); 47 mark::hit!(coerce_merge_fail_fallback);
48 // For incompatible types, we use the latter one as result 48 // For incompatible types, we use the latter one as result
49 // to be better recovery for `if` without `else`. 49 // to be better recovery for `if` without `else`.
50 ty2.clone() 50 ty2.clone()
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 0b67d216a..b28724f0e 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -93,22 +93,25 @@ impl<'a> InferenceContext<'a> {
93 Ty::Unknown 93 Ty::Unknown
94 } 94 }
95 Expr::Loop { body } => { 95 Expr::Loop { body } => {
96 self.breakables.push(BreakableContext { may_break: false }); 96 self.breakables.push(BreakableContext {
97 may_break: false,
98 break_ty: self.table.new_type_var(),
99 });
97 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 100 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
98 101
99 let ctxt = self.breakables.pop().expect("breakable stack broken"); 102 let ctxt = self.breakables.pop().expect("breakable stack broken");
100 if ctxt.may_break { 103 if ctxt.may_break {
101 self.diverges = Diverges::Maybe; 104 self.diverges = Diverges::Maybe;
102 } 105 }
103 // FIXME handle break with value 106
104 if ctxt.may_break { 107 if ctxt.may_break {
105 Ty::unit() 108 ctxt.break_ty
106 } else { 109 } else {
107 Ty::simple(TypeCtor::Never) 110 Ty::simple(TypeCtor::Never)
108 } 111 }
109 } 112 }
110 Expr::While { condition, body } => { 113 Expr::While { condition, body } => {
111 self.breakables.push(BreakableContext { may_break: false }); 114 self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown });
112 // 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
113 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); 116 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool)));
114 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 117 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
@@ -120,7 +123,7 @@ impl<'a> InferenceContext<'a> {
120 Expr::For { iterable, body, pat } => { 123 Expr::For { iterable, body, pat } => {
121 let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 124 let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
122 125
123 self.breakables.push(BreakableContext { may_break: false }); 126 self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown });
124 let pat_ty = 127 let pat_ty =
125 self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); 128 self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
126 129
@@ -229,17 +232,29 @@ impl<'a> InferenceContext<'a> {
229 } 232 }
230 Expr::Continue => Ty::simple(TypeCtor::Never), 233 Expr::Continue => Ty::simple(TypeCtor::Never),
231 Expr::Break { expr } => { 234 Expr::Break { expr } => {
232 if let Some(expr) = expr { 235 let val_ty = if let Some(expr) = expr {
233 // FIXME handle break with value 236 self.infer_expr(*expr, &Expectation::none())
234 self.infer_expr(*expr, &Expectation::none()); 237 } else {
235 } 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
236 if let Some(ctxt) = self.breakables.last_mut() { 249 if let Some(ctxt) = self.breakables.last_mut() {
250 ctxt.break_ty = merged_type;
237 ctxt.may_break = true; 251 ctxt.may_break = true;
238 } else { 252 } else {
239 self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop { 253 self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop {
240 expr: tgt_expr, 254 expr: tgt_expr,
241 }); 255 });
242 } 256 }
257
243 Ty::simple(TypeCtor::Never) 258 Ty::simple(TypeCtor::Never)
244 } 259 }
245 Expr::Return { expr } => { 260 Expr::Return { expr } => {
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index 54ec870df..4006f595d 100644
--- a/crates/ra_hir_ty/src/infer/pat.rs
+++ b/crates/ra_hir_ty/src/infer/pat.rs
@@ -10,7 +10,7 @@ use hir_def::{
10 FieldId, 10 FieldId,
11}; 11};
12use hir_expand::name::Name; 12use hir_expand::name::Name;
13use test_utils::tested_by; 13use test_utils::mark;
14 14
15use super::{BindingMode, Expectation, InferenceContext}; 15use super::{BindingMode, Expectation, InferenceContext};
16use crate::{utils::variant_data, Substs, Ty, TypeCtor}; 16use crate::{utils::variant_data, Substs, Ty, TypeCtor};
@@ -111,7 +111,7 @@ impl<'a> InferenceContext<'a> {
111 } 111 }
112 } 112 }
113 } else if let Pat::Ref { .. } = &body[pat] { 113 } else if let Pat::Ref { .. } = &body[pat] {
114 tested_by!(match_ergonomics_ref); 114 mark::hit!(match_ergonomics_ref);
115 // When you encounter a `&pat` pattern, reset to Move. 115 // When you encounter a `&pat` pattern, reset to Move.
116 // This is so that `w` is by value: `let (_, &w) = &(1, &2);` 116 // This is so that `w` is by value: `let (_, &w) = &(1, &2);`
117 default_bm = BindingMode::Move; 117 default_bm = BindingMode::Move;
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index ab0bc8b70..269495ca0 100644
--- a/crates/ra_hir_ty/src/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -4,7 +4,7 @@ use std::borrow::Cow;
4 4
5use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 5use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
6 6
7use test_utils::tested_by; 7use test_utils::mark;
8 8
9use super::{InferenceContext, Obligation}; 9use super::{InferenceContext, Obligation};
10use crate::{ 10use crate::{
@@ -313,7 +313,7 @@ impl InferenceTable {
313 // more than once 313 // more than once
314 for i in 0..3 { 314 for i in 0..3 {
315 if i > 0 { 315 if i > 0 {
316 tested_by!(type_var_resolves_to_int_var); 316 mark::hit!(type_var_resolves_to_int_var);
317 } 317 }
318 match &*ty { 318 match &*ty {
319 Ty::Infer(tv) => { 319 Ty::Infer(tv) => {
@@ -342,7 +342,7 @@ impl InferenceTable {
342 Ty::Infer(tv) => { 342 Ty::Infer(tv) => {
343 let inner = tv.to_inner(); 343 let inner = tv.to_inner();
344 if tv_stack.contains(&inner) { 344 if tv_stack.contains(&inner) {
345 tested_by!(type_var_cycles_resolve_as_possible); 345 mark::hit!(type_var_cycles_resolve_as_possible);
346 // recursive type 346 // recursive type
347 return tv.fallback_value(); 347 return tv.fallback_value();
348 } 348 }
@@ -369,7 +369,7 @@ impl InferenceTable {
369 Ty::Infer(tv) => { 369 Ty::Infer(tv) => {
370 let inner = tv.to_inner(); 370 let inner = tv.to_inner();
371 if tv_stack.contains(&inner) { 371 if tv_stack.contains(&inner) {
372 tested_by!(type_var_cycles_resolve_completely); 372 mark::hit!(type_var_cycles_resolve_completely);
373 // recursive type 373 // recursive type
374 return tv.fallback_value(); 374 return tv.fallback_value();
375 } 375 }