Implement rudimentary type inference for unary operators

This commit is contained in:
Marcus Klaas de Vries 2019-01-14 23:15:16 +01:00
parent ab46f8abf1
commit a2b6d3da30
4 changed files with 72 additions and 5 deletions

View File

@ -182,7 +182,7 @@ pub enum Expr {
},
UnaryOp {
expr: ExprId,
op: Option<UnaryOp>,
op: UnaryOp,
},
BinaryOp {
lhs: ExprId,
@ -612,8 +612,11 @@ impl ExprCollector {
}
ast::ExprKind::PrefixExpr(e) => {
let expr = self.collect_expr_opt(e.expr());
let op = e.op();
self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr)
if let Some(op) = e.op() {
self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr)
} else {
self.alloc_expr(Expr::Missing, syntax_ptr)
}
}
ast::ExprKind::LambdaExpr(e) => {
let mut args = Vec::new();

View File

@ -1051,7 +1051,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
Expr::UnaryOp { expr, op } => {
let inner_ty = self.infer_expr(*expr, &Expectation::none());
match op {
Some(UnaryOp::Deref) => {
UnaryOp::Deref => {
if let Some(derefed_ty) = inner_ty.builtin_deref() {
derefed_ty
} else {
@ -1059,7 +1059,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
Ty::Unknown
}
}
_ => Ty::Unknown,
UnaryOp::Neg => {
match inner_ty {
Ty::Int(primitive::UncertainIntTy::Unknown)
| Ty::Int(primitive::UncertainIntTy::Signed(..))
| Ty::Infer(InferTy::IntVar(..))
| Ty::Infer(InferTy::FloatVar(..))
| Ty::Float(..) => inner_ty,
// TODO: resolve ops::Neg trait
_ => Ty::Unknown,
}
}
UnaryOp::Not if inner_ty == Ty::Bool => Ty::Bool,
// TODO: resolve ops::Not trait for inner_ty
UnaryOp::Not => Ty::Unknown,
}
}
Expr::BinaryOp { lhs, rhs, op } => match op {

View File

@ -158,6 +158,29 @@ fn test() {
);
}
#[test]
fn infer_unary_op() {
check_inference(
r#"
enum SomeType {}
fn test(x: SomeType) {
let b = false;
let c = !b;
let a = 100;
let d: i128 = -a;
let e = -100;
let f = !!!true;
-3.14;
-x;
!x;
-"hello";
}
"#,
"unary_op.txt",
);
}
#[test]
fn infer_backwards() {
check_inference(

View File

@ -0,0 +1,28 @@
[27; 28) 'x': SomeType
[40; 197) '{ ...lo"; }': ()
[50; 51) 'b': bool
[54; 59) 'false': bool
[69; 70) 'c': bool
[73; 75) '!b': bool
[74; 75) 'b': bool
[85; 86) 'a': i128
[89; 92) '100': i128
[102; 103) 'd': i128
[112; 114) '-a': i128
[113; 114) 'a': i128
[124; 125) 'e': i32
[128; 132) '-100': i32
[129; 132) '100': i32
[142; 143) 'f': bool
[146; 153) '!!!true': bool
[147; 153) '!!true': bool
[148; 153) '!true': bool
[149; 153) 'true': bool
[159; 164) '-3.14': f64
[160; 164) '3.14': f64
[170; 172) '-x': [unknown]
[171; 172) 'x': SomeType
[178; 180) '!x': [unknown]
[179; 180) 'x': SomeType
[186; 194) '-"hello"': [unknown]
[187; 194) '"hello"': &str