Fix inference for shift operators

Fixes #2602.
This commit is contained in:
Florian Diebold 2020-01-17 16:59:02 +01:00
parent 07dca1123d
commit 33d637f2dd
3 changed files with 35 additions and 5 deletions

View File

@ -386,11 +386,11 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
let lhs_ty = self.infer_expr(*lhs, &lhs_expectation);
// FIXME: find implementation of trait corresponding to operation
// symbol and resolve associated `Output` type
let rhs_expectation = op::binary_op_rhs_expectation(*op, lhs_ty);
let rhs_expectation = op::binary_op_rhs_expectation(*op, lhs_ty.clone());
let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation));
// FIXME: similar as above, return ty is often associated trait type
op::binary_op_return_ty(*op, rhs_ty)
op::binary_op_return_ty(*op, lhs_ty, rhs_ty)
}
_ => Ty::Unknown,
},

View File

@ -1,13 +1,21 @@
//! FIXME: write short doc here
use hir_def::expr::{BinaryOp, CmpOp};
//! Helper functions for binary operator type inference.
use hir_def::expr::{ArithOp, BinaryOp, CmpOp};
use super::{InferTy, Ty, TypeCtor};
use crate::ApplicationTy;
pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty {
pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
match op {
BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => Ty::simple(TypeCtor::Bool),
BinaryOp::Assignment { .. } => Ty::unit(),
BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => match lhs_ty {
Ty::Apply(ApplicationTy { ctor, .. }) => match ctor {
TypeCtor::Int(..) | TypeCtor::Float(..) => lhs_ty,
_ => Ty::Unknown,
},
Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => lhs_ty,
_ => Ty::Unknown,
},
BinaryOp::ArithOp(_) => match rhs_ty {
Ty::Apply(ApplicationTy { ctor, .. }) => match ctor {
TypeCtor::Int(..) | TypeCtor::Float(..) => rhs_ty,
@ -36,6 +44,7 @@ pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty {
_ => Ty::Unknown,
}
}
BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => Ty::Unknown,
BinaryOp::CmpOp(CmpOp::Ord { .. })
| BinaryOp::Assignment { op: Some(_) }
| BinaryOp::ArithOp(_) => match lhs_ty {

View File

@ -613,6 +613,27 @@ fn test() -> bool {
);
}
#[test]
fn infer_shift_op() {
assert_snapshot!(
infer(r#"
fn test() {
1u32 << 5u8;
1u32 >> 5u8;
}
"#),
@r###"
[11; 48) '{ ...5u8; }': ()
[17; 21) '1u32': u32
[17; 28) '1u32 << 5u8': u32
[25; 28) '5u8': u8
[34; 38) '1u32': u32
[34; 45) '1u32 >> 5u8': u32
[42; 45) '5u8': u8
"###
);
}
#[test]
fn infer_field_autoderef() {
assert_snapshot!(