aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorMarcus Klaas de Vries <[email protected]>2019-01-14 22:15:16 +0000
committerMarcus Klaas de Vries <[email protected]>2019-01-15 23:04:39 +0000
commita2b6d3da30020421c97100d7c8699a3b4f8cd6fb (patch)
treef38fafe9cbc4efea5574afa6c40a0fea403bf34c /crates
parentab46f8abf195a78c018d8b23896eb920d16b028b (diff)
Implement rudimentary type inference for unary operators
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/expr.rs9
-rw-r--r--crates/ra_hir/src/ty.rs17
-rw-r--r--crates/ra_hir/src/ty/tests.rs23
-rw-r--r--crates/ra_hir/src/ty/tests/data/unary_op.txt28
4 files changed, 72 insertions, 5 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 4e8dc0c54..663338844 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -182,7 +182,7 @@ pub enum Expr {
182 }, 182 },
183 UnaryOp { 183 UnaryOp {
184 expr: ExprId, 184 expr: ExprId,
185 op: Option<UnaryOp>, 185 op: UnaryOp,
186 }, 186 },
187 BinaryOp { 187 BinaryOp {
188 lhs: ExprId, 188 lhs: ExprId,
@@ -612,8 +612,11 @@ impl ExprCollector {
612 } 612 }
613 ast::ExprKind::PrefixExpr(e) => { 613 ast::ExprKind::PrefixExpr(e) => {
614 let expr = self.collect_expr_opt(e.expr()); 614 let expr = self.collect_expr_opt(e.expr());
615 let op = e.op(); 615 if let Some(op) = e.op() {
616 self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr) 616 self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr)
617 } else {
618 self.alloc_expr(Expr::Missing, syntax_ptr)
619 }
617 } 620 }
618 ast::ExprKind::LambdaExpr(e) => { 621 ast::ExprKind::LambdaExpr(e) => {
619 let mut args = Vec::new(); 622 let mut args = Vec::new();
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index dbbbce795..85d4dc05c 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -1051,7 +1051,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1051 Expr::UnaryOp { expr, op } => { 1051 Expr::UnaryOp { expr, op } => {
1052 let inner_ty = self.infer_expr(*expr, &Expectation::none()); 1052 let inner_ty = self.infer_expr(*expr, &Expectation::none());
1053 match op { 1053 match op {
1054 Some(UnaryOp::Deref) => { 1054 UnaryOp::Deref => {
1055 if let Some(derefed_ty) = inner_ty.builtin_deref() { 1055 if let Some(derefed_ty) = inner_ty.builtin_deref() {
1056 derefed_ty 1056 derefed_ty
1057 } else { 1057 } else {
@@ -1059,7 +1059,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1059 Ty::Unknown 1059 Ty::Unknown
1060 } 1060 }
1061 } 1061 }
1062 _ => Ty::Unknown, 1062 UnaryOp::Neg => {
1063 match inner_ty {
1064 Ty::Int(primitive::UncertainIntTy::Unknown)
1065 | Ty::Int(primitive::UncertainIntTy::Signed(..))
1066 | Ty::Infer(InferTy::IntVar(..))
1067 | Ty::Infer(InferTy::FloatVar(..))
1068 | Ty::Float(..) => inner_ty,
1069 // TODO: resolve ops::Neg trait
1070 _ => Ty::Unknown,
1071 }
1072 }
1073 UnaryOp::Not if inner_ty == Ty::Bool => Ty::Bool,
1074 // TODO: resolve ops::Not trait for inner_ty
1075 UnaryOp::Not => Ty::Unknown,
1063 } 1076 }
1064 } 1077 }
1065 Expr::BinaryOp { lhs, rhs, op } => match op { 1078 Expr::BinaryOp { lhs, rhs, op } => match op {
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 929fee04c..5d7bc25cc 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -159,6 +159,29 @@ fn test() {
159} 159}
160 160
161#[test] 161#[test]
162fn infer_unary_op() {
163 check_inference(
164 r#"
165enum SomeType {}
166
167fn test(x: SomeType) {
168 let b = false;
169 let c = !b;
170 let a = 100;
171 let d: i128 = -a;
172 let e = -100;
173 let f = !!!true;
174 -3.14;
175 -x;
176 !x;
177 -"hello";
178}
179"#,
180 "unary_op.txt",
181 );
182}
183
184#[test]
162fn infer_backwards() { 185fn infer_backwards() {
163 check_inference( 186 check_inference(
164 r#" 187 r#"
diff --git a/crates/ra_hir/src/ty/tests/data/unary_op.txt b/crates/ra_hir/src/ty/tests/data/unary_op.txt
new file mode 100644
index 000000000..203022e82
--- /dev/null
+++ b/crates/ra_hir/src/ty/tests/data/unary_op.txt
@@ -0,0 +1,28 @@
1[27; 28) 'x': SomeType
2[40; 197) '{ ...lo"; }': ()
3[50; 51) 'b': bool
4[54; 59) 'false': bool
5[69; 70) 'c': bool
6[73; 75) '!b': bool
7[74; 75) 'b': bool
8[85; 86) 'a': i128
9[89; 92) '100': i128
10[102; 103) 'd': i128
11[112; 114) '-a': i128
12[113; 114) 'a': i128
13[124; 125) 'e': i32
14[128; 132) '-100': i32
15[129; 132) '100': i32
16[142; 143) 'f': bool
17[146; 153) '!!!true': bool
18[147; 153) '!!true': bool
19[148; 153) '!true': bool
20[149; 153) 'true': bool
21[159; 164) '-3.14': f64
22[160; 164) '3.14': f64
23[170; 172) '-x': [unknown]
24[171; 172) 'x': SomeType
25[178; 180) '!x': [unknown]
26[179; 180) 'x': SomeType
27[186; 194) '-"hello"': [unknown]
28[187; 194) '"hello"': &str