typelevel/scala

Singleton type not inferred correctly

Closed this issue · 4 comments

This modified example from SI-5103 fails to compile:

$ curl -s https://raw.githubusercontent.com/typelevel/scala/typelevel-readme/try-typelevel-scala.sh | bash
Loading...
Welcome to the Ammonite Repl 0.8.4
(Scala 2.12.2-bin-typelevel-4 Java 1.8.0_112)
If you like Ammonite, please support our development at www.patreon.com/lihaoyi
@ repl.compiler.settings.YliteralTypes.value = true 

@ val x = "one" 
x: String = "one"
@ def single[T <: String with Singleton](x: T) = x 
defined function single
@ single(x) 
cmd3.sc:1: inferred type arguments [String] do not conform to method single's type parameter bounds [T <: String with Singleton]
val res3 = single(x)                                                                                                                                                            
           ^                                                                                                                                                                    
cmd3.sc:1: type mismatch;
 found   : String                                                                                                                                                               
 required: T                                                                                                                                                                    
val res3 = single(x)                                                                                                                                                            
                  ^                                                                                                                                                             
Compilation Failed

That's the expected behaviour.

If you want a val to have an inferred singleton type it should be marked as final. This is consistent between Typelevel and Lightbend Scala.

Thanks! Adding final fixes this particular example. Unfortunately, final vals cannot be used within function definitions.

Do you have any insights as to why vals cannot be inferred when the singleton type is String with Singleton as opposed to Singleton?

You can give the def a literal result type. Bear in mind that a literal type as a result means that the method must be constant so there's no reason (other than side effects, tsk, tsk) not to use a final val here, which might also be inlined.

@tindzk This is one of the reasons I created TwoFace values in the singleton-ops library. They keep their 'final-ness' as long as possible.
https://contributors.scala-lang.org/t/twoface-values-closing-the-gap-between-run-compile-time-functionality/869