diff options
author | Marcus Klaas de Vries <[email protected]> | 2019-01-07 19:11:31 +0000 |
---|---|---|
committer | Marcus Klaas de Vries <[email protected]> | 2019-01-07 19:11:31 +0000 |
commit | 7b0eaef58072acc087d23faca5a9f9879f1765d5 (patch) | |
tree | 753250bc428b0313faac6de7622686c445ef7dd6 /crates/ra_hir/src/ty.rs | |
parent | 3238c06a5a122b7e7b9b6871484c700b7947fae1 (diff) |
Implement type inference for more binary operators
Mostly just for primitive numeric types such as u32 and f64. Not
yet a general solution using trait resolution.
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 85 |
1 files changed, 74 insertions, 11 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 23ee76f4e..e09279a68 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -529,7 +529,7 @@ struct InferenceContext<'a, D: HirDatabase> { | |||
529 | 529 | ||
530 | // helper function that determines whether a binary operator | 530 | // helper function that determines whether a binary operator |
531 | // always returns a boolean | 531 | // always returns a boolean |
532 | fn is_boolean_operator(op: BinaryOp) -> bool { | 532 | fn boolean_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { |
533 | match op { | 533 | match op { |
534 | BinaryOp::BooleanOr | 534 | BinaryOp::BooleanOr |
535 | | BinaryOp::BooleanAnd | 535 | | BinaryOp::BooleanAnd |
@@ -537,8 +537,32 @@ fn is_boolean_operator(op: BinaryOp) -> bool { | |||
537 | | BinaryOp::LesserEqualTest | 537 | | BinaryOp::LesserEqualTest |
538 | | BinaryOp::GreaterEqualTest | 538 | | BinaryOp::GreaterEqualTest |
539 | | BinaryOp::LesserTest | 539 | | BinaryOp::LesserTest |
540 | | BinaryOp::GreaterTest => true, | 540 | | BinaryOp::GreaterTest => Ty::Bool, |
541 | _ => false, | 541 | BinaryOp::Assignment |
542 | | BinaryOp::AddAssign | ||
543 | | BinaryOp::SubAssign | ||
544 | | BinaryOp::DivAssign | ||
545 | | BinaryOp::MulAssign | ||
546 | | BinaryOp::RemAssign | ||
547 | | BinaryOp::ShrAssign | ||
548 | | BinaryOp::ShlAssign | ||
549 | | BinaryOp::BitAndAssign | ||
550 | | BinaryOp::BitOrAssign | ||
551 | | BinaryOp::BitXorAssign => Ty::unit(), | ||
552 | BinaryOp::Addition | ||
553 | | BinaryOp::Subtraction | ||
554 | | BinaryOp::Multiplication | ||
555 | | BinaryOp::Division | ||
556 | | BinaryOp::Remainder | ||
557 | | BinaryOp::LeftShift | ||
558 | | BinaryOp::RightShift | ||
559 | | BinaryOp::BitwiseAnd | ||
560 | | BinaryOp::BitwiseOr | ||
561 | | BinaryOp::BitwiseXor => match rhs_ty { | ||
562 | Ty::Uint(..) | Ty::Int(..) | Ty::Float(..) => rhs_ty, | ||
563 | _ => Ty::Unknown, | ||
564 | }, | ||
565 | BinaryOp::RangeRightOpen | BinaryOp::RangeRightClosed => Ty::Unknown, | ||
542 | } | 566 | } |
543 | } | 567 | } |
544 | 568 | ||
@@ -890,20 +914,59 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
890 | } | 914 | } |
891 | Expr::BinaryOp { lhs, rhs, op } => match op { | 915 | Expr::BinaryOp { lhs, rhs, op } => match op { |
892 | Some(op) => { | 916 | Some(op) => { |
893 | let subtype_expectation = match op { | 917 | let lhs_expectation = match op { |
894 | BinaryOp::BooleanAnd | BinaryOp::BooleanOr => { | 918 | BinaryOp::BooleanAnd | BinaryOp::BooleanOr => { |
895 | Expectation::has_type(Ty::Bool) | 919 | Expectation::has_type(Ty::Bool) |
896 | } | 920 | } |
897 | _ => Expectation::none(), | 921 | _ => Expectation::none(), |
898 | }; | 922 | }; |
899 | let _lhs_ty = self.infer_expr(*lhs, &subtype_expectation)?; | 923 | let lhs_ty = self.infer_expr(*lhs, &lhs_expectation)?; |
900 | let _rhs_ty = self.infer_expr(*rhs, &subtype_expectation)?; | 924 | // TODO: find implementation of trait corresponding to operation |
925 | // symbol and resolve associated `Output` type | ||
926 | let rhs_expectation = match op { | ||
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))?; | ||
901 | 967 | ||
902 | if is_boolean_operator(*op) { | 968 | // TODO: similar as above, return ty is often associated trait type |
903 | Ty::Bool | 969 | boolean_op_return_ty(*op, rhs_ty) |
904 | } else { | ||
905 | Ty::Unknown | ||
906 | } | ||
907 | } | 970 | } |
908 | _ => Ty::Unknown, | 971 | _ => Ty::Unknown, |
909 | }, | 972 | }, |