diff options
author | Marcus Klaas de Vries <[email protected]> | 2019-01-10 17:08:54 +0000 |
---|---|---|
committer | Marcus Klaas de Vries <[email protected]> | 2019-01-14 12:54:31 +0000 |
commit | 1574715be5d3fc7e07160708810dcbc9c1b01733 (patch) | |
tree | c482c99282393d75606c4487d316103b14208561 /crates | |
parent | 5f5dc20d85dead5fbd51d163451f796255c9faea (diff) |
Use type variables to determine exact type for ambiguous numeric literals
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 17 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 45 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/basics.txt | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/literals.txt | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/struct.txt | 4 |
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)] |
115 | pub enum InferTy { | 115 | pub 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 |