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.rs194
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs4
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs35
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs8
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
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
@@ -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
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,
@@ -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
24use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; 24use super::{
25 find_breakable, BindingMode, BreakableContext, Diverges, Expectation, InferenceContext,
26 InferenceDiagnostic, 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,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};
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/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;
5use hir_def::{ 5use 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};
10use hir_expand::name::Name; 10use 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
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 }