aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-01-14 20:58:20 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-01-14 20:58:20 +0000
commite8e82ce032f8678929b015e6f70ac060bb2cf94c (patch)
tree9fb158e9f7115bb70cf2b8623b70710c55497ed4 /crates/ra_hir
parent784ff638e549a27503b719e5c2f0009b40d25364 (diff)
parent37ba237e6686d94783d1f025d23823ad7c0cb0c8 (diff)
Merge #485
485: Add type inference for a bunch of primitives r=flodiebold a=marcusklaas This PR adds inference for `&str`, `&[u8]`, `char`, `bool`, floats and integers. For floats and integers it uses type variables to infer the exact type, i.e. `u32`, from context when it's not annotated explicitly. I'm not quite happy with the implementation yet, but I think it mostly works now. Co-authored-by: Marcus Klaas de Vries <[email protected]>
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/expr.rs56
-rw-r--r--crates/ra_hir/src/name.rs2
-rw-r--r--crates/ra_hir/src/ty.rs148
-rw-r--r--crates/ra_hir/src/ty/primitive.rs50
-rw-r--r--crates/ra_hir/src/ty/tests.rs30
-rw-r--r--crates/ra_hir/src/ty/tests/data/basics.txt8
-rw-r--r--crates/ra_hir/src/ty/tests/data/binary_op.txt86
-rw-r--r--crates/ra_hir/src/ty/tests/data/let.txt4
-rw-r--r--crates/ra_hir/src/ty/tests/data/literals.txt12
-rw-r--r--crates/ra_hir/src/ty/tests/data/struct.txt4
-rw-r--r--crates/ra_hir/src/ty/tests/data/tuple.txt18
11 files changed, 308 insertions, 110 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index f0936e9f3..5081466a2 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -5,9 +5,12 @@ use rustc_hash::FxHashMap;
5 5
6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; 6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
7use ra_db::{LocalSyntaxPtr, Cancelable}; 7use ra_db::{LocalSyntaxPtr, Cancelable};
8use ra_syntax::ast::{self, AstNode, LoopBodyOwner, ArgListOwner, NameOwner}; 8use ra_syntax::{
9 ast::{self, AstNode, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor}
10};
9 11
10use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName}; 12use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName};
13use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy};
11 14
12#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub struct ExprId(RawId); 16pub struct ExprId(RawId);
@@ -104,6 +107,16 @@ impl BodySyntaxMapping {
104} 107}
105 108
106#[derive(Debug, Clone, Eq, PartialEq)] 109#[derive(Debug, Clone, Eq, PartialEq)]
110pub enum Literal {
111 String(String),
112 ByteString(Vec<u8>),
113 Char(char),
114 Bool(bool),
115 Int(u64, UncertainIntTy),
116 Float(u64, UncertainFloatTy), // FIXME: f64 is not Eq
117}
118
119#[derive(Debug, Clone, Eq, PartialEq)]
107pub enum Expr { 120pub enum Expr {
108 /// This is produced if syntax tree does not have a required expression piece. 121 /// This is produced if syntax tree does not have a required expression piece.
109 Missing, 122 Missing,
@@ -186,6 +199,7 @@ pub enum Expr {
186 Tuple { 199 Tuple {
187 exprs: Vec<ExprId>, 200 exprs: Vec<ExprId>,
188 }, 201 },
202 Literal(Literal),
189} 203}
190 204
191pub use ra_syntax::ast::PrefixOp as UnaryOp; 205pub use ra_syntax::ast::PrefixOp as UnaryOp;
@@ -305,6 +319,7 @@ impl Expr {
305 f(*expr); 319 f(*expr);
306 } 320 }
307 } 321 }
322 Expr::Literal(_) => {}
308 } 323 }
309 } 324 }
310} 325}
@@ -633,13 +648,50 @@ impl ExprCollector {
633 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect(); 648 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect();
634 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr) 649 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
635 } 650 }
651 ast::ExprKind::Literal(e) => {
652 let child = if let Some(child) = e.literal_expr() {
653 child
654 } else {
655 return self.alloc_expr(Expr::Missing, syntax_ptr);
656 };
657
658 let lit = match child.flavor() {
659 LiteralFlavor::IntNumber { suffix } => {
660 let known_name = suffix
661 .map(|s| Name::new(s))
662 .and_then(|name| UncertainIntTy::from_name(&name));
663
664 Literal::Int(
665 Default::default(),
666 known_name.unwrap_or(UncertainIntTy::Unknown),
667 )
668 }
669 LiteralFlavor::FloatNumber { suffix } => {
670 let known_name = suffix
671 .map(|s| Name::new(s))
672 .and_then(|name| UncertainFloatTy::from_name(&name));
673
674 Literal::Float(
675 Default::default(),
676 known_name.unwrap_or(UncertainFloatTy::Unknown),
677 )
678 }
679 LiteralFlavor::ByteString => Literal::ByteString(Default::default()),
680 LiteralFlavor::String => Literal::String(Default::default()),
681 LiteralFlavor::Byte => {
682 Literal::Int(Default::default(), UncertainIntTy::Unsigned(UintTy::U8))
683 }
684 LiteralFlavor::Bool => Literal::Bool(Default::default()),
685 LiteralFlavor::Char => Literal::Char(Default::default()),
686 };
687 self.alloc_expr(Expr::Literal(lit), syntax_ptr)
688 }
636 689
637 // TODO implement HIR for these: 690 // TODO implement HIR for these:
638 ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 691 ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
639 ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 692 ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
640 ast::ExprKind::ArrayExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 693 ast::ExprKind::ArrayExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
641 ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 694 ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
642 ast::ExprKind::Literal(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
643 } 695 }
644 } 696 }
645 697
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
index d9683549c..8d786d2ac 100644
--- a/crates/ra_hir/src/name.rs
+++ b/crates/ra_hir/src/name.rs
@@ -23,7 +23,7 @@ impl fmt::Debug for Name {
23} 23}
24 24
25impl Name { 25impl Name {
26 fn new(text: SmolStr) -> Name { 26 pub(crate) fn new(text: SmolStr) -> Name {
27 Name { text } 27 Name { text }
28 } 28 }
29 29
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
16mod autoderef; 16mod autoderef;
17mod primitive; 17pub(crate) mod primitive;
18#[cfg(test)] 18#[cfg(test)]
19mod tests; 19mod tests;
20pub(crate) mod method_resolution; 20pub(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
44fn transpose<T>(x: Cancelable<Option<T>>) -> Option<Cancelable<T>> { 44fn 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)]
115pub enum InferTy { 115pub enum InferTy {
116 TypeVar(TypeVarId), 116 TypeVar(TypeVarId),
117 IntVar(TypeVarId),
118 FloatVar(TypeVarId),
119}
120
121impl 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);
diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs
index 498d42d52..5741ca90d 100644
--- a/crates/ra_hir/src/ty/primitive.rs
+++ b/crates/ra_hir/src/ty/primitive.rs
@@ -2,6 +2,56 @@ use std::fmt;
2 2
3use crate::{Name, KnownName}; 3use crate::{Name, KnownName};
4 4
5#[derive(Debug, Clone, Eq, PartialEq, Hash, Copy)]
6pub enum UncertainIntTy {
7 Unknown,
8 Unsigned(UintTy),
9 Signed(IntTy),
10}
11
12impl UncertainIntTy {
13 pub fn ty_to_string(&self) -> &'static str {
14 match *self {
15 UncertainIntTy::Unknown => "{integer}",
16 UncertainIntTy::Signed(ty) => ty.ty_to_string(),
17 UncertainIntTy::Unsigned(ty) => ty.ty_to_string(),
18 }
19 }
20
21 pub fn from_name(name: &Name) -> Option<UncertainIntTy> {
22 if let Some(ty) = IntTy::from_name(name) {
23 Some(UncertainIntTy::Signed(ty))
24 } else if let Some(ty) = UintTy::from_name(name) {
25 Some(UncertainIntTy::Unsigned(ty))
26 } else {
27 None
28 }
29 }
30}
31
32#[derive(Debug, Clone, Eq, PartialEq, Hash, Copy)]
33pub enum UncertainFloatTy {
34 Unknown,
35 Known(FloatTy),
36}
37
38impl UncertainFloatTy {
39 pub fn ty_to_string(&self) -> &'static str {
40 match *self {
41 UncertainFloatTy::Unknown => "{float}",
42 UncertainFloatTy::Known(ty) => ty.ty_to_string(),
43 }
44 }
45
46 pub fn from_name(name: &Name) -> Option<UncertainFloatTy> {
47 if let Some(ty) = FloatTy::from_name(name) {
48 Some(UncertainFloatTy::Known(ty))
49 } else {
50 None
51 }
52 }
53}
54
5#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] 55#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
6pub enum IntTy { 56pub enum IntTy {
7 Isize, 57 Isize,
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 920188fc9..8aacb1a7f 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -133,6 +133,32 @@ fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
133} 133}
134 134
135#[test] 135#[test]
136fn infer_literals() {
137 check_inference(
138 r##"
139fn test() {
140 5i32;
141 "hello";
142 b"bytes";
143 'c';
144 b'b';
145 3.14;
146 5000;
147 false;
148 true;
149 r#"
150 //! doc
151 // non-doc
152 mod foo {}
153 "#;
154 br#"yolo"#;
155}
156"##,
157 "literals.txt",
158 );
159}
160
161#[test]
136fn infer_backwards() { 162fn infer_backwards() {
137 check_inference( 163 check_inference(
138 r#" 164 r#"
@@ -180,7 +206,7 @@ fn f(x: bool) -> i32 {
180 0i32 206 0i32
181} 207}
182 208
183fn test() { 209fn test() -> bool {
184 let x = a && b; 210 let x = a && b;
185 let y = true || false; 211 let y = true || false;
186 let z = x == y; 212 let z = x == y;
@@ -277,8 +303,6 @@ fn test(x: &str, y: isize) {
277 let b = (a, x); 303 let b = (a, x);
278 let c = (y, x); 304 let c = (y, x);
279 let d = (c, x); 305 let d = (c, x);
280
281 // we have not infered these case yet.
282 let e = (1, "e"); 306 let e = (1, "e");
283 let f = (e, "d"); 307 let f = (e, "d");
284} 308}
diff --git a/crates/ra_hir/src/ty/tests/data/basics.txt b/crates/ra_hir/src/ty/tests/data/basics.txt
index ac7faae0a..e65fe07aa 100644
--- a/crates/ra_hir/src/ty/tests/data/basics.txt
+++ b/crates/ra_hir/src/ty/tests/data/basics.txt
@@ -7,7 +7,7 @@
7[55; 56) 'b': isize 7[55; 56) 'b': isize
8[62; 63) 'c': ! 8[62; 63) 'c': !
9[69; 70) 'd': &str 9[69; 70) 'd': &str
10[76; 82) '1usize': [unknown] 10[76; 82) '1usize': usize
11[88; 94) '1isize': [unknown] 11[88; 94) '1isize': isize
12[100; 106) '"test"': [unknown] 12[100; 106) '"test"': &str
13[112; 118) '1.0f32': [unknown] 13[112; 118) '1.0f32': f32
diff --git a/crates/ra_hir/src/ty/tests/data/binary_op.txt b/crates/ra_hir/src/ty/tests/data/binary_op.txt
index 8a515ac5e..58a727691 100644
--- a/crates/ra_hir/src/ty/tests/data/binary_op.txt
+++ b/crates/ra_hir/src/ty/tests/data/binary_op.txt
@@ -1,46 +1,46 @@
1[6; 7) 'x': bool 1[6; 7) 'x': bool
2[22; 34) '{ 0i32 }': i32 2[22; 34) '{ 0i32 }': i32
3[28; 32) '0i32': i32 3[28; 32) '0i32': i32
4[46; 342) '{ ... < 3 }': bool 4[54; 350) '{ ... < 3 }': bool
5[56; 57) 'x': bool 5[64; 65) 'x': bool
6[60; 61) 'a': bool 6[68; 69) 'a': bool
7[60; 66) 'a && b': bool 7[68; 74) 'a && b': bool
8[65; 66) 'b': bool 8[73; 74) 'b': bool
9[76; 77) 'y': bool 9[84; 85) 'y': bool
10[80; 84) 'true': bool 10[88; 92) 'true': bool
11[80; 93) 'true || false': bool 11[88; 101) 'true || false': bool
12[88; 93) 'false': bool 12[96; 101) 'false': bool
13[103; 104) 'z': bool 13[111; 112) 'z': bool
14[107; 108) 'x': bool 14[115; 116) 'x': bool
15[107; 113) 'x == y': bool 15[115; 121) 'x == y': bool
16[112; 113) 'y': bool 16[120; 121) 'y': bool
17[123; 134) 'minus_forty': isize 17[131; 142) 'minus_forty': isize
18[144; 152) '-40isize': isize 18[152; 160) '-40isize': isize
19[145; 152) '40isize': [unknown] 19[153; 160) '40isize': isize
20[162; 163) 'h': bool 20[170; 171) 'h': bool
21[166; 177) 'minus_forty': isize 21[174; 185) 'minus_forty': isize
22[166; 188) 'minus_...ONST_2': bool 22[174; 196) 'minus_...ONST_2': bool
23[181; 188) 'CONST_2': isize 23[189; 196) 'CONST_2': isize
24[198; 199) 'c': i32 24[206; 207) 'c': i32
25[202; 203) 'f': fn(bool) -> i32 25[210; 211) 'f': fn(bool) -> i32
26[202; 211) 'f(z || y)': i32 26[210; 219) 'f(z || y)': i32
27[202; 215) 'f(z || y) + 5': i32 27[210; 223) 'f(z || y) + 5': i32
28[204; 205) 'z': bool 28[212; 213) 'z': bool
29[204; 210) 'z || y': bool 29[212; 218) 'z || y': bool
30[209; 210) 'y': bool 30[217; 218) 'y': bool
31[214; 215) '5': i32 31[222; 223) '5': i32
32[225; 226) 'd': [unknown] 32[233; 234) 'd': [unknown]
33[229; 230) 'b': [unknown] 33[237; 238) 'b': [unknown]
34[240; 241) 'g': () 34[248; 249) 'g': ()
35[244; 255) 'minus_forty': isize 35[252; 263) 'minus_forty': isize
36[244; 260) 'minus_...y ^= i': () 36[252; 268) 'minus_...y ^= i': ()
37[259; 260) 'i': isize 37[267; 268) 'i': isize
38[270; 273) 'ten': usize 38[278; 281) 'ten': usize
39[283; 285) '10': usize 39[291; 293) '10': usize
40[295; 308) 'ten_is_eleven': bool 40[303; 316) 'ten_is_eleven': bool
41[311; 314) 'ten': usize 41[319; 322) 'ten': usize
42[311; 326) 'ten == some_num': bool 42[319; 334) 'ten == some_num': bool
43[318; 326) 'some_num': usize 43[326; 334) 'some_num': usize
44[333; 336) 'ten': usize 44[341; 344) 'ten': usize
45[333; 340) 'ten < 3': bool 45[341; 348) 'ten < 3': bool
46[339; 340) '3': usize 46[347; 348) '3': usize
diff --git a/crates/ra_hir/src/ty/tests/data/let.txt b/crates/ra_hir/src/ty/tests/data/let.txt
index 30f4a2cf5..8815dba41 100644
--- a/crates/ra_hir/src/ty/tests/data/let.txt
+++ b/crates/ra_hir/src/ty/tests/data/let.txt
@@ -1,6 +1,6 @@
1[11; 71) '{ ...= b; }': () 1[11; 71) '{ ...= b; }': ()
2[21; 22) 'a': [unknown] 2[21; 22) 'a': isize
3[25; 31) '1isize': [unknown] 3[25; 31) '1isize': isize
4[41; 42) 'b': usize 4[41; 42) 'b': usize
5[52; 53) '1': usize 5[52; 53) '1': usize
6[63; 64) 'c': usize 6[63; 64) 'c': usize
diff --git a/crates/ra_hir/src/ty/tests/data/literals.txt b/crates/ra_hir/src/ty/tests/data/literals.txt
new file mode 100644
index 000000000..84ee2c11b
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/literals.txt
@@ -0,0 +1,12 @@
1[11; 201) '{ ...o"#; }': ()
2[17; 21) '5i32': i32
3[27; 34) '"hello"': &str
4[40; 48) 'b"bytes"': &[u8]
5[54; 57) ''c'': char
6[63; 67) 'b'b'': u8
7[73; 77) '3.14': f64
8[83; 87) '5000': i32
9[93; 98) 'false': bool
10[104; 108) 'true': bool
11[114; 182) 'r#" ... "#': &str
12[188; 198) 'br#"yolo"#': &[u8]
diff --git a/crates/ra_hir/src/ty/tests/data/struct.txt b/crates/ra_hir/src/ty/tests/data/struct.txt
index 7b324c82f..be9e12d02 100644
--- a/crates/ra_hir/src/ty/tests/data/struct.txt
+++ b/crates/ra_hir/src/ty/tests/data/struct.txt
@@ -2,14 +2,14 @@
2[82; 83) 'c': [unknown] 2[82; 83) 'c': [unknown]
3[86; 87) 'C': [unknown] 3[86; 87) 'C': [unknown]
4[86; 90) 'C(1)': [unknown] 4[86; 90) 'C(1)': [unknown]
5[88; 89) '1': [unknown] 5[88; 89) '1': i32
6[96; 97) 'B': [unknown] 6[96; 97) 'B': [unknown]
7[107; 108) 'a': A 7[107; 108) 'a': A
8[114; 133) 'A { b:...C(1) }': A 8[114; 133) 'A { b:...C(1) }': A
9[121; 122) 'B': B 9[121; 122) 'B': B
10[127; 128) 'C': [unknown] 10[127; 128) 'C': [unknown]
11[127; 131) 'C(1)': C 11[127; 131) 'C(1)': C
12[129; 130) '1': [unknown] 12[129; 130) '1': i32
13[139; 140) 'a': A 13[139; 140) 'a': A
14[139; 142) 'a.b': B 14[139; 142) 'a.b': B
15[148; 149) 'a': A 15[148; 149) 'a': A
diff --git a/crates/ra_hir/src/ty/tests/data/tuple.txt b/crates/ra_hir/src/ty/tests/data/tuple.txt
index 96169180d..a95d3c286 100644
--- a/crates/ra_hir/src/ty/tests/data/tuple.txt
+++ b/crates/ra_hir/src/ty/tests/data/tuple.txt
@@ -1,6 +1,6 @@
1[9; 10) 'x': &str 1[9; 10) 'x': &str
2[18; 19) 'y': isize 2[18; 19) 'y': isize
3[28; 214) '{ ...d"); }': () 3[28; 170) '{ ...d"); }': ()
4[38; 39) 'a': (u32, &str) 4[38; 39) 'a': (u32, &str)
5[55; 63) '(1, "a")': (u32, &str) 5[55; 63) '(1, "a")': (u32, &str)
6[56; 57) '1': u32 6[56; 57) '1': u32
@@ -17,11 +17,11 @@
17[117; 123) '(c, x)': ((isize, &str), &str) 17[117; 123) '(c, x)': ((isize, &str), &str)
18[118; 119) 'c': (isize, &str) 18[118; 119) 'c': (isize, &str)
19[121; 122) 'x': &str 19[121; 122) 'x': &str
20[177; 178) 'e': ([unknown], [unknown]) 20[133; 134) 'e': (i32, &str)
21[181; 189) '(1, "e")': ([unknown], [unknown]) 21[137; 145) '(1, "e")': (i32, &str)
22[182; 183) '1': [unknown] 22[138; 139) '1': i32
23[185; 188) '"e"': [unknown] 23[141; 144) '"e"': &str
24[199; 200) 'f': (([unknown], [unknown]), [unknown]) 24[155; 156) 'f': ((i32, &str), &str)
25[203; 211) '(e, "d")': (([unknown], [unknown]), [unknown]) 25[159; 167) '(e, "d")': ((i32, &str), &str)
26[204; 205) 'e': ([unknown], [unknown]) 26[160; 161) 'e': (i32, &str)
27[207; 210) '"d"': [unknown] 27[163; 166) '"d"': &str