mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-05 13:13:40 +00:00
Implement rudimentary type inference for unary operators
This commit is contained in:
parent
ab46f8abf1
commit
a2b6d3da30
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
28
crates/ra_hir/src/ty/tests/data/unary_op.txt
Normal file
28
crates/ra_hir/src/ty/tests/data/unary_op.txt
Normal 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
|
Loading…
Reference in New Issue
Block a user