aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-04-10 15:56:32 +0100
committerLukas Wirth <[email protected]>2021-04-10 15:56:32 +0100
commit252eb78dc3852707969b27b8a30f8844289aa985 (patch)
tree5bb3f755bd5d154233758a63122817381e3b66d1 /crates
parente357b6bb36828ecf3404fcc382da09216eef0997 (diff)
Implement more precise binary op return type prediction
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_ty/src/op.rs58
-rw-r--r--crates/hir_ty/src/tests/traits.rs10
2 files changed, 51 insertions, 17 deletions
diff --git a/crates/hir_ty/src/op.rs b/crates/hir_ty/src/op.rs
index 0491c5cb4..0222de2bc 100644
--- a/crates/hir_ty/src/op.rs
+++ b/crates/hir_ty/src/op.rs
@@ -9,21 +9,55 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner), 9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
10 BinaryOp::Assignment { .. } => TyBuilder::unit(), 10 BinaryOp::Assignment { .. } => TyBuilder::unit(),
11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => { 11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => {
12 match lhs_ty.kind(&Interner) { 12 // all integer combinations are valid here
13 if matches!(
14 lhs_ty.kind(&Interner),
13 TyKind::Scalar(Scalar::Int(_)) 15 TyKind::Scalar(Scalar::Int(_))
14 | TyKind::Scalar(Scalar::Uint(_)) 16 | TyKind::Scalar(Scalar::Uint(_))
15 | TyKind::Scalar(Scalar::Float(_)) => lhs_ty, 17 | TyKind::InferenceVar(_, TyVariableKind::Integer)
16 TyKind::InferenceVar(_, TyVariableKind::Integer) 18 ) && matches!(
17 | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty, 19 rhs_ty.kind(&Interner),
18 _ => TyKind::Error.intern(&Interner), 20 TyKind::Scalar(Scalar::Int(_))
21 | TyKind::Scalar(Scalar::Uint(_))
22 | TyKind::InferenceVar(_, TyVariableKind::Integer)
23 ) {
24 lhs_ty
25 } else {
26 TyKind::Error.intern(&Interner)
19 } 27 }
20 } 28 }
21 BinaryOp::ArithOp(_) => match rhs_ty.kind(&Interner) { 29 BinaryOp::ArithOp(_) => match (lhs_ty.kind(&Interner), rhs_ty.kind(&Interner)) {
22 TyKind::Scalar(Scalar::Int(_)) 30 // (int, int) | (uint, uint) | (float, float)
23 | TyKind::Scalar(Scalar::Uint(_)) 31 (TyKind::Scalar(Scalar::Int(_)), TyKind::Scalar(Scalar::Int(_)))
24 | TyKind::Scalar(Scalar::Float(_)) => rhs_ty, 32 | (TyKind::Scalar(Scalar::Uint(_)), TyKind::Scalar(Scalar::Uint(_)))
25 TyKind::InferenceVar(_, TyVariableKind::Integer) 33 | (TyKind::Scalar(Scalar::Float(_)), TyKind::Scalar(Scalar::Float(_))) => rhs_ty,
26 | TyKind::InferenceVar(_, TyVariableKind::Float) => rhs_ty, 34 // ({int}, int) | ({int}, uint)
35 (TyKind::InferenceVar(_, TyVariableKind::Integer), TyKind::Scalar(Scalar::Int(_)))
36 | (TyKind::InferenceVar(_, TyVariableKind::Integer), TyKind::Scalar(Scalar::Uint(_))) => {
37 rhs_ty
38 }
39 // (int, {int}) | (uint, {int})
40 (TyKind::Scalar(Scalar::Int(_)), TyKind::InferenceVar(_, TyVariableKind::Integer))
41 | (TyKind::Scalar(Scalar::Uint(_)), TyKind::InferenceVar(_, TyVariableKind::Integer)) => {
42 lhs_ty
43 }
44 // ({float} | float)
45 (TyKind::InferenceVar(_, TyVariableKind::Float), TyKind::Scalar(Scalar::Float(_))) => {
46 rhs_ty
47 }
48 // (float, {float})
49 (TyKind::Scalar(Scalar::Float(_)), TyKind::InferenceVar(_, TyVariableKind::Float)) => {
50 lhs_ty
51 }
52 // ({int}, {int}) | ({float}, {float})
53 (
54 TyKind::InferenceVar(_, TyVariableKind::Integer),
55 TyKind::InferenceVar(_, TyVariableKind::Integer),
56 )
57 | (
58 TyKind::InferenceVar(_, TyVariableKind::Float),
59 TyKind::InferenceVar(_, TyVariableKind::Float),
60 ) => rhs_ty,
27 _ => TyKind::Error.intern(&Interner), 61 _ => TyKind::Error.intern(&Interner),
28 }, 62 },
29 } 63 }
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 1c1aa491d..89b65fb5f 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -1936,14 +1936,14 @@ fn closure_2() {
1936 84..85 'f': F 1936 84..85 'f': F
1937 84..88 'f(1)': {unknown} 1937 84..88 'f(1)': {unknown}
1938 86..87 '1': i32 1938 86..87 '1': i32
1939 98..99 'g': |u64| -> i32 1939 98..99 'g': |u64| -> {unknown}
1940 102..111 '|v| v + 1': |u64| -> i32 1940 102..111 '|v| v + 1': |u64| -> {unknown}
1941 103..104 'v': u64 1941 103..104 'v': u64
1942 106..107 'v': u64 1942 106..107 'v': u64
1943 106..111 'v + 1': i32 1943 106..111 'v + 1': {unknown}
1944 110..111 '1': i32 1944 110..111 '1': i32
1945 117..118 'g': |u64| -> i32 1945 117..118 'g': |u64| -> {unknown}
1946 117..124 'g(1u64)': i32 1946 117..124 'g(1u64)': {unknown}
1947 119..123 '1u64': u64 1947 119..123 '1u64': u64
1948 134..135 'h': |u128| -> u128 1948 134..135 'h': |u128| -> u128
1949 138..151 '|v| 1u128 + v': |u128| -> u128 1949 138..151 '|v| 1u128 + v': |u128| -> u128