aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Klaas de Vries <[email protected]>2019-01-10 17:08:54 +0000
committerMarcus Klaas de Vries <[email protected]>2019-01-14 12:54:31 +0000
commit1574715be5d3fc7e07160708810dcbc9c1b01733 (patch)
treec482c99282393d75606c4487d316103b14208561
parent5f5dc20d85dead5fbd51d163451f796255c9faea (diff)
Use type variables to determine exact type for ambiguous numeric literals
-rw-r--r--crates/ra_hir/src/expr.rs17
-rw-r--r--crates/ra_hir/src/ty.rs45
-rw-r--r--crates/ra_hir/src/ty/tests.rs1
-rw-r--r--crates/ra_hir/src/ty/tests/data/basics.txt2
-rw-r--r--crates/ra_hir/src/ty/tests/data/literals.txt9
-rw-r--r--crates/ra_hir/src/ty/tests/data/struct.txt4
6 files changed, 64 insertions, 14 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index bc8515836..2798937a6 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -699,7 +699,22 @@ impl ExprCollector {
699 // TODO: actually parse integer 699 // TODO: actually parse integer
700 Literal::Int(0u64, ty) 700 Literal::Int(0u64, ty)
701 } 701 }
702 SyntaxKind::FLOAT_NUMBER => Literal::Float(0, UncertainFloatTy::Unknown), 702 SyntaxKind::FLOAT_NUMBER => {
703 let text = c.text().to_string();
704
705 // FIXME: don't do it like this. maybe use something like
706 // the IntTy::from_name functions
707 let ty = if text.ends_with("f64") {
708 UncertainFloatTy::Known(FloatTy::F64)
709 } else if text.ends_with("f32") {
710 UncertainFloatTy::Known(FloatTy::F32)
711 } else {
712 UncertainFloatTy::Unknown
713 };
714
715 // TODO: actually parse value
716 Literal::Float(0, ty)
717 }
703 SyntaxKind::STRING => { 718 SyntaxKind::STRING => {
704 // FIXME: this likely includes the " characters 719 // FIXME: this likely includes the " characters
705 let text = c.text().to_string(); 720 let text = c.text().to_string();
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 13a1c2907..b4b338874 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -114,6 +114,8 @@ impl UnifyValue for TypeVarValue {
114#[derive(Clone, PartialEq, Eq, Hash, Debug)] 114#[derive(Clone, PartialEq, Eq, Hash, Debug)]
115pub enum InferTy { 115pub enum InferTy {
116 TypeVar(TypeVarId), 116 TypeVar(TypeVarId),
117 IntVar(TypeVarId),
118 FloatVar(TypeVarId),
117} 119}
118 120
119/// When inferring an expression, we propagate downward whatever type hint we 121/// When inferring an expression, we propagate downward whatever type hint we
@@ -718,12 +720,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
718 .iter() 720 .iter()
719 .zip(ts2.iter()) 721 .zip(ts2.iter())
720 .all(|(t1, t2)| self.unify(t1, t2)), 722 .all(|(t1, t2)| self.unify(t1, t2)),
721 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) => { 723 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2)))
724 | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2)))
725 | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => {
722 // both type vars are unknown since we tried to resolve them 726 // both type vars are unknown since we tried to resolve them
723 self.var_unification_table.union(*tv1, *tv2); 727 self.var_unification_table.union(*tv1, *tv2);
724 true 728 true
725 } 729 }
726 (Ty::Infer(InferTy::TypeVar(tv)), other) | (other, Ty::Infer(InferTy::TypeVar(tv))) => { 730 (Ty::Infer(InferTy::TypeVar(tv)), other)
731 | (other, Ty::Infer(InferTy::TypeVar(tv)))
732 | (Ty::Infer(InferTy::IntVar(tv)), other)
733 | (other, Ty::Infer(InferTy::IntVar(tv)))
734 | (Ty::Infer(InferTy::FloatVar(tv)), other)
735 | (other, Ty::Infer(InferTy::FloatVar(tv))) => {
727 // the type var is unknown since we tried to resolve it 736 // the type var is unknown since we tried to resolve it
728 self.var_unification_table 737 self.var_unification_table
729 .union_value(*tv, TypeVarValue::Known(other.clone())); 738 .union_value(*tv, TypeVarValue::Known(other.clone()));
@@ -739,10 +748,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
739 )) 748 ))
740 } 749 }
741 750
751 fn new_integer_var(&mut self) -> Ty {
752 Ty::Infer(InferTy::IntVar(
753 self.var_unification_table.new_key(TypeVarValue::Unknown),
754 ))
755 }
756
757 fn new_float_var(&mut self) -> Ty {
758 Ty::Infer(InferTy::FloatVar(
759 self.var_unification_table.new_key(TypeVarValue::Unknown),
760 ))
761 }
762
742 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. 763 /// 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 { 764 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
744 match ty { 765 match ty {
745 Ty::Unknown => self.new_type_var(), 766 Ty::Unknown => self.new_type_var(),
767 Ty::Int(primitive::UncertainIntTy::Unknown) => self.new_integer_var(),
768 Ty::Float(primitive::UncertainFloatTy::Unknown) => self.new_float_var(),
746 _ => ty, 769 _ => ty,
747 } 770 }
748 } 771 }
@@ -757,12 +780,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
757 /// known type. 780 /// known type.
758 fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty { 781 fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
759 ty.fold(&mut |ty| match ty { 782 ty.fold(&mut |ty| match ty {
760 Ty::Infer(InferTy::TypeVar(tv)) => { 783 Ty::Infer(InferTy::TypeVar(tv))
784 | Ty::Infer(InferTy::IntVar(tv))
785 | Ty::Infer(InferTy::FloatVar(tv)) => {
761 if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() { 786 if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() {
762 // known_ty may contain other variables that are known by now 787 // known_ty may contain other variables that are known by now
763 self.resolve_ty_as_possible(known_ty.clone()) 788 self.resolve_ty_as_possible(known_ty.clone())
764 } else { 789 } else {
765 Ty::Infer(InferTy::TypeVar(tv)) 790 ty
766 } 791 }
767 } 792 }
768 _ => ty, 793 _ => ty,
@@ -790,12 +815,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
790 /// replaced by Ty::Unknown. 815 /// replaced by Ty::Unknown.
791 fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { 816 fn resolve_ty_completely(&mut self, ty: Ty) -> Ty {
792 ty.fold(&mut |ty| match ty { 817 ty.fold(&mut |ty| match ty {
793 Ty::Infer(InferTy::TypeVar(tv)) => { 818 Ty::Infer(i) => {
819 let tv = match i {
820 InferTy::TypeVar(tv) | InferTy::IntVar(tv) | InferTy::FloatVar(tv) => tv,
821 };
822
794 if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() { 823 if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() {
795 // known_ty may contain other variables that are known by now 824 // known_ty may contain other variables that are known by now
796 self.resolve_ty_completely(known_ty.clone()) 825 self.resolve_ty_completely(known_ty.clone())
797 } else { 826 } else {
798 Ty::Unknown 827 match i {
828 InferTy::TypeVar(..) => Ty::Unknown,
829 InferTy::IntVar(..) => Ty::Int(primitive::UncertainIntTy::Unknown),
830 InferTy::FloatVar(..) => Ty::Float(primitive::UncertainFloatTy::Unknown),
831 }
799 } 832 }
800 } 833 }
801 _ => ty, 834 _ => ty,
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 97d3d222f..0c43415a6 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -145,6 +145,7 @@ fn test() {
145 3.14; 145 3.14;
146 5000; 146 5000;
147 (0u32, -5isize); 147 (0u32, -5isize);
148 false;
148 [true, true, false] 149 [true, true, false]
149} 150}
150"#, 151"#,
diff --git a/crates/ra_hir/src/ty/tests/data/basics.txt b/crates/ra_hir/src/ty/tests/data/basics.txt
index 4a3b69b7e..e65fe07aa 100644
--- a/crates/ra_hir/src/ty/tests/data/basics.txt
+++ b/crates/ra_hir/src/ty/tests/data/basics.txt
@@ -10,4 +10,4 @@
10[76; 82) '1usize': usize 10[76; 82) '1usize': usize
11[88; 94) '1isize': isize 11[88; 94) '1isize': isize
12[100; 106) '"test"': &str 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/literals.txt b/crates/ra_hir/src/ty/tests/data/literals.txt
index e139d57a8..df435edd7 100644
--- a/crates/ra_hir/src/ty/tests/data/literals.txt
+++ b/crates/ra_hir/src/ty/tests/data/literals.txt
@@ -1,10 +1,11 @@
1[11; 135) '{ ...lse] }': () 1[11; 146) '{ ...lse] }': ()
2[17; 21) '5i32': i32 2[17; 21) '5i32': i32
3[27; 34) '"hello"': &str 3[27; 34) '"hello"': &str
4[40; 48) 'b"bytes"': &[u8] 4[40; 48) 'b"bytes"': &[u8]
5[54; 57) ''c'': char 5[54; 57) ''c'': char
6[63; 67) 'b'b'': u8 6[63; 67) 'b'b'': u8
7[73; 77) '3.14': [unknown] 7[73; 77) '3.14': {float}
8[83; 87) '5000': [unknown] 8[83; 87) '5000': {integer}
9[93; 108) '(0u32, -5isize)': [unknown] 9[93; 108) '(0u32, -5isize)': [unknown]
10[114; 133) '[true,...false]': () 10[114; 119) 'false': bool
11[125; 144) '[true,...false]': ()
diff --git a/crates/ra_hir/src/ty/tests/data/struct.txt b/crates/ra_hir/src/ty/tests/data/struct.txt
index 7b324c82f..dcdf61363 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': {integer}
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': {integer}
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