typelevel / scala

Typelevel Scala, a fork of Scala
http://typelevel.org/scala/
372 stars 21 forks source link

Singleton type not inferred correctly #154

Closed tindzk closed 7 years ago

tindzk commented 7 years ago

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
milessabin commented 7 years ago

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.

tindzk commented 7 years ago

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?

milessabin commented 7 years ago

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.

soronpo commented 7 years ago

@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