Skip to content

Commit 40689d1

Browse files
committed
fix #23261 Handle ConstantType comparison for floating-point 0.0 with sign sensitivity
- Ensure match types distinguish between 0.0 and -0.0 in pattern matching. - This enables accurate reduction in match types involving Double constants.
1 parent a5a7644 commit 40689d1

File tree

3 files changed

+60
-1
lines changed

3 files changed

+60
-1
lines changed

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,13 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
401401
compareErasedValueType
402402
case ConstantType(v2) =>
403403
tp1 match {
404-
case ConstantType(v1) => v1.value == v2.value && recur(v1.tpe, v2.tpe)
404+
case ConstantType(v1) =>
405+
(v1.value, v2.value) match {
406+
// To distinguish 0.0 and -0.0, floating-point numbers use the equals method of their boxing type.
407+
case (d1: Double, d2: Double) => java.lang.Double.valueOf(d1).equals(java.lang.Double.valueOf(d2)) && recur(v1.tpe, v2.tpe)
408+
case (f1: Float, f2: Float) => java.lang.Float.valueOf(f1).equals(java.lang.Float.valueOf(f2)) && recur(v1.tpe, v2.tpe)
409+
case _ => v1.value == v2.value && recur(v1.tpe, v2.tpe)
410+
}
405411
case _ => secondTry
406412
}
407413
case tp2: AnyConstantType =>

tests/neg/i23261.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@main def main(): Unit =
2+
summon[0.0 =:= -0.0]
3+
val d: 0.0 = -0.0
4+
val d2: -0.0 = 0.0
5+
summon[0.0f =:= -0.0f]
6+
val f: 0.0f = -0.0f
7+
val f2: -0.0f = 0.0f

tests/pos/i23261.scala

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
type DoubleToString[D <: Double] <: String = D match
2+
case 0.0 => "0.0"
3+
case -0.0 => "-0.0"
4+
case _ => "_"
5+
6+
type DoubleToString2[D <: Double] <: String = D match
7+
case 0.0 => "0.0"
8+
case _ => "_"
9+
10+
type DoubleToString3[D <: Double] <: String = D match
11+
case -0.0 => "-0.0"
12+
case _ => "_"
13+
14+
type FloatToString[F <: Float] <: String = F match
15+
case 0.0f => "0.0f"
16+
case -0.0f => "-0.0f"
17+
case _ => "_"
18+
19+
type FloatToString2[F <: Float] <: String = F match
20+
case 0.0f => "0.0f"
21+
case _ => "_"
22+
23+
type FloatToString3[F <: Float] <: String = F match
24+
case -0.0f => "-0.0f"
25+
case _ => "_"
26+
27+
@main def main(): Unit = {
28+
summon[0.0 =:= 0.0]
29+
summon[-0.0 =:= -0.0]
30+
summon[DoubleToString[0.0] =:= "0.0"]
31+
summon[DoubleToString[-0.0] =:= "-0.0"]
32+
summon[DoubleToString[3.14] =:= "_"]
33+
summon[DoubleToString2[0.0] =:= "0.0"]
34+
summon[DoubleToString2[-0.0] =:= "_"]
35+
summon[DoubleToString3[-0.0] =:= "-0.0"]
36+
summon[DoubleToString3[0.0] =:= "_"]
37+
summon[0.0f =:= 0.0f]
38+
summon[-0.0f =:= -0.0f]
39+
summon[FloatToString[0.0f] =:= "0.0f"]
40+
summon[FloatToString[-0.0f] =:= "-0.0f"]
41+
summon[FloatToString[3.14f] =:= "_"]
42+
summon[FloatToString2[0.0f] =:= "0.0f"]
43+
summon[FloatToString2[-0.0f] =:= "_"]
44+
summon[FloatToString3[-0.0f] =:= "-0.0f"]
45+
summon[FloatToString3[0.0f] =:= "_"]
46+
}

0 commit comments

Comments
 (0)