diff options
author | Marcus Klaas de Vries <[email protected]> | 2019-01-14 22:15:16 +0000 |
---|---|---|
committer | Marcus Klaas de Vries <[email protected]> | 2019-01-15 23:04:39 +0000 |
commit | a2b6d3da30020421c97100d7c8699a3b4f8cd6fb (patch) | |
tree | f38fafe9cbc4efea5574afa6c40a0fea403bf34c /crates | |
parent | ab46f8abf195a78c018d8b23896eb920d16b028b (diff) |
Implement rudimentary type inference for unary operators
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 17 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/unary_op.txt | 28 |
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] |
162 | fn infer_unary_op() { | ||
163 | check_inference( | ||
164 | r#" | ||
165 | enum SomeType {} | ||
166 | |||
167 | fn 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] | ||
162 | fn infer_backwards() { | 185 | fn 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 | ||