Open
Description
Compiler version
Scala 3.7.0
(Confirmed with both sbt and Scala CLI)
Minimized code
type DoubleToString[D <: Double] <: String = D match
case 0.0 => "0.0"
case _ => "_"
@main def main(): Unit =
summon[DoubleToString[0.0] =:= "0.0"]
summon[DoubleToString[-0.0] =:= "0.0"]
summon[DoubleToString[-0.0] =:= "_"]
Compilation output
[error] -- [E172] Type Error: src/main/scala/Main.scala:7:40
[error] 7 | summon[DoubleToString[-0.0] =:= "0.0"]
[error] | ^
[error] | Cannot prove that DoubleToString[(-0.0d : Double)] =:= ("0.0" : String).
[error] |
[error] | Note: a match type could not be fully reduced:
[error] | trying to reduce DoubleToString[(-0.0d : Double)]
[error] | failed since selector (-0.0d : Double)
[error] | is uninhabited (there are no values of that type).
[error] -- [E172] Type Error: src/main/scala/Main.scala:8:38
[error] 8 | summon[DoubleToString[-0.0] =:= "_"]
[error] | ^
[error] | Cannot prove that DoubleToString[(-0.0d : Double)] =:= ("_" : String).
[error] | Note: a match type could not be fully reduced:
[error] | trying to reduce DoubleToString[(-0.0d : Double)]
[error] | failed since selector (-0.0d : Double)
[error] | is uninhabited (there are no values of that type).
Problem description
In Scala 3.7.0, match types cannot distinguish or unify 0.0
and -0.0
, even though:
0.0d == -0.0d
holds at runtime- Using
=:=
on the type level compiles successfully:summon[0.0 =:= -0.0]
works
However, in match types, writing case 0.0 =>
causes -0.0
to be rejected as an uninhabited selector.
Switching to case -0.0 =>
then rejects 0.0
.
This suggests that match types are not treating 0.0d
and -0.0d
as equivalent constant values, which is inconsistent with how =:=
treats them.
Expected behavior
Match types on Double
constants should not distinguish 0.0
and -0.0
, just as =:=
does not.