Skip to content

Match types do not treat 0.0d and -0.0d as equivalent constants #23261

Open
@kijuky

Description

@kijuky

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions