aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/expr.rs141
-rw-r--r--crates/ra_hir/src/name.rs2
-rw-r--r--crates/ra_hir/src/ty.rs46
-rw-r--r--crates/ra_hir/src/ty/tests.rs5
-rw-r--r--crates/ra_hir/src/ty/tests/data/binary_op.txt86
-rw-r--r--crates/ra_hir/src/ty/tests/data/literals.txt3
-rw-r--r--crates/ra_hir/src/ty/tests/data/tuple.txt18
7 files changed, 135 insertions, 166 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 3f2689781..2f3432870 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -6,12 +6,11 @@ use rustc_hash::FxHashMap;
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::{ 8use ra_syntax::{
9 SyntaxKind, 9 ast::{self, AstNode, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor}
10 ast::{self, AstNode, LoopBodyOwner, ArgListOwner, NameOwner}
11}; 10};
12 11
13use 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};
14use crate::ty::primitive::{UintTy, IntTy, FloatTy, UncertainIntTy, UncertainFloatTy}; 13use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy};
15 14
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
17pub struct ExprId(RawId); 16pub struct ExprId(RawId);
@@ -649,93 +648,59 @@ impl ExprCollector {
649 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect(); 648 let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect();
650 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr) 649 self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
651 } 650 }
652 ast::ExprKind::LiteralExpr(e) => { 651 ast::ExprKind::Literal(e) => {
653 if let Some(child) = e.literal() { 652 let child = if let Some(child) = e.literal_expr() {
654 let c = child.syntax(); 653 child
655 let lit = match c.kind() { 654 } else {
656 SyntaxKind::INT_NUMBER => { 655 return self.alloc_expr(Expr::Missing, syntax_ptr);
657 let text = c.text().to_string(); 656 };
658 657 let c = child.syntax();
659 // FIXME: don't do it like this. maybe use something like 658
660 // the IntTy::from_name functions 659 let lit = match child.flavor() {
661 let ty = if text.ends_with("isize") { 660 LiteralFlavor::IntNumber { suffix } => {
662 UncertainIntTy::Signed(IntTy::Isize) 661 let known_name = suffix
663 } else if text.ends_with("i128") { 662 .map(|s| Name::new(s))
664 UncertainIntTy::Signed(IntTy::I128) 663 .and_then(|name| UncertainIntTy::from_name(&name));
665 } else if text.ends_with("i64") { 664
666 UncertainIntTy::Signed(IntTy::I64) 665 if let Some(kn) = known_name {
667 } else if text.ends_with("i32") { 666 Literal::Int(0u64, kn)
668 UncertainIntTy::Signed(IntTy::I32) 667 } else {
669 } else if text.ends_with("i16") { 668 Literal::Int(0u64, UncertainIntTy::Unknown)
670 UncertainIntTy::Signed(IntTy::I16)
671 } else if text.ends_with("i8") {
672 UncertainIntTy::Signed(IntTy::I8)
673 } else if text.ends_with("usize") {
674 UncertainIntTy::Unsigned(UintTy::Usize)
675 } else if text.ends_with("u128") {
676 UncertainIntTy::Unsigned(UintTy::U128)
677 } else if text.ends_with("u64") {
678 UncertainIntTy::Unsigned(UintTy::U64)
679 } else if text.ends_with("u32") {
680 UncertainIntTy::Unsigned(UintTy::U32)
681 } else if text.ends_with("u16") {
682 UncertainIntTy::Unsigned(UintTy::U16)
683 } else if text.ends_with("u8") {
684 UncertainIntTy::Unsigned(UintTy::U8)
685 } else {
686 UncertainIntTy::Unknown
687 };
688
689 // TODO: actually parse integer
690 Literal::Int(0u64, ty)
691 }
692 SyntaxKind::FLOAT_NUMBER => {
693 let text = c.text().to_string();
694
695 // FIXME: don't do it like this. maybe use something like
696 // the IntTy::from_name functions
697 let ty = if text.ends_with("f64") {
698 UncertainFloatTy::Known(FloatTy::F64)
699 } else if text.ends_with("f32") {
700 UncertainFloatTy::Known(FloatTy::F32)
701 } else {
702 UncertainFloatTy::Unknown
703 };
704
705 // TODO: actually parse value
706 Literal::Float(0, ty)
707 }
708 SyntaxKind::STRING => {
709 // FIXME: this likely includes the " characters
710 let text = c.text().to_string();
711 Literal::String(text)
712 }
713 SyntaxKind::TRUE_KW => Literal::Bool(true),
714 SyntaxKind::FALSE_KW => Literal::Bool(false),
715 SyntaxKind::BYTE_STRING => {
716 // FIXME: this is completely incorrect for a variety
717 // of reasons, but at least it gives the right type
718 let bytes = c.text().to_string().into_bytes();
719 Literal::ByteString(bytes)
720 }
721 SyntaxKind::CHAR => {
722 let character = c.text().char_at(1).unwrap_or('X');
723 Literal::Char(character)
724 } 669 }
725 SyntaxKind::BYTE => { 670 }
726 let character = c.text().char_at(1).unwrap_or('X'); 671 LiteralFlavor::FloatNumber { suffix } => {
727 Literal::Int( 672 let known_name = suffix
728 character as u8 as u64, 673 .map(|s| Name::new(s))
729 UncertainIntTy::Unsigned(UintTy::U8), 674 .and_then(|name| UncertainFloatTy::from_name(&name));
730 ) 675
676 if let Some(kn) = known_name {
677 Literal::Float(0u64, kn)
678 } else {
679 Literal::Float(0u64, UncertainFloatTy::Unknown)
731 } 680 }
732 _ => return self.alloc_expr(Expr::Missing, syntax_ptr), 681 }
733 }; 682 LiteralFlavor::ByteString => {
734 683 // FIXME: this is completely incorrect for a variety
735 self.alloc_expr(Expr::Literal(lit), syntax_ptr) 684 // of reasons, but at least it gives the right type
736 } else { 685 let bytes = c.text().to_string().into_bytes();
737 self.alloc_expr(Expr::Missing, syntax_ptr) 686 Literal::ByteString(bytes)
738 } 687 }
688 LiteralFlavor::String => {
689 // FIXME: this likely includes the " characters
690 let text = c.text().to_string();
691 Literal::String(text)
692 }
693 LiteralFlavor::Byte => {
694 let character = c.text().char_at(1).unwrap_or('X');
695 Literal::Int(character as u8 as u64, UncertainIntTy::Unsigned(UintTy::U8))
696 }
697 LiteralFlavor::Bool => Literal::Bool(true),
698 LiteralFlavor::Char => {
699 let character = c.text().char_at(1).unwrap_or('X');
700 Literal::Char(character)
701 }
702 };
703 self.alloc_expr(Expr::Literal(lit), syntax_ptr)
739 } 704 }
740 705
741 // TODO implement HIR for these: 706 // TODO implement HIR for these:
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 de5ec5b46..b6577ee5e 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -111,7 +111,7 @@ impl UnifyValue for TypeVarValue {
111/// values for general types, and for integer and float variables. The latter 111/// values for general types, and for integer and float variables. The latter
112/// two are used 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), 117 IntVar(TypeVarId),
@@ -119,6 +119,12 @@ pub enum InferTy {
119} 119}
120 120
121impl InferTy { 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
122 fn fallback_value(self) -> Ty { 128 fn fallback_value(self) -> Ty {
123 match self { 129 match self {
124 InferTy::TypeVar(..) => Ty::Unknown, 130 InferTy::TypeVar(..) => Ty::Unknown,
@@ -326,18 +332,19 @@ impl Ty {
326 path: &Path, 332 path: &Path,
327 ) -> Cancelable<Self> { 333 ) -> Cancelable<Self> {
328 if let Some(name) = path.as_ident() { 334 if let Some(name) = path.as_ident() {
329 if let Some(KnownName::Bool) = name.as_known_name() { 335 if let Some(int_ty) = primitive::UncertainIntTy::from_name(name) {
330 return Ok(Ty::Bool);
331 } else if let Some(KnownName::Char) = name.as_known_name() {
332 return Ok(Ty::Char);
333 } else if let Some(KnownName::Str) = name.as_known_name() {
334 return Ok(Ty::Str);
335 } else if let Some(int_ty) = primitive::UncertainIntTy::from_name(name) {
336 return Ok(Ty::Int(int_ty)); 336 return Ok(Ty::Int(int_ty));
337 } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { 337 } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) {
338 return Ok(Ty::Float(float_ty)); 338 return Ok(Ty::Float(float_ty));
339 } else if name.as_known_name() == Some(KnownName::SelfType) { 339 } else if name.as_known_name() == Some(KnownName::SelfType) {
340 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 }
341 } 348 }
342 } 349 }
343 350
@@ -793,10 +800,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
793 /// known type. 800 /// known type.
794 fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty { 801 fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
795 ty.fold(&mut |ty| match ty { 802 ty.fold(&mut |ty| match ty {
796 Ty::Infer(InferTy::TypeVar(tv)) 803 Ty::Infer(tv) => {
797 | Ty::Infer(InferTy::IntVar(tv)) 804 let inner = tv.to_inner();
798 | Ty::Infer(InferTy::FloatVar(tv)) => { 805 if let Some(known_ty) = self.var_unification_table.probe_value(inner).known() {
799 if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() {
800 // known_ty may contain other variables that are known by now 806 // known_ty may contain other variables that are known by now
801 self.resolve_ty_as_possible(known_ty.clone()) 807 self.resolve_ty_as_possible(known_ty.clone())
802 } else { 808 } else {
@@ -811,8 +817,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
811 /// otherwise, return ty. 817 /// otherwise, return ty.
812 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> {
813 match ty { 819 match ty {
814 Ty::Infer(InferTy::TypeVar(tv)) => { 820 Ty::Infer(tv) => {
815 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() {
816 Some(known_ty) => { 823 Some(known_ty) => {
817 // The known_ty can't be a type var itself 824 // The known_ty can't be a type var itself
818 Cow::Owned(known_ty.clone()) 825 Cow::Owned(known_ty.clone())
@@ -828,16 +835,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
828 /// replaced by Ty::Unknown. 835 /// replaced by Ty::Unknown.
829 fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { 836 fn resolve_ty_completely(&mut self, ty: Ty) -> Ty {
830 ty.fold(&mut |ty| match ty { 837 ty.fold(&mut |ty| match ty {
831 Ty::Infer(i) => { 838 Ty::Infer(tv) => {
832 let tv = match i { 839 let inner = tv.to_inner();
833 InferTy::TypeVar(tv) | InferTy::IntVar(tv) | InferTy::FloatVar(tv) => tv, 840 if let Some(known_ty) = self.var_unification_table.probe_value(inner).known() {
834 };
835
836 if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() {
837 // known_ty may contain other variables that are known by now 841 // known_ty may contain other variables that are known by now
838 self.resolve_ty_completely(known_ty.clone()) 842 self.resolve_ty_completely(known_ty.clone())
839 } else { 843 } else {
840 i.fallback_value() 844 tv.fallback_value()
841 } 845 }
842 } 846 }
843 _ => ty, 847 _ => ty,
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 53ea99874..cbdb2a4b7 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 false; 147 false;
148 true;
148} 149}
149"#, 150"#,
150 "literals.txt", 151 "literals.txt",
@@ -199,7 +200,7 @@ fn f(x: bool) -> i32 {
199 0i32 200 0i32
200} 201}
201 202
202fn test() { 203fn test() -> bool {
203 let x = a && b; 204 let x = a && b;
204 let y = true || false; 205 let y = true || false;
205 let z = x == y; 206 let z = x == y;
@@ -296,8 +297,6 @@ fn test(x: &str, y: isize) {
296 let b = (a, x); 297 let b = (a, x);
297 let c = (y, x); 298 let c = (y, x);
298 let d = (c, x); 299 let d = (c, x);
299
300 // we have not infered these case yet.
301 let e = (1, "e"); 300 let e = (1, "e");
302 let f = (e, "d"); 301 let f = (e, "d");
303} 302}
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 7fdb8a900..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': isize 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/literals.txt b/crates/ra_hir/src/ty/tests/data/literals.txt
index 8d6079c98..6e82f458f 100644
--- a/crates/ra_hir/src/ty/tests/data/literals.txt
+++ b/crates/ra_hir/src/ty/tests/data/literals.txt
@@ -1,4 +1,4 @@
1[11; 101) '{ ...lse; }': () 1[11; 111) '{ ...rue; }': ()
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]
@@ -7,3 +7,4 @@
7[73; 77) '3.14': f64 7[73; 77) '3.14': f64
8[83; 87) '5000': i32 8[83; 87) '5000': i32
9[93; 98) 'false': bool 9[93; 98) 'false': bool
10[104; 108) 'true': bool
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