Skip to content

Commit 252eb78

Browse files
committed
Implement more precise binary op return type prediction
1 parent e357b6b commit 252eb78

File tree

2 files changed

+51
-17
lines changed

2 files changed

+51
-17
lines changed

crates/hir_ty/src/op.rs

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,55 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
99
BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
1010
BinaryOp::Assignment { .. } => TyBuilder::unit(),
1111
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),
1315
TyKind::Scalar(Scalar::Int(_))
14-
| TyKind::Scalar(Scalar::Uint(_))
15-
| TyKind::Scalar(Scalar::Float(_)) => lhs_ty,
16-
TyKind::InferenceVar(_, TyVariableKind::Integer)
17-
| TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
18-
_ => TyKind::Error.intern(&Interner),
16+
| TyKind::Scalar(Scalar::Uint(_))
17+
| TyKind::InferenceVar(_, TyVariableKind::Integer)
18+
) && matches!(
19+
rhs_ty.kind(&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)
1927
}
2028
}
21-
BinaryOp::ArithOp(_) => match rhs_ty.kind(&Interner) {
22-
TyKind::Scalar(Scalar::Int(_))
23-
| TyKind::Scalar(Scalar::Uint(_))
24-
| TyKind::Scalar(Scalar::Float(_)) => rhs_ty,
25-
TyKind::InferenceVar(_, TyVariableKind::Integer)
26-
| TyKind::InferenceVar(_, TyVariableKind::Float) => rhs_ty,
29+
BinaryOp::ArithOp(_) => match (lhs_ty.kind(&Interner), rhs_ty.kind(&Interner)) {
30+
// (int, int) | (uint, uint) | (float, float)
31+
(TyKind::Scalar(Scalar::Int(_)), TyKind::Scalar(Scalar::Int(_)))
32+
| (TyKind::Scalar(Scalar::Uint(_)), TyKind::Scalar(Scalar::Uint(_)))
33+
| (TyKind::Scalar(Scalar::Float(_)), TyKind::Scalar(Scalar::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,
2761
_ => TyKind::Error.intern(&Interner),
2862
},
2963
}

crates/hir_ty/src/tests/traits.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1936,14 +1936,14 @@ fn closure_2() {
19361936
84..85 'f': F
19371937
84..88 'f(1)': {unknown}
19381938
86..87 '1': i32
1939-
98..99 'g': |u64| -> i32
1940-
102..111 '|v| v + 1': |u64| -> i32
1939+
98..99 'g': |u64| -> {unknown}
1940+
102..111 '|v| v + 1': |u64| -> {unknown}
19411941
103..104 'v': u64
19421942
106..107 'v': u64
1943-
106..111 'v + 1': i32
1943+
106..111 'v + 1': {unknown}
19441944
110..111 '1': i32
1945-
117..118 'g': |u64| -> i32
1946-
117..124 'g(1u64)': i32
1945+
117..118 'g': |u64| -> {unknown}
1946+
117..124 'g(1u64)': {unknown}
19471947
119..123 '1u64': u64
19481948
134..135 'h': |u128| -> u128
19491949
138..151 '|v| 1u128 + v': |u128| -> u128

0 commit comments

Comments
 (0)