scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
230 stars 21 forks source link

`java.lang.Boolean.TRUE` doesn't conform to the instance type `java.lang.Boolean.TRUE.type` in function parameters #12901

Open unkarjedy opened 7 months ago

unkarjedy commented 7 months ago

Scala 2.13.12

Example:

class Key[T] {}

object example {
  private val Key: Key[java.lang.Boolean.TRUE.type] = new Key[java.lang.Boolean.TRUE.type]

  def putUserData[T](key: Key[T], value: T): Unit = ???

  def main(args: Array[String]): Unit = {
    //OK: compiles fine
    val value: java.lang.Boolean.TRUE.type = java.lang.Boolean.TRUE
    val option: Option[java.lang.Boolean.TRUE.type] = Option(java.lang.Boolean.TRUE)

    //Error: found: Boolean, required: Boolean.TRUE.type
    putUserData(Key, java.lang.Boolean.TRUE)
  }
}

The code compiles with error at line 14

type mismatch;
 found   : Boolean
 required: Boolean.TRUE.type
    putUserData(Key, java.lang.Boolean.TRUE)

Note that it compiles fine in Scala 3.3.1

unkarjedy commented 7 months ago

java.lang.Boolean.TRUE might be used just as some marker for some API. In Scala Plugin we have several places where it is actual, though not critical

som-snytt commented 7 months ago

Scala 2 types the arg as java.lang.Boolean.

[log typer] infer method inst example.this.putUserData[T], tparams = List(type T), args = List(<empty>.this.Key[Boolean.TRUE.type], lang.this.Boolean), pt = scala.this.Unit, lobounds = List(scala.this.Nothing), parambounds = List()

so it gets T correct

example.this.putUserData[Boolean.TRUE.type](example.this.Key, java.lang.Boolean.<TRUE: error>)

The example works in Scala 2 if

class Key[+T]

Dotty is more patient. Presumably it's not widening the arg. (I can't tell by looking.)

    private[this] val Key: Key[java.lang.Boolean.TRUE.type] = new Key[java.lang.Boolean.TRUE.type]()
    def putUserData[T >: Nothing <: Any](key: Key[T], value: T): Unit = ()
    def main(args: Array[String]): Unit =
      {
        val value: java.lang.Boolean.TRUE.type = java.lang.Boolean.TRUE
        val option: Option[java.lang.Boolean.TRUE.type] = Option.apply[(Boolean.TRUE : Boolean)](java.lang.Boolean.TRUE)
        example.putUserData[(Boolean.TRUE : Boolean)](example.Key, java.lang.Boolean.TRUE)
      }
unkarjedy commented 7 months ago

The example works in Scala 2 if class Key[+T]

Unfortunately, the original Key definition in our case code is in a Java library (IntelliJ IDEA SDK)

SethTisue commented 5 months ago

(Perhaps this is obvious and/or pedantic, but for the record: this is a type inference issue (not conformance), and the workaround is to explicitly supply the type parameter.)

som-snytt commented 5 months ago

This may be a pedantic nitpick, but

The code compiles with error at line 14

should say that it does not compile.

Also pedantically, it infers the correct type argument (the singleton) but then "widens" the type of the argument written by the user. So although inference is implicated, I would characterize this as a bug and not a limitation.

Literal works:

    putUserData(null.asInstanceOf[Key[42]], 42) // or true

Too outré.

    putUserData(Key, java.lang.Boolean.TRUE: java.lang.Boolean.TRUE.type) // or any x.type

Either of these work:

    putUserData(Key, value) // value is the singleton type as shown above
    putUserData[java.lang.Boolean.TRUE.type](Key, java.lang.Boolean.TRUE)