diff options
author | uHOOCCOOHu <[email protected]> | 2019-09-25 22:56:55 +0100 |
---|---|---|
committer | uHOOCCOOHu <[email protected]> | 2019-09-25 23:16:58 +0100 |
commit | 29e56b8ee480828b81011cfa16c055fa0c9c89fe (patch) | |
tree | 45f901e9a92ffc8cf1d90a3fef1db45a70df632a /crates/ra_hir/src/ty/infer.rs | |
parent | 5807e261c27e4964fc6a8d2b8cf02e548292b940 (diff) |
Support all coercion places
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 82 |
1 files changed, 57 insertions, 25 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index ba63050a9..db3377357 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -14,7 +14,7 @@ | |||
14 | //! the `ena` crate, which is extracted from rustc. | 14 | //! the `ena` crate, which is extracted from rustc. |
15 | 15 | ||
16 | use std::borrow::Cow; | 16 | use std::borrow::Cow; |
17 | use std::iter::repeat; | 17 | use std::iter::{repeat, repeat_with}; |
18 | use std::mem; | 18 | use std::mem; |
19 | use std::ops::Index; | 19 | use std::ops::Index; |
20 | use std::sync::Arc; | 20 | use std::sync::Arc; |
@@ -876,10 +876,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
876 | } | 876 | } |
877 | 877 | ||
878 | /// Infer type of expression with possibly implicit coerce to the expected type. | 878 | /// Infer type of expression with possibly implicit coerce to the expected type. |
879 | /// Return the type after possible coercion. | ||
879 | fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty { | 880 | fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty { |
880 | let ty = self.infer_expr_inner(expr, &expected); | 881 | let ty = self.infer_expr_inner(expr, &expected); |
881 | self.coerce(&ty, &expected.ty); | 882 | let ty = if !self.coerce(&ty, &expected.ty) { |
882 | ty | 883 | self.result |
884 | .type_mismatches | ||
885 | .insert(expr, TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() }); | ||
886 | // Return actual type when type mismatch. | ||
887 | // This is needed for diagnostic when return type mismatch. | ||
888 | ty | ||
889 | } else if expected.ty == Ty::Unknown { | ||
890 | ty | ||
891 | } else { | ||
892 | expected.ty.clone() | ||
893 | }; | ||
894 | |||
895 | self.resolve_ty_as_possible(&mut vec![], ty) | ||
883 | } | 896 | } |
884 | 897 | ||
885 | /// Merge two types from different branches, with possible implicit coerce. | 898 | /// Merge two types from different branches, with possible implicit coerce. |
@@ -1328,6 +1341,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1328 | self.write_variant_resolution(tgt_expr.into(), variant); | 1341 | self.write_variant_resolution(tgt_expr.into(), variant); |
1329 | } | 1342 | } |
1330 | 1343 | ||
1344 | self.unify(&ty, &expected.ty); | ||
1345 | |||
1331 | let substs = ty.substs().unwrap_or_else(Substs::empty); | 1346 | let substs = ty.substs().unwrap_or_else(Substs::empty); |
1332 | for (field_idx, field) in fields.iter().enumerate() { | 1347 | for (field_idx, field) in fields.iter().enumerate() { |
1333 | let field_ty = def_id | 1348 | let field_ty = def_id |
@@ -1343,7 +1358,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1343 | }) | 1358 | }) |
1344 | .map_or(Ty::Unknown, |field| field.ty(self.db)) | 1359 | .map_or(Ty::Unknown, |field| field.ty(self.db)) |
1345 | .subst(&substs); | 1360 | .subst(&substs); |
1346 | self.infer_expr(field.expr, &Expectation::has_type(field_ty)); | 1361 | self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); |
1347 | } | 1362 | } |
1348 | if let Some(expr) = spread { | 1363 | if let Some(expr) = spread { |
1349 | self.infer_expr(*expr, &Expectation::has_type(ty.clone())); | 1364 | self.infer_expr(*expr, &Expectation::has_type(ty.clone())); |
@@ -1513,35 +1528,41 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1513 | Ty::Unknown | 1528 | Ty::Unknown |
1514 | } | 1529 | } |
1515 | Expr::Tuple { exprs } => { | 1530 | Expr::Tuple { exprs } => { |
1516 | let mut ty_vec = Vec::with_capacity(exprs.len()); | 1531 | let mut tys = match &expected.ty { |
1517 | for arg in exprs.iter() { | 1532 | ty_app!(TypeCtor::Tuple { .. }, st) => st |
1518 | ty_vec.push(self.infer_expr(*arg, &Expectation::none())); | 1533 | .iter() |
1534 | .cloned() | ||
1535 | .chain(repeat_with(|| self.new_type_var())) | ||
1536 | .take(exprs.len()) | ||
1537 | .collect::<Vec<_>>(), | ||
1538 | _ => (0..exprs.len()).map(|_| self.new_type_var()).collect(), | ||
1539 | }; | ||
1540 | |||
1541 | for (expr, ty) in exprs.iter().zip(tys.iter_mut()) { | ||
1542 | self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); | ||
1519 | } | 1543 | } |
1520 | 1544 | ||
1521 | Ty::apply( | 1545 | Ty::apply(TypeCtor::Tuple { cardinality: tys.len() as u16 }, Substs(tys.into())) |
1522 | TypeCtor::Tuple { cardinality: ty_vec.len() as u16 }, | ||
1523 | Substs(ty_vec.into()), | ||
1524 | ) | ||
1525 | } | 1546 | } |
1526 | Expr::Array(array) => { | 1547 | Expr::Array(array) => { |
1527 | let elem_ty = match &expected.ty { | 1548 | let elem_ty = match &expected.ty { |
1528 | Ty::Apply(a_ty) => match a_ty.ctor { | 1549 | ty_app!(TypeCtor::Array, st) | ty_app!(TypeCtor::Slice, st) => { |
1529 | TypeCtor::Slice | TypeCtor::Array => { | 1550 | st.as_single().clone() |
1530 | Ty::clone(&a_ty.parameters.as_single()) | 1551 | } |
1531 | } | ||
1532 | _ => self.new_type_var(), | ||
1533 | }, | ||
1534 | _ => self.new_type_var(), | 1552 | _ => self.new_type_var(), |
1535 | }; | 1553 | }; |
1536 | 1554 | ||
1537 | match array { | 1555 | match array { |
1538 | Array::ElementList(items) => { | 1556 | Array::ElementList(items) => { |
1539 | for expr in items.iter() { | 1557 | for expr in items.iter() { |
1540 | self.infer_expr(*expr, &Expectation::has_type(elem_ty.clone())); | 1558 | self.infer_expr_coerce(*expr, &Expectation::has_type(elem_ty.clone())); |
1541 | } | 1559 | } |
1542 | } | 1560 | } |
1543 | Array::Repeat { initializer, repeat } => { | 1561 | Array::Repeat { initializer, repeat } => { |
1544 | self.infer_expr(*initializer, &Expectation::has_type(elem_ty.clone())); | 1562 | self.infer_expr_coerce( |
1563 | *initializer, | ||
1564 | &Expectation::has_type(elem_ty.clone()), | ||
1565 | ); | ||
1545 | self.infer_expr( | 1566 | self.infer_expr( |
1546 | *repeat, | 1567 | *repeat, |
1547 | &Expectation::has_type(Ty::simple(TypeCtor::Int( | 1568 | &Expectation::has_type(Ty::simple(TypeCtor::Int( |
@@ -1588,12 +1609,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1588 | Statement::Let { pat, type_ref, initializer } => { | 1609 | Statement::Let { pat, type_ref, initializer } => { |
1589 | let decl_ty = | 1610 | let decl_ty = |
1590 | type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(Ty::Unknown); | 1611 | type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(Ty::Unknown); |
1591 | let decl_ty = self.insert_type_vars(decl_ty); | 1612 | |
1613 | // Always use the declared type when specified | ||
1614 | let mut ty = decl_ty.clone(); | ||
1615 | |||
1592 | if let Some(expr) = initializer { | 1616 | if let Some(expr) = initializer { |
1593 | self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty.clone())); | 1617 | let actual_ty = |
1618 | self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty.clone())); | ||
1619 | if decl_ty == Ty::Unknown { | ||
1620 | ty = actual_ty; | ||
1621 | } | ||
1594 | } | 1622 | } |
1595 | 1623 | ||
1596 | let ty = self.resolve_ty_as_possible(&mut vec![], decl_ty); | 1624 | let ty = self.resolve_ty_as_possible(&mut vec![], ty); |
1597 | self.infer_pat(*pat, &ty, BindingMode::default()); | 1625 | self.infer_pat(*pat, &ty, BindingMode::default()); |
1598 | } | 1626 | } |
1599 | Statement::Expr(expr) => { | 1627 | Statement::Expr(expr) => { |
@@ -1601,9 +1629,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1601 | } | 1629 | } |
1602 | } | 1630 | } |
1603 | } | 1631 | } |
1604 | let ty = | 1632 | |
1605 | if let Some(expr) = tail { self.infer_expr_inner(expr, expected) } else { Ty::unit() }; | 1633 | if let Some(expr) = tail { |
1606 | ty | 1634 | self.infer_expr_coerce(expr, expected) |
1635 | } else { | ||
1636 | self.coerce(&Ty::unit(), &expected.ty); | ||
1637 | Ty::unit() | ||
1638 | } | ||
1607 | } | 1639 | } |
1608 | 1640 | ||
1609 | fn check_call_arguments(&mut self, args: &[ExprId], param_tys: &[Ty]) { | 1641 | fn check_call_arguments(&mut self, args: &[ExprId], param_tys: &[Ty]) { |