diff options
Diffstat (limited to 'crates/ra_hir_ty/src/infer/expr.rs')
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 194 |
1 files changed, 148 insertions, 46 deletions
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( |