Open
Description
import scala.language.experimental.modularity
class Box1[T <: Singleton](val x: T)
class Box2[T : Singleton](val x: T)
def id(x: Int): x.type = x
def readInt(): Int = ???
def Test = ()
val x /*: Box1[(?1 : Int) | (?2 : Int)]*/ = Box1(id(readInt()))
val y = Box2(id(readInt())) // error: Failed to synthesize an instance of type
// Singleton{type Self = (?1 : Int) | (?2 : Int)}:
// (?1 : Int) | (?2 : Int) is not a singleton
sbt:scala3> scalac -Xprint-types -Xprint:typer tests/pos/singleton-skolem.scala
...
val x: Box1[(<?3:Int> : Int) | (<?4:Int> : Int)] =
<
<<<new Box1:Box1>:([T <: Singleton](x: T): Box1[T])>[
(<?3:Int> : Int) | (<?4:Int> : Int)]:
((x: (<?3:Int> : Int) | (<?4:Int> : Int)):
Box1[(<?3:Int> : Int) | (<?4:Int> : Int)])
>
(<<id:((x: Int): x.type)>(<<readInt:((): Int)>():Int>):(<?4:Int> : Int)>):
Box1[(<?3:Int> : Int) | (<?4:Int> : Int)]>
...
id(readInt())
gets a skolem type (?4: Int)
as expected.
But then the type argument of Box1
is inferred to be (?3: Int) | (?4: Int)
. I don't understand where (?3: Int) |
comes from. I would expect it to just be (?4: Int)
Compiler version: 8598403.
Same behavior since 3.0:
class Box1[T <: Singleton](val x: T)
def id(x: Int): x.type = x
def readInt(): Int = ???
def Test = ()
val x /*: Box1[(?1 : Int) | (?2 : Int)]*/ = Box1(id(readInt()))
$ scala compile -S 3.0 --server=false -Xprint:typer tests/pos/singleton-skolem.scala
...
val x: Box1[(?1 : Int) | (?2 : Int)] = new Box1[((?1 : Int) | (?2 : Int))](id(readInt()))
...