diff options
Diffstat (limited to 'crates/ra_hir_ty/src/infer')
-rw-r--r-- | crates/ra_hir_ty/src/infer/coerce.rs | 34 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 194 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/pat.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/path.rs | 35 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/unify.rs | 8 |
5 files changed, 210 insertions, 65 deletions
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 89200255a..32c7c57cd 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 | ||
7 | use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; | 7 | use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; |
8 | use test_utils::tested_by; | 8 | use test_utils::mark; |
9 | 9 | ||
10 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor}; | 10 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor}; |
11 | 11 | ||
@@ -20,21 +20,33 @@ 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 | mark::hit!(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 | mark::hit!(coerce_merge_fail_fallback); | ||
48 | ty1.clone() | ||
49 | } | ||
38 | } | 50 | } |
39 | } | 51 | } |
40 | 52 | ||
@@ -84,9 +96,7 @@ impl<'a> InferenceContext<'a> { | |||
84 | match from_ty.callable_sig(self.db) { | 96 | match from_ty.callable_sig(self.db) { |
85 | None => return false, | 97 | None => return false, |
86 | Some(sig) => { | 98 | Some(sig) => { |
87 | let num_args = sig.params_and_return.len() as u16 - 1; | 99 | from_ty = Ty::fn_ptr(sig); |
88 | from_ty = | ||
89 | Ty::apply(TypeCtor::FnPtr { num_args }, Substs(sig.params_and_return)); | ||
90 | } | 100 | } |
91 | } | 101 | } |
92 | } | 102 | } |
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index efc60986b..4a98e2deb 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 | ||
3 | use std::iter::{repeat, repeat_with}; | 3 | use std::iter::{repeat, repeat_with}; |
4 | use std::sync::Arc; | 4 | use std::{mem, sync::Arc}; |
5 | 5 | ||
6 | use hir_def::{ | 6 | use hir_def::{ |
7 | builtin_type::Signedness, | 7 | builtin_type::Signedness, |
@@ -17,15 +17,22 @@ use crate::{ | |||
17 | autoderef, method_resolution, op, | 17 | autoderef, method_resolution, op, |
18 | traits::InEnvironment, | 18 | traits::InEnvironment, |
19 | utils::{generics, variant_data, Generics}, | 19 | utils::{generics, variant_data, Generics}, |
20 | ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, | 20 | ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, |
21 | Ty, TypeCtor, Uncertain, | 21 | TraitRef, Ty, TypeCtor, Uncertain, |
22 | }; | 22 | }; |
23 | 23 | ||
24 | use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; | 24 | use super::{ |
25 | find_breakable, BindingMode, BreakableContext, Diverges, Expectation, InferenceContext, | ||
26 | InferenceDiagnostic, TypeMismatch, | ||
27 | }; | ||
25 | 28 | ||
26 | impl<'a> InferenceContext<'a> { | 29 | impl<'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,80 @@ 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, .. } => { |
76 | Expr::Loop { body } => { | 90 | // FIXME: Breakable block inference |
91 | self.infer_block(statements, *tail, expected) | ||
92 | } | ||
93 | Expr::TryBlock { body } => { | ||
94 | let _inner = self.infer_expr(*body, expected); | ||
95 | // FIXME should be std::result::Result<{inner}, _> | ||
96 | Ty::Unknown | ||
97 | } | ||
98 | Expr::Loop { body, label } => { | ||
99 | self.breakables.push(BreakableContext { | ||
100 | may_break: false, | ||
101 | break_ty: self.table.new_type_var(), | ||
102 | label: label.clone(), | ||
103 | }); | ||
77 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 104 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
78 | // FIXME handle break with value | 105 | |
79 | Ty::simple(TypeCtor::Never) | 106 | let ctxt = self.breakables.pop().expect("breakable stack broken"); |
107 | if ctxt.may_break { | ||
108 | self.diverges = Diverges::Maybe; | ||
109 | } | ||
110 | |||
111 | if ctxt.may_break { | ||
112 | ctxt.break_ty | ||
113 | } else { | ||
114 | Ty::simple(TypeCtor::Never) | ||
115 | } | ||
80 | } | 116 | } |
81 | Expr::While { condition, body } => { | 117 | Expr::While { condition, body, label } => { |
118 | self.breakables.push(BreakableContext { | ||
119 | may_break: false, | ||
120 | break_ty: Ty::Unknown, | ||
121 | label: label.clone(), | ||
122 | }); | ||
82 | // while let is desugared to a match loop, so this is always simple while | 123 | // 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))); | 124 | self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); |
84 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 125 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
126 | let _ctxt = self.breakables.pop().expect("breakable stack broken"); | ||
127 | // the body may not run, so it diverging doesn't mean we diverge | ||
128 | self.diverges = Diverges::Maybe; | ||
85 | Ty::unit() | 129 | Ty::unit() |
86 | } | 130 | } |
87 | Expr::For { iterable, body, pat } => { | 131 | Expr::For { iterable, body, pat, label } => { |
88 | let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); | 132 | let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); |
89 | 133 | ||
134 | self.breakables.push(BreakableContext { | ||
135 | may_break: false, | ||
136 | break_ty: Ty::Unknown, | ||
137 | label: label.clone(), | ||
138 | }); | ||
90 | let pat_ty = | 139 | let pat_ty = |
91 | self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); | 140 | self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); |
92 | 141 | ||
93 | self.infer_pat(*pat, &pat_ty, BindingMode::default()); | 142 | self.infer_pat(*pat, &pat_ty, BindingMode::default()); |
143 | |||
94 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 144 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); |
145 | let _ctxt = self.breakables.pop().expect("breakable stack broken"); | ||
146 | // the body may not run, so it diverging doesn't mean we diverge | ||
147 | self.diverges = Diverges::Maybe; | ||
95 | Ty::unit() | 148 | Ty::unit() |
96 | } | 149 | } |
97 | Expr::Lambda { body, args, ret_type, arg_types } => { | 150 | Expr::Lambda { body, args, ret_type, arg_types } => { |
@@ -99,13 +152,13 @@ impl<'a> InferenceContext<'a> { | |||
99 | 152 | ||
100 | let mut sig_tys = Vec::new(); | 153 | let mut sig_tys = Vec::new(); |
101 | 154 | ||
102 | for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { | 155 | // collect explicitly written argument types |
103 | let expected = if let Some(type_ref) = arg_type { | 156 | for arg_type in arg_types.iter() { |
157 | let arg_ty = if let Some(type_ref) = arg_type { | ||
104 | self.make_ty(type_ref) | 158 | self.make_ty(type_ref) |
105 | } else { | 159 | } else { |
106 | Ty::Unknown | 160 | self.table.new_type_var() |
107 | }; | 161 | }; |
108 | let arg_ty = self.infer_pat(*arg_pat, &expected, BindingMode::default()); | ||
109 | sig_tys.push(arg_ty); | 162 | sig_tys.push(arg_ty); |
110 | } | 163 | } |
111 | 164 | ||
@@ -117,7 +170,7 @@ impl<'a> InferenceContext<'a> { | |||
117 | sig_tys.push(ret_ty.clone()); | 170 | sig_tys.push(ret_ty.clone()); |
118 | let sig_ty = Ty::apply( | 171 | let sig_ty = Ty::apply( |
119 | TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, | 172 | TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, |
120 | Substs(sig_tys.into()), | 173 | Substs(sig_tys.clone().into()), |
121 | ); | 174 | ); |
122 | let closure_ty = | 175 | let closure_ty = |
123 | Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); | 176 | Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); |
@@ -127,10 +180,18 @@ impl<'a> InferenceContext<'a> { | |||
127 | // infer the body. | 180 | // infer the body. |
128 | self.coerce(&closure_ty, &expected.ty); | 181 | self.coerce(&closure_ty, &expected.ty); |
129 | 182 | ||
130 | let prev_ret_ty = std::mem::replace(&mut self.return_ty, ret_ty.clone()); | 183 | // Now go through the argument patterns |
184 | for (arg_pat, arg_ty) in args.iter().zip(sig_tys) { | ||
185 | let resolved = self.resolve_ty_as_possible(arg_ty); | ||
186 | self.infer_pat(*arg_pat, &resolved, BindingMode::default()); | ||
187 | } | ||
188 | |||
189 | let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); | ||
190 | let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); | ||
131 | 191 | ||
132 | self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty)); | 192 | self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty)); |
133 | 193 | ||
194 | self.diverges = prev_diverges; | ||
134 | self.return_ty = prev_ret_ty; | 195 | self.return_ty = prev_ret_ty; |
135 | 196 | ||
136 | closure_ty | 197 | closure_ty |
@@ -160,7 +221,11 @@ impl<'a> InferenceContext<'a> { | |||
160 | self.table.new_type_var() | 221 | self.table.new_type_var() |
161 | }; | 222 | }; |
162 | 223 | ||
224 | let matchee_diverges = self.diverges; | ||
225 | let mut all_arms_diverge = Diverges::Always; | ||
226 | |||
163 | for arm in arms { | 227 | for arm in arms { |
228 | self.diverges = Diverges::Maybe; | ||
164 | let _pat_ty = self.infer_pat(arm.pat, &input_ty, BindingMode::default()); | 229 | let _pat_ty = self.infer_pat(arm.pat, &input_ty, BindingMode::default()); |
165 | if let Some(guard_expr) = arm.guard { | 230 | if let Some(guard_expr) = arm.guard { |
166 | self.infer_expr( | 231 | self.infer_expr( |
@@ -170,9 +235,12 @@ impl<'a> InferenceContext<'a> { | |||
170 | } | 235 | } |
171 | 236 | ||
172 | let arm_ty = self.infer_expr_inner(arm.expr, &expected); | 237 | let arm_ty = self.infer_expr_inner(arm.expr, &expected); |
238 | all_arms_diverge &= self.diverges; | ||
173 | result_ty = self.coerce_merge_branch(&result_ty, &arm_ty); | 239 | result_ty = self.coerce_merge_branch(&result_ty, &arm_ty); |
174 | } | 240 | } |
175 | 241 | ||
242 | self.diverges = matchee_diverges | all_arms_diverge; | ||
243 | |||
176 | result_ty | 244 | result_ty |
177 | } | 245 | } |
178 | Expr::Path(p) => { | 246 | Expr::Path(p) => { |
@@ -180,12 +248,32 @@ impl<'a> InferenceContext<'a> { | |||
180 | let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); | 248 | let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); |
181 | self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) | 249 | self.infer_path(&resolver, p, tgt_expr.into()).unwrap_or(Ty::Unknown) |
182 | } | 250 | } |
183 | Expr::Continue => Ty::simple(TypeCtor::Never), | 251 | Expr::Continue { .. } => Ty::simple(TypeCtor::Never), |
184 | Expr::Break { expr } => { | 252 | Expr::Break { expr, label } => { |
185 | if let Some(expr) = expr { | 253 | let val_ty = if let Some(expr) = expr { |
186 | // FIXME handle break with value | 254 | self.infer_expr(*expr, &Expectation::none()) |
187 | self.infer_expr(*expr, &Expectation::none()); | 255 | } else { |
256 | Ty::unit() | ||
257 | }; | ||
258 | |||
259 | let last_ty = | ||
260 | if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { | ||
261 | ctxt.break_ty.clone() | ||
262 | } else { | ||
263 | Ty::Unknown | ||
264 | }; | ||
265 | |||
266 | let merged_type = self.coerce_merge_branch(&last_ty, &val_ty); | ||
267 | |||
268 | if let Some(ctxt) = find_breakable(&mut self.breakables, label.as_ref()) { | ||
269 | ctxt.break_ty = merged_type; | ||
270 | ctxt.may_break = true; | ||
271 | } else { | ||
272 | self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop { | ||
273 | expr: tgt_expr, | ||
274 | }); | ||
188 | } | 275 | } |
276 | |||
189 | Ty::simple(TypeCtor::Never) | 277 | Ty::simple(TypeCtor::Never) |
190 | } | 278 | } |
191 | Expr::Return { expr } => { | 279 | Expr::Return { expr } => { |
@@ -281,19 +369,28 @@ impl<'a> InferenceContext<'a> { | |||
281 | // FIXME check the cast... | 369 | // FIXME check the cast... |
282 | cast_ty | 370 | cast_ty |
283 | } | 371 | } |
284 | Expr::Ref { expr, mutability } => { | 372 | Expr::Ref { expr, rawness, mutability } => { |
285 | let expectation = | 373 | let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = |
286 | if let Some((exp_inner, exp_mutability)) = &expected.ty.as_reference() { | 374 | &expected.ty.as_reference_or_ptr() |
287 | if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { | 375 | { |
288 | // FIXME: throw type error - expected mut reference but found shared ref, | 376 | if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { |
289 | // which cannot be coerced | 377 | // FIXME: throw type error - expected mut reference but found shared ref, |
290 | } | 378 | // which cannot be coerced |
291 | Expectation::rvalue_hint(Ty::clone(exp_inner)) | 379 | } |
292 | } else { | 380 | if *exp_rawness == Rawness::Ref && *rawness == Rawness::RawPtr { |
293 | Expectation::none() | 381 | // FIXME: throw type error - expected reference but found ptr, |
294 | }; | 382 | // which cannot be coerced |
383 | } | ||
384 | Expectation::rvalue_hint(Ty::clone(exp_inner)) | ||
385 | } else { | ||
386 | Expectation::none() | ||
387 | }; | ||
295 | let inner_ty = self.infer_expr_inner(*expr, &expectation); | 388 | let inner_ty = self.infer_expr_inner(*expr, &expectation); |
296 | Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) | 389 | let ty = match rawness { |
390 | Rawness::RawPtr => TypeCtor::RawPtr(*mutability), | ||
391 | Rawness::Ref => TypeCtor::Ref(*mutability), | ||
392 | }; | ||
393 | Ty::apply_one(ty, inner_ty) | ||
297 | } | 394 | } |
298 | Expr::Box { expr } => { | 395 | Expr::Box { expr } => { |
299 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); | 396 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
@@ -496,8 +593,8 @@ impl<'a> InferenceContext<'a> { | |||
496 | } | 593 | } |
497 | Literal::ByteString(..) => { | 594 | Literal::ByteString(..) => { |
498 | let byte_type = Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::u8()))); | 595 | let byte_type = Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::u8()))); |
499 | let slice_type = Ty::apply_one(TypeCtor::Slice, byte_type); | 596 | let array_type = Ty::apply_one(TypeCtor::Array, byte_type); |
500 | Ty::apply_one(TypeCtor::Ref(Mutability::Shared), slice_type) | 597 | Ty::apply_one(TypeCtor::Ref(Mutability::Shared), array_type) |
501 | } | 598 | } |
502 | Literal::Char(..) => Ty::simple(TypeCtor::Char), | 599 | Literal::Char(..) => Ty::simple(TypeCtor::Char), |
503 | Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int((*ty).into())), | 600 | Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int((*ty).into())), |
@@ -517,7 +614,6 @@ impl<'a> InferenceContext<'a> { | |||
517 | tail: Option<ExprId>, | 614 | tail: Option<ExprId>, |
518 | expected: &Expectation, | 615 | expected: &Expectation, |
519 | ) -> Ty { | 616 | ) -> Ty { |
520 | let mut diverges = false; | ||
521 | for stmt in statements { | 617 | for stmt in statements { |
522 | match stmt { | 618 | match stmt { |
523 | Statement::Let { pat, type_ref, initializer } => { | 619 | Statement::Let { pat, type_ref, initializer } => { |
@@ -539,9 +635,7 @@ impl<'a> InferenceContext<'a> { | |||
539 | self.infer_pat(*pat, &ty, BindingMode::default()); | 635 | self.infer_pat(*pat, &ty, BindingMode::default()); |
540 | } | 636 | } |
541 | Statement::Expr(expr) => { | 637 | Statement::Expr(expr) => { |
542 | if let ty_app!(TypeCtor::Never) = self.infer_expr(*expr, &Expectation::none()) { | 638 | self.infer_expr(*expr, &Expectation::none()); |
543 | diverges = true; | ||
544 | } | ||
545 | } | 639 | } |
546 | } | 640 | } |
547 | } | 641 | } |
@@ -549,14 +643,22 @@ impl<'a> InferenceContext<'a> { | |||
549 | let ty = if let Some(expr) = tail { | 643 | let ty = if let Some(expr) = tail { |
550 | self.infer_expr_coerce(expr, expected) | 644 | self.infer_expr_coerce(expr, expected) |
551 | } else { | 645 | } else { |
552 | self.coerce(&Ty::unit(), expected.coercion_target()); | 646 | // Citing rustc: if there is no explicit tail expression, |
553 | Ty::unit() | 647 | // that is typically equivalent to a tail expression |
648 | // of `()` -- except if the block diverges. In that | ||
649 | // case, there is no value supplied from the tail | ||
650 | // expression (assuming there are no other breaks, | ||
651 | // this implies that the type of the block will be | ||
652 | // `!`). | ||
653 | if self.diverges.is_always() { | ||
654 | // we don't even make an attempt at coercion | ||
655 | self.table.new_maybe_never_type_var() | ||
656 | } else { | ||
657 | self.coerce(&Ty::unit(), expected.coercion_target()); | ||
658 | Ty::unit() | ||
659 | } | ||
554 | }; | 660 | }; |
555 | if diverges { | 661 | ty |
556 | Ty::simple(TypeCtor::Never) | ||
557 | } else { | ||
558 | ty | ||
559 | } | ||
560 | } | 662 | } |
561 | 663 | ||
562 | fn infer_method_call( | 664 | fn infer_method_call( |
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 | }; |
12 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
13 | use test_utils::tested_by; | 13 | use test_utils::mark; |
14 | 14 | ||
15 | use super::{BindingMode, Expectation, InferenceContext}; | 15 | use super::{BindingMode, Expectation, InferenceContext}; |
16 | use crate::{utils::variant_data, Substs, Ty, TypeCtor}; | 16 | use 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/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 2b6bc0f79..1c2e56fb0 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs | |||
@@ -5,7 +5,7 @@ use std::iter; | |||
5 | use hir_def::{ | 5 | use hir_def::{ |
6 | path::{Path, PathSegment}, | 6 | path::{Path, PathSegment}, |
7 | resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, | 7 | resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, |
8 | AssocContainerId, AssocItemId, Lookup, | 8 | AdtId, AssocContainerId, AssocItemId, EnumVariantId, Lookup, |
9 | }; | 9 | }; |
10 | use hir_expand::name::Name; | 10 | use hir_expand::name::Name; |
11 | 11 | ||
@@ -77,6 +77,18 @@ impl<'a> InferenceContext<'a> { | |||
77 | 77 | ||
78 | it.into() | 78 | it.into() |
79 | } | 79 | } |
80 | ValueNs::ImplSelf(impl_id) => { | ||
81 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); | ||
82 | let substs = Substs::type_params_for_generics(&generics); | ||
83 | let ty = self.db.impl_self_ty(impl_id).subst(&substs); | ||
84 | if let Some((AdtId::StructId(struct_id), _)) = ty.as_adt() { | ||
85 | let ty = self.db.value_ty(struct_id.into()).subst(&substs); | ||
86 | return Some(ty); | ||
87 | } else { | ||
88 | // FIXME: diagnostic, invalid Self reference | ||
89 | return None; | ||
90 | } | ||
91 | } | ||
80 | }; | 92 | }; |
81 | 93 | ||
82 | let ty = self.db.value_ty(typable); | 94 | let ty = self.db.value_ty(typable); |
@@ -199,6 +211,10 @@ impl<'a> InferenceContext<'a> { | |||
199 | return None; | 211 | return None; |
200 | } | 212 | } |
201 | 213 | ||
214 | if let Some(result) = self.resolve_enum_variant_on_ty(&ty, name, id) { | ||
215 | return Some(result); | ||
216 | } | ||
217 | |||
202 | let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); | 218 | let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); |
203 | let krate = self.resolver.krate()?; | 219 | let krate = self.resolver.krate()?; |
204 | let traits_in_scope = self.resolver.traits_in_scope(self.db.upcast()); | 220 | let traits_in_scope = self.resolver.traits_in_scope(self.db.upcast()); |
@@ -250,4 +266,21 @@ impl<'a> InferenceContext<'a> { | |||
250 | }, | 266 | }, |
251 | ) | 267 | ) |
252 | } | 268 | } |
269 | |||
270 | fn resolve_enum_variant_on_ty( | ||
271 | &mut self, | ||
272 | ty: &Ty, | ||
273 | name: &Name, | ||
274 | id: ExprOrPatId, | ||
275 | ) -> Option<(ValueNs, Option<Substs>)> { | ||
276 | let (enum_id, subst) = match ty.as_adt() { | ||
277 | Some((AdtId::EnumId(e), subst)) => (e, subst), | ||
278 | _ => return None, | ||
279 | }; | ||
280 | let enum_data = self.db.enum_data(enum_id); | ||
281 | let local_id = enum_data.variant(name)?; | ||
282 | let variant = EnumVariantId { parent: enum_id, local_id }; | ||
283 | self.write_variant_resolution(id, variant.into()); | ||
284 | Some((ValueNs::EnumVariantId(variant), Some(subst.clone()))) | ||
285 | } | ||
253 | } | 286 | } |
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 | ||
5 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 5 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
6 | 6 | ||
7 | use test_utils::tested_by; | 7 | use test_utils::mark; |
8 | 8 | ||
9 | use super::{InferenceContext, Obligation}; | 9 | use super::{InferenceContext, Obligation}; |
10 | use crate::{ | 10 | use 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 | } |