diff options
author | Florian Diebold <[email protected]> | 2020-01-17 15:59:02 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2020-01-17 15:59:51 +0000 |
commit | 33d637f2ddb5e5eab6d5dfaf75042dfc1a58d241 (patch) | |
tree | 52d96e64a1235e3b22d5ed8e213a7b616d115aba /crates/ra_hir_ty/src | |
parent | 07dca1123dfaec527c6ba3164125309f5c4cc3db (diff) |
Fix inference for shift operators
Fixes #2602.
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/op.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 21 |
3 files changed, 35 insertions, 5 deletions
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index d6a17e469..31259a01d 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -386,11 +386,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
386 | let lhs_ty = self.infer_expr(*lhs, &lhs_expectation); | 386 | let lhs_ty = self.infer_expr(*lhs, &lhs_expectation); |
387 | // FIXME: find implementation of trait corresponding to operation | 387 | // FIXME: find implementation of trait corresponding to operation |
388 | // symbol and resolve associated `Output` type | 388 | // symbol and resolve associated `Output` type |
389 | let rhs_expectation = op::binary_op_rhs_expectation(*op, lhs_ty); | 389 | let rhs_expectation = op::binary_op_rhs_expectation(*op, lhs_ty.clone()); |
390 | let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation)); | 390 | let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation)); |
391 | 391 | ||
392 | // FIXME: similar as above, return ty is often associated trait type | 392 | // FIXME: similar as above, return ty is often associated trait type |
393 | op::binary_op_return_ty(*op, rhs_ty) | 393 | op::binary_op_return_ty(*op, lhs_ty, rhs_ty) |
394 | } | 394 | } |
395 | _ => Ty::Unknown, | 395 | _ => Ty::Unknown, |
396 | }, | 396 | }, |
diff --git a/crates/ra_hir_ty/src/op.rs b/crates/ra_hir_ty/src/op.rs index 09c47a76d..ae253ca04 100644 --- a/crates/ra_hir_ty/src/op.rs +++ b/crates/ra_hir_ty/src/op.rs | |||
@@ -1,13 +1,21 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Helper functions for binary operator type inference. |
2 | use hir_def::expr::{BinaryOp, CmpOp}; | 2 | use hir_def::expr::{ArithOp, BinaryOp, CmpOp}; |
3 | 3 | ||
4 | use super::{InferTy, Ty, TypeCtor}; | 4 | use super::{InferTy, Ty, TypeCtor}; |
5 | use crate::ApplicationTy; | 5 | use crate::ApplicationTy; |
6 | 6 | ||
7 | pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | 7 | pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { |
8 | match op { | 8 | match op { |
9 | BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => Ty::simple(TypeCtor::Bool), | 9 | BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => Ty::simple(TypeCtor::Bool), |
10 | BinaryOp::Assignment { .. } => Ty::unit(), | 10 | BinaryOp::Assignment { .. } => Ty::unit(), |
11 | BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => match lhs_ty { | ||
12 | Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { | ||
13 | TypeCtor::Int(..) | TypeCtor::Float(..) => lhs_ty, | ||
14 | _ => Ty::Unknown, | ||
15 | }, | ||
16 | Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty, | ||
17 | _ => Ty::Unknown, | ||
18 | }, | ||
11 | BinaryOp::ArithOp(_) => match rhs_ty { | 19 | BinaryOp::ArithOp(_) => match rhs_ty { |
12 | Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { | 20 | Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { |
13 | TypeCtor::Int(..) | TypeCtor::Float(..) => rhs_ty, | 21 | TypeCtor::Int(..) | TypeCtor::Float(..) => rhs_ty, |
@@ -36,6 +44,7 @@ pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | |||
36 | _ => Ty::Unknown, | 44 | _ => Ty::Unknown, |
37 | } | 45 | } |
38 | } | 46 | } |
47 | BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => Ty::Unknown, | ||
39 | BinaryOp::CmpOp(CmpOp::Ord { .. }) | 48 | BinaryOp::CmpOp(CmpOp::Ord { .. }) |
40 | | BinaryOp::Assignment { op: Some(_) } | 49 | | BinaryOp::Assignment { op: Some(_) } |
41 | | BinaryOp::ArithOp(_) => match lhs_ty { | 50 | | BinaryOp::ArithOp(_) => match lhs_ty { |
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index f7e042c12..b7204ec00 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -614,6 +614,27 @@ fn test() -> bool { | |||
614 | } | 614 | } |
615 | 615 | ||
616 | #[test] | 616 | #[test] |
617 | fn infer_shift_op() { | ||
618 | assert_snapshot!( | ||
619 | infer(r#" | ||
620 | fn test() { | ||
621 | 1u32 << 5u8; | ||
622 | 1u32 >> 5u8; | ||
623 | } | ||
624 | "#), | ||
625 | @r###" | ||
626 | [11; 48) '{ ...5u8; }': () | ||
627 | [17; 21) '1u32': u32 | ||
628 | [17; 28) '1u32 << 5u8': u32 | ||
629 | [25; 28) '5u8': u8 | ||
630 | [34; 38) '1u32': u32 | ||
631 | [34; 45) '1u32 >> 5u8': u32 | ||
632 | [42; 45) '5u8': u8 | ||
633 | "### | ||
634 | ); | ||
635 | } | ||
636 | |||
637 | #[test] | ||
617 | fn infer_field_autoderef() { | 638 | fn infer_field_autoderef() { |
618 | assert_snapshot!( | 639 | assert_snapshot!( |
619 | infer(r#" | 640 | infer(r#" |