diff options
author | Lukas Wirth <[email protected]> | 2021-04-10 15:56:32 +0100 |
---|---|---|
committer | Lukas Wirth <[email protected]> | 2021-04-10 15:56:32 +0100 |
commit | 252eb78dc3852707969b27b8a30f8844289aa985 (patch) | |
tree | 5bb3f755bd5d154233758a63122817381e3b66d1 /crates/hir_ty | |
parent | e357b6bb36828ecf3404fcc382da09216eef0997 (diff) |
Implement more precise binary op return type prediction
Diffstat (limited to 'crates/hir_ty')
-rw-r--r-- | crates/hir_ty/src/op.rs | 58 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 10 |
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 |