diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 148 |
1 files changed, 104 insertions, 44 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index fa46ddfe9..5579db8fb 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -14,7 +14,7 @@ | |||
14 | //! rustc. | 14 | //! rustc. |
15 | 15 | ||
16 | mod autoderef; | 16 | mod autoderef; |
17 | mod primitive; | 17 | pub(crate) mod primitive; |
18 | #[cfg(test)] | 18 | #[cfg(test)] |
19 | mod tests; | 19 | mod tests; |
20 | pub(crate) mod method_resolution; | 20 | pub(crate) mod method_resolution; |
@@ -38,7 +38,7 @@ use crate::{ | |||
38 | db::HirDatabase, | 38 | db::HirDatabase, |
39 | type_ref::{TypeRef, Mutability}, | 39 | type_ref::{TypeRef, Mutability}, |
40 | name::KnownName, | 40 | name::KnownName, |
41 | expr::{Body, Expr, ExprId, PatId, UnaryOp, BinaryOp, Statement}, | 41 | expr::{Body, Expr, Literal, ExprId, PatId, UnaryOp, BinaryOp, Statement}, |
42 | }; | 42 | }; |
43 | 43 | ||
44 | fn transpose<T>(x: Cancelable<Option<T>>) -> Option<Cancelable<T>> { | 44 | fn transpose<T>(x: Cancelable<Option<T>>) -> Option<Cancelable<T>> { |
@@ -107,13 +107,35 @@ impl UnifyValue for TypeVarValue { | |||
107 | } | 107 | } |
108 | } | 108 | } |
109 | 109 | ||
110 | /// The kinds of placeholders we need during type inference. Currently, we only | 110 | /// The kinds of placeholders we need during type inference. There's separate |
111 | /// have type variables; in the future, we will probably also need int and float | 111 | /// values for general types, and for integer and float variables. The latter |
112 | /// variables, for inference of literal values (e.g. `100` could be one of | 112 | /// two are used for inference of literal values (e.g. `100` could be one of |
113 | /// several integer types). | 113 | /// several integer types). |
114 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 114 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
115 | pub enum InferTy { | 115 | pub enum InferTy { |
116 | TypeVar(TypeVarId), | 116 | TypeVar(TypeVarId), |
117 | IntVar(TypeVarId), | ||
118 | FloatVar(TypeVarId), | ||
119 | } | ||
120 | |||
121 | impl InferTy { | ||
122 | fn to_inner(self) -> TypeVarId { | ||
123 | match self { | ||
124 | InferTy::TypeVar(ty) | InferTy::IntVar(ty) | InferTy::FloatVar(ty) => ty, | ||
125 | } | ||
126 | } | ||
127 | |||
128 | fn fallback_value(self) -> Ty { | ||
129 | match self { | ||
130 | InferTy::TypeVar(..) => Ty::Unknown, | ||
131 | InferTy::IntVar(..) => { | ||
132 | Ty::Int(primitive::UncertainIntTy::Signed(primitive::IntTy::I32)) | ||
133 | } | ||
134 | InferTy::FloatVar(..) => { | ||
135 | Ty::Float(primitive::UncertainFloatTy::Known(primitive::FloatTy::F64)) | ||
136 | } | ||
137 | } | ||
138 | } | ||
117 | } | 139 | } |
118 | 140 | ||
119 | /// When inferring an expression, we propagate downward whatever type hint we | 141 | /// When inferring an expression, we propagate downward whatever type hint we |
@@ -151,14 +173,11 @@ pub enum Ty { | |||
151 | /// (a non-surrogate code point). Written as `char`. | 173 | /// (a non-surrogate code point). Written as `char`. |
152 | Char, | 174 | Char, |
153 | 175 | ||
154 | /// A primitive signed integer type. For example, `i32`. | 176 | /// A primitive integer type. For example, `i32`. |
155 | Int(primitive::IntTy), | 177 | Int(primitive::UncertainIntTy), |
156 | |||
157 | /// A primitive unsigned integer type. For example, `u32`. | ||
158 | Uint(primitive::UintTy), | ||
159 | 178 | ||
160 | /// A primitive floating-point type. For example, `f64`. | 179 | /// A primitive floating-point type. For example, `f64`. |
161 | Float(primitive::FloatTy), | 180 | Float(primitive::UncertainFloatTy), |
162 | 181 | ||
163 | /// Structures, enumerations and unions. | 182 | /// Structures, enumerations and unions. |
164 | Adt { | 183 | Adt { |
@@ -198,8 +217,9 @@ pub enum Ty { | |||
198 | // above function pointer type. Once we implement generics, we will probably | 217 | // above function pointer type. Once we implement generics, we will probably |
199 | // need this as well. | 218 | // need this as well. |
200 | 219 | ||
201 | // A trait, defined with `dyn trait`. | 220 | // A trait, defined with `dyn Trait`. |
202 | // Dynamic(), | 221 | // Dynamic(), |
222 | |||
203 | // The anonymous type of a closure. Used to represent the type of | 223 | // The anonymous type of a closure. Used to represent the type of |
204 | // `|a| a`. | 224 | // `|a| a`. |
205 | // Closure(DefId, ClosureSubsts<'tcx>), | 225 | // Closure(DefId, ClosureSubsts<'tcx>), |
@@ -312,20 +332,19 @@ impl Ty { | |||
312 | path: &Path, | 332 | path: &Path, |
313 | ) -> Cancelable<Self> { | 333 | ) -> Cancelable<Self> { |
314 | if let Some(name) = path.as_ident() { | 334 | if let Some(name) = path.as_ident() { |
315 | if let Some(KnownName::Bool) = name.as_known_name() { | 335 | if let Some(int_ty) = primitive::UncertainIntTy::from_name(name) { |
316 | return Ok(Ty::Bool); | ||
317 | } else if let Some(KnownName::Char) = name.as_known_name() { | ||
318 | return Ok(Ty::Char); | ||
319 | } else if let Some(KnownName::Str) = name.as_known_name() { | ||
320 | return Ok(Ty::Str); | ||
321 | } else if let Some(int_ty) = primitive::IntTy::from_name(name) { | ||
322 | return Ok(Ty::Int(int_ty)); | 336 | return Ok(Ty::Int(int_ty)); |
323 | } else if let Some(uint_ty) = primitive::UintTy::from_name(name) { | 337 | } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { |
324 | return Ok(Ty::Uint(uint_ty)); | ||
325 | } else if let Some(float_ty) = primitive::FloatTy::from_name(name) { | ||
326 | return Ok(Ty::Float(float_ty)); | 338 | return Ok(Ty::Float(float_ty)); |
327 | } else if name.as_known_name() == Some(KnownName::SelfType) { | 339 | } else if name.as_known_name() == Some(KnownName::SelfType) { |
328 | return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target_type())); | 340 | return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target_type())); |
341 | } else if let Some(known) = name.as_known_name() { | ||
342 | match known { | ||
343 | KnownName::Bool => return Ok(Ty::Bool), | ||
344 | KnownName::Char => return Ok(Ty::Char), | ||
345 | KnownName::Str => return Ok(Ty::Str), | ||
346 | _ => {} | ||
347 | } | ||
329 | } | 348 | } |
330 | } | 349 | } |
331 | 350 | ||
@@ -392,7 +411,6 @@ impl fmt::Display for Ty { | |||
392 | Ty::Bool => write!(f, "bool"), | 411 | Ty::Bool => write!(f, "bool"), |
393 | Ty::Char => write!(f, "char"), | 412 | Ty::Char => write!(f, "char"), |
394 | Ty::Int(t) => write!(f, "{}", t.ty_to_string()), | 413 | Ty::Int(t) => write!(f, "{}", t.ty_to_string()), |
395 | Ty::Uint(t) => write!(f, "{}", t.ty_to_string()), | ||
396 | Ty::Float(t) => write!(f, "{}", t.ty_to_string()), | 414 | Ty::Float(t) => write!(f, "{}", t.ty_to_string()), |
397 | Ty::Str => write!(f, "str"), | 415 | Ty::Str => write!(f, "str"), |
398 | Ty::Slice(t) => write!(f, "[{}]", t), | 416 | Ty::Slice(t) => write!(f, "[{}]", t), |
@@ -587,7 +605,7 @@ fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | |||
587 | | BinaryOp::BitwiseAnd | 605 | | BinaryOp::BitwiseAnd |
588 | | BinaryOp::BitwiseOr | 606 | | BinaryOp::BitwiseOr |
589 | | BinaryOp::BitwiseXor => match rhs_ty { | 607 | | BinaryOp::BitwiseXor => match rhs_ty { |
590 | Ty::Uint(..) | Ty::Int(..) | Ty::Float(..) => rhs_ty, | 608 | Ty::Int(..) | Ty::Float(..) => rhs_ty, |
591 | _ => Ty::Unknown, | 609 | _ => Ty::Unknown, |
592 | }, | 610 | }, |
593 | BinaryOp::RangeRightOpen | BinaryOp::RangeRightClosed => Ty::Unknown, | 611 | BinaryOp::RangeRightOpen | BinaryOp::RangeRightClosed => Ty::Unknown, |
@@ -598,7 +616,7 @@ fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | |||
598 | match op { | 616 | match op { |
599 | BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::Bool, | 617 | BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::Bool, |
600 | BinaryOp::Assignment | BinaryOp::EqualityTest => match lhs_ty { | 618 | BinaryOp::Assignment | BinaryOp::EqualityTest => match lhs_ty { |
601 | Ty::Uint(..) | Ty::Int(..) | Ty::Float(..) | Ty::Str | Ty::Char | Ty::Bool => lhs_ty, | 619 | Ty::Int(..) | Ty::Float(..) | Ty::Str | Ty::Char | Ty::Bool => lhs_ty, |
602 | _ => Ty::Unknown, | 620 | _ => Ty::Unknown, |
603 | }, | 621 | }, |
604 | BinaryOp::LesserEqualTest | 622 | BinaryOp::LesserEqualTest |
@@ -625,7 +643,7 @@ fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | |||
625 | | BinaryOp::BitwiseAnd | 643 | | BinaryOp::BitwiseAnd |
626 | | BinaryOp::BitwiseOr | 644 | | BinaryOp::BitwiseOr |
627 | | BinaryOp::BitwiseXor => match lhs_ty { | 645 | | BinaryOp::BitwiseXor => match lhs_ty { |
628 | Ty::Uint(..) | Ty::Int(..) | Ty::Float(..) => lhs_ty, | 646 | Ty::Int(..) | Ty::Float(..) => lhs_ty, |
629 | _ => Ty::Unknown, | 647 | _ => Ty::Unknown, |
630 | }, | 648 | }, |
631 | _ => Ty::Unknown, | 649 | _ => Ty::Unknown, |
@@ -695,13 +713,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
695 | match (&*ty1, &*ty2) { | 713 | match (&*ty1, &*ty2) { |
696 | (Ty::Unknown, ..) => true, | 714 | (Ty::Unknown, ..) => true, |
697 | (.., Ty::Unknown) => true, | 715 | (.., Ty::Unknown) => true, |
698 | (Ty::Bool, _) | 716 | (Ty::Int(t1), Ty::Int(t2)) => match (t1, t2) { |
699 | | (Ty::Str, _) | 717 | (primitive::UncertainIntTy::Unknown, _) |
700 | | (Ty::Never, _) | 718 | | (_, primitive::UncertainIntTy::Unknown) => true, |
701 | | (Ty::Char, _) | 719 | _ => t1 == t2, |
702 | | (Ty::Int(..), Ty::Int(..)) | 720 | }, |
703 | | (Ty::Uint(..), Ty::Uint(..)) | 721 | (Ty::Float(t1), Ty::Float(t2)) => match (t1, t2) { |
704 | | (Ty::Float(..), Ty::Float(..)) => ty1 == ty2, | 722 | (primitive::UncertainFloatTy::Unknown, _) |
723 | | (_, primitive::UncertainFloatTy::Unknown) => true, | ||
724 | _ => t1 == t2, | ||
725 | }, | ||
726 | (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2, | ||
705 | ( | 727 | ( |
706 | Ty::Adt { | 728 | Ty::Adt { |
707 | def_id: def_id1, .. | 729 | def_id: def_id1, .. |
@@ -718,12 +740,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
718 | .iter() | 740 | .iter() |
719 | .zip(ts2.iter()) | 741 | .zip(ts2.iter()) |
720 | .all(|(t1, t2)| self.unify(t1, t2)), | 742 | .all(|(t1, t2)| self.unify(t1, t2)), |
721 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) => { | 743 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) |
744 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) | ||
745 | | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => { | ||
722 | // both type vars are unknown since we tried to resolve them | 746 | // both type vars are unknown since we tried to resolve them |
723 | self.var_unification_table.union(*tv1, *tv2); | 747 | self.var_unification_table.union(*tv1, *tv2); |
724 | true | 748 | true |
725 | } | 749 | } |
726 | (Ty::Infer(InferTy::TypeVar(tv)), other) | (other, Ty::Infer(InferTy::TypeVar(tv))) => { | 750 | (Ty::Infer(InferTy::TypeVar(tv)), other) |
751 | | (other, Ty::Infer(InferTy::TypeVar(tv))) | ||
752 | | (Ty::Infer(InferTy::IntVar(tv)), other) | ||
753 | | (other, Ty::Infer(InferTy::IntVar(tv))) | ||
754 | | (Ty::Infer(InferTy::FloatVar(tv)), other) | ||
755 | | (other, Ty::Infer(InferTy::FloatVar(tv))) => { | ||
727 | // the type var is unknown since we tried to resolve it | 756 | // the type var is unknown since we tried to resolve it |
728 | self.var_unification_table | 757 | self.var_unification_table |
729 | .union_value(*tv, TypeVarValue::Known(other.clone())); | 758 | .union_value(*tv, TypeVarValue::Known(other.clone())); |
@@ -739,10 +768,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
739 | )) | 768 | )) |
740 | } | 769 | } |
741 | 770 | ||
771 | fn new_integer_var(&mut self) -> Ty { | ||
772 | Ty::Infer(InferTy::IntVar( | ||
773 | self.var_unification_table.new_key(TypeVarValue::Unknown), | ||
774 | )) | ||
775 | } | ||
776 | |||
777 | fn new_float_var(&mut self) -> Ty { | ||
778 | Ty::Infer(InferTy::FloatVar( | ||
779 | self.var_unification_table.new_key(TypeVarValue::Unknown), | ||
780 | )) | ||
781 | } | ||
782 | |||
742 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. | 783 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. |
743 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { | 784 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { |
744 | match ty { | 785 | match ty { |
745 | Ty::Unknown => self.new_type_var(), | 786 | Ty::Unknown => self.new_type_var(), |
787 | Ty::Int(primitive::UncertainIntTy::Unknown) => self.new_integer_var(), | ||
788 | Ty::Float(primitive::UncertainFloatTy::Unknown) => self.new_float_var(), | ||
746 | _ => ty, | 789 | _ => ty, |
747 | } | 790 | } |
748 | } | 791 | } |
@@ -757,12 +800,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
757 | /// known type. | 800 | /// known type. |
758 | fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty { | 801 | fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty { |
759 | ty.fold(&mut |ty| match ty { | 802 | ty.fold(&mut |ty| match ty { |
760 | Ty::Infer(InferTy::TypeVar(tv)) => { | 803 | Ty::Infer(tv) => { |
761 | if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() { | 804 | let inner = tv.to_inner(); |
805 | if let Some(known_ty) = self.var_unification_table.probe_value(inner).known() { | ||
762 | // known_ty may contain other variables that are known by now | 806 | // known_ty may contain other variables that are known by now |
763 | self.resolve_ty_as_possible(known_ty.clone()) | 807 | self.resolve_ty_as_possible(known_ty.clone()) |
764 | } else { | 808 | } else { |
765 | Ty::Infer(InferTy::TypeVar(tv)) | 809 | ty |
766 | } | 810 | } |
767 | } | 811 | } |
768 | _ => ty, | 812 | _ => ty, |
@@ -773,8 +817,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
773 | /// otherwise, return ty. | 817 | /// otherwise, return ty. |
774 | fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { | 818 | fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { |
775 | match ty { | 819 | match ty { |
776 | Ty::Infer(InferTy::TypeVar(tv)) => { | 820 | Ty::Infer(tv) => { |
777 | match self.var_unification_table.probe_value(*tv).known() { | 821 | let inner = tv.to_inner(); |
822 | match self.var_unification_table.probe_value(inner).known() { | ||
778 | Some(known_ty) => { | 823 | Some(known_ty) => { |
779 | // The known_ty can't be a type var itself | 824 | // The known_ty can't be a type var itself |
780 | Cow::Owned(known_ty.clone()) | 825 | Cow::Owned(known_ty.clone()) |
@@ -790,12 +835,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
790 | /// replaced by Ty::Unknown. | 835 | /// replaced by Ty::Unknown. |
791 | fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { | 836 | fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { |
792 | ty.fold(&mut |ty| match ty { | 837 | ty.fold(&mut |ty| match ty { |
793 | Ty::Infer(InferTy::TypeVar(tv)) => { | 838 | Ty::Infer(tv) => { |
794 | if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() { | 839 | let inner = tv.to_inner(); |
840 | if let Some(known_ty) = self.var_unification_table.probe_value(inner).known() { | ||
795 | // known_ty may contain other variables that are known by now | 841 | // known_ty may contain other variables that are known by now |
796 | self.resolve_ty_completely(known_ty.clone()) | 842 | self.resolve_ty_completely(known_ty.clone()) |
797 | } else { | 843 | } else { |
798 | Ty::Unknown | 844 | tv.fallback_value() |
799 | } | 845 | } |
800 | } | 846 | } |
801 | _ => ty, | 847 | _ => ty, |
@@ -1067,6 +1113,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1067 | 1113 | ||
1068 | Ty::Tuple(Arc::from(ty_vec)) | 1114 | Ty::Tuple(Arc::from(ty_vec)) |
1069 | } | 1115 | } |
1116 | Expr::Literal(lit) => match lit { | ||
1117 | Literal::Bool(..) => Ty::Bool, | ||
1118 | Literal::String(..) => Ty::Ref(Arc::new(Ty::Str), Mutability::Shared), | ||
1119 | Literal::ByteString(..) => { | ||
1120 | let byte_type = Arc::new(Ty::Int(primitive::UncertainIntTy::Unsigned( | ||
1121 | primitive::UintTy::U8, | ||
1122 | ))); | ||
1123 | let slice_type = Arc::new(Ty::Slice(byte_type)); | ||
1124 | Ty::Ref(slice_type, Mutability::Shared) | ||
1125 | } | ||
1126 | Literal::Char(..) => Ty::Char, | ||
1127 | Literal::Int(_v, ty) => Ty::Int(*ty), | ||
1128 | Literal::Float(_v, ty) => Ty::Float(*ty), | ||
1129 | }, | ||
1070 | }; | 1130 | }; |
1071 | // use a new type variable if we got Ty::Unknown here | 1131 | // use a new type variable if we got Ty::Unknown here |
1072 | let ty = self.insert_type_vars_shallow(ty); | 1132 | let ty = self.insert_type_vars_shallow(ty); |