diff options
-rw-r--r-- | crates/ra_hir/src/ty.rs | 85 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/binary_op.txt | 46 |
2 files changed, 87 insertions, 44 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index e09279a68..7827e82c4 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -527,9 +527,7 @@ struct InferenceContext<'a, D: HirDatabase> { | |||
527 | return_ty: Ty, | 527 | return_ty: Ty, |
528 | } | 528 | } |
529 | 529 | ||
530 | // helper function that determines whether a binary operator | 530 | fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { |
531 | // always returns a boolean | ||
532 | fn boolean_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | ||
533 | match op { | 531 | match op { |
534 | BinaryOp::BooleanOr | 532 | BinaryOp::BooleanOr |
535 | | BinaryOp::BooleanAnd | 533 | | BinaryOp::BooleanAnd |
@@ -566,6 +564,44 @@ fn boolean_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | |||
566 | } | 564 | } |
567 | } | 565 | } |
568 | 566 | ||
567 | fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | ||
568 | match op { | ||
569 | BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::Bool, | ||
570 | BinaryOp::Assignment | BinaryOp::EqualityTest => match lhs_ty { | ||
571 | Ty::Uint(..) | Ty::Int(..) | Ty::Float(..) | Ty::Str | Ty::Char | Ty::Bool => lhs_ty, | ||
572 | _ => Ty::Unknown, | ||
573 | }, | ||
574 | BinaryOp::LesserEqualTest | ||
575 | | BinaryOp::GreaterEqualTest | ||
576 | | BinaryOp::LesserTest | ||
577 | | BinaryOp::GreaterTest | ||
578 | | BinaryOp::AddAssign | ||
579 | | BinaryOp::SubAssign | ||
580 | | BinaryOp::DivAssign | ||
581 | | BinaryOp::MulAssign | ||
582 | | BinaryOp::RemAssign | ||
583 | | BinaryOp::ShrAssign | ||
584 | | BinaryOp::ShlAssign | ||
585 | | BinaryOp::BitAndAssign | ||
586 | | BinaryOp::BitOrAssign | ||
587 | | BinaryOp::BitXorAssign | ||
588 | | BinaryOp::Addition | ||
589 | | BinaryOp::Subtraction | ||
590 | | BinaryOp::Multiplication | ||
591 | | BinaryOp::Division | ||
592 | | BinaryOp::Remainder | ||
593 | | BinaryOp::LeftShift | ||
594 | | BinaryOp::RightShift | ||
595 | | BinaryOp::BitwiseAnd | ||
596 | | BinaryOp::BitwiseOr | ||
597 | | BinaryOp::BitwiseXor => match lhs_ty { | ||
598 | Ty::Uint(..) | Ty::Int(..) | Ty::Float(..) => lhs_ty, | ||
599 | _ => Ty::Unknown, | ||
600 | }, | ||
601 | _ => Ty::Unknown, | ||
602 | } | ||
603 | } | ||
604 | |||
569 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 605 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
570 | fn new( | 606 | fn new( |
571 | db: &'a D, | 607 | db: &'a D, |
@@ -923,50 +959,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
923 | let lhs_ty = self.infer_expr(*lhs, &lhs_expectation)?; | 959 | let lhs_ty = self.infer_expr(*lhs, &lhs_expectation)?; |
924 | // TODO: find implementation of trait corresponding to operation | 960 | // TODO: find implementation of trait corresponding to operation |
925 | // symbol and resolve associated `Output` type | 961 | // symbol and resolve associated `Output` type |
926 | let rhs_expectation = match op { | 962 | let rhs_expectation = binary_op_rhs_expectation(*op, lhs_ty); |
927 | BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::Bool, | ||
928 | BinaryOp::Assignment | BinaryOp::EqualityTest => match lhs_ty { | ||
929 | Ty::Uint(..) | ||
930 | | Ty::Int(..) | ||
931 | | Ty::Float(..) | ||
932 | | Ty::Str | ||
933 | | Ty::Char | ||
934 | | Ty::Bool => lhs_ty, | ||
935 | _ => Ty::Unknown, | ||
936 | }, | ||
937 | BinaryOp::LesserEqualTest | ||
938 | | BinaryOp::GreaterEqualTest | ||
939 | | BinaryOp::LesserTest | ||
940 | | BinaryOp::GreaterTest | ||
941 | | BinaryOp::AddAssign | ||
942 | | BinaryOp::SubAssign | ||
943 | | BinaryOp::DivAssign | ||
944 | | BinaryOp::MulAssign | ||
945 | | BinaryOp::RemAssign | ||
946 | | BinaryOp::ShrAssign | ||
947 | | BinaryOp::ShlAssign | ||
948 | | BinaryOp::BitAndAssign | ||
949 | | BinaryOp::BitOrAssign | ||
950 | | BinaryOp::BitXorAssign | ||
951 | | BinaryOp::Addition | ||
952 | | BinaryOp::Subtraction | ||
953 | | BinaryOp::Multiplication | ||
954 | | BinaryOp::Division | ||
955 | | BinaryOp::Remainder | ||
956 | | BinaryOp::LeftShift | ||
957 | | BinaryOp::RightShift | ||
958 | | BinaryOp::BitwiseAnd | ||
959 | | BinaryOp::BitwiseOr | ||
960 | | BinaryOp::BitwiseXor => match lhs_ty { | ||
961 | Ty::Uint(..) | Ty::Int(..) | Ty::Float(..) => lhs_ty, | ||
962 | _ => Ty::Unknown, | ||
963 | }, | ||
964 | _ => Ty::Unknown, | ||
965 | }; | ||
966 | let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation))?; | 963 | let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation))?; |
967 | 964 | ||
968 | // TODO: similar as above, return ty is often associated trait type | 965 | // TODO: similar as above, return ty is often associated trait type |
969 | boolean_op_return_ty(*op, rhs_ty) | 966 | binary_op_return_ty(*op, rhs_ty) |
970 | } | 967 | } |
971 | _ => Ty::Unknown, | 968 | _ => Ty::Unknown, |
972 | }, | 969 | }, |
diff --git a/crates/ra_hir/src/ty/tests/data/binary_op.txt b/crates/ra_hir/src/ty/tests/data/binary_op.txt new file mode 100644 index 000000000..59c07ff43 --- /dev/null +++ b/crates/ra_hir/src/ty/tests/data/binary_op.txt | |||
@@ -0,0 +1,46 @@ | |||
1 | [6; 7) 'x': [unknown] | ||
2 | [22; 34) '{ 0i32 }': i32 | ||
3 | [28; 32) '0i32': i32 | ||
4 | [46; 342) '{ ... < 3 }': bool | ||
5 | [56; 57) 'x': bool | ||
6 | [60; 61) 'a': bool | ||
7 | [60; 66) 'a && b': bool | ||
8 | [65; 66) 'b': bool | ||
9 | [76; 77) 'y': bool | ||
10 | [80; 84) 'true': bool | ||
11 | [80; 93) 'true || false': bool | ||
12 | [88; 93) 'false': bool | ||
13 | [103; 104) 'z': bool | ||
14 | [107; 108) 'x': bool | ||
15 | [107; 113) 'x == y': bool | ||
16 | [112; 113) 'y': bool | ||
17 | [123; 134) 'minus_forty': isize | ||
18 | [144; 152) '-40isize': isize | ||
19 | [145; 152) '40isize': [unknown] | ||
20 | [162; 163) 'h': bool | ||
21 | [166; 177) 'minus_forty': isize | ||
22 | [166; 188) 'minus_...ONST_2': bool | ||
23 | [181; 188) 'CONST_2': isize | ||
24 | [198; 199) 'c': i32 | ||
25 | [202; 203) 'f': fn([unknown],) -> i32 | ||
26 | [202; 211) 'f(z || y)': i32 | ||
27 | [202; 215) 'f(z || y) + 5': i32 | ||
28 | [204; 205) 'z': bool | ||
29 | [204; 210) 'z || y': bool | ||
30 | [209; 210) 'y': bool | ||
31 | [214; 215) '5': i32 | ||
32 | [225; 226) 'd': [unknown] | ||
33 | [229; 230) 'b': [unknown] | ||
34 | [240; 241) 'g': () | ||
35 | [244; 255) 'minus_forty': isize | ||
36 | [244; 260) 'minus_...y ^= i': () | ||
37 | [259; 260) 'i': isize | ||
38 | [270; 273) 'ten': usize | ||
39 | [283; 285) '10': usize | ||
40 | [295; 308) 'ten_is_eleven': bool | ||
41 | [311; 314) 'ten': usize | ||
42 | [311; 326) 'ten == some_num': bool | ||
43 | [318; 326) 'some_num': usize | ||
44 | [333; 336) 'ten': usize | ||
45 | [333; 340) 'ten < 3': bool | ||
46 | [339; 340) '3': usize | ||