Compilation error, literal types

My sbt file is:

val scala3Version = "3.0.0"

lazy val root = project
  .in(file("."))
  .settings(
    name := "scala-3-advanced",
    version := "0.1.0",

    scalaVersion := scala3Version,

    libraryDependencies ++= Seq(
      "com.novocode" % "junit-interface" % "0.11" % "test",
      "org.scala-lang.modules" %% "scala-parallel-collections" % "1.0.3"
    )
  )

And the scala code is:

package jk.p5

object CompilerError {

  def main(args: Array[String]): Unit = {
    println(s"Class: ${getClass.getSimpleName} Main thread running: ${Thread.currentThread().getName}")

    val pi: 3.14 = 3.14
    println(pi)
    val pi2: 3.14 = 123 // Compiles OK ???
    println(pi2)
    // Prints 3.14 ???
  }
}

Output of this program is:

[info] running jk.p5.CompilerError 
Class: CompilerError$ Main thread running: run-main-3
3.14
3.14
[success] Total time: 12 s, completed Jan 4, 2022, 6:27:57 PM

What is wrong here? In my mind the line

val pi2: 3.14 = 123 // Compiles OK ???

should cause compile error, but it compiles fine.

Thank you for your support!

I didn’t realize that there were types for double literals as well as integers, but I had a REPL up with Scala 3.1.0 and tried the following. Any chance this is 3.0.0 specific and has been fixed?

scala> val pi:3.14 = 3.14
val pi: 3.14 = 3.14
                                                                                
scala> println(pi)
3.14
                                                                                
scala> val pi2:3.14 = 123
-- Error:
1 |val pi2:3.14 = 123
  |               ^^^
  |               Found:    (123 : Int)
  |               Required: (3.14d : Double)

You are right, I tried Scala 3.1.0 and compilation fails:

[error] -- [E007] Type Mismatch Error: /home/jk/workspace/scala-3-advanced/src/main/scala/jk/p5/LiteralUnionIntersectionTypes.scala:26:19 
[error] 26 |    val pi: 3.14 = 123
[error]    |                   ^^^
[error]    |                   Found:    (123 : Int)
[error]    |                   Required: (3.14d : Double)

Now I don’t know what to think:

➜  ~ sdk use scala 3.0.0

Using scala version 3.0.0 in this shell.
➜  ~ scala
scala> val pi: 3.14 = 1.7
1 |val pi: 3.14 = 1.7
  |               ^^^
  |               Found:    (1.7d : Double)
  |               Required: (3.14d : Double)

and also in my terminal window

➜  ~ sdk use scala 3.0.0

Using scala version 3.0.0 in this shell.
➜  ~ scala
scala> val pi: 3.14 = 42
val pi: 3.14 = 42.0

Oh I see, it was ignoring the “harmonized” int literal.

It’s also interesting that the REPL is not showing the value of pi with its definition:

scala> val pi: 3.14 = 42
val pi: 3.14 = 42.0

scala> pi
val res2: Double = 3.14

I expected 3.14 not 42.0, if that is the value of pi after definition. Maybe the scala 3 REPL is trying to show your definition, in the interest of fidelity. Oh, it seems 42.0 is stored in the field, but it’s not used in res2, which only has to report the value that inhabits the literal type!

The fix is in 3.0.1, which has a fix for constant folding, so maybe this was involved.

3 Likes