typelevel / scala

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

Singleton default parameters #153

Closed tindzk closed 6 years ago

tindzk commented 7 years ago

There seems to be a problem with handling default parameters that are singleton values:

$ 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  

@ case class Tag[T <: Singleton](a: T) 
defined class Tag
@ Tag("a").copy() 
cmd2.sc:1: type mismatch;
 found   : String                                                                                                                                                               
 required: "a"                                                                                                                                                                  
val res2 = Tag("a").copy()                                                                                                                                                      
                    ^                                                                                                                                                           
Compilation Failed

This works as expected:

@ Tag("a").copy(a = "b") 
res2: Tag[b] = Tag("b")
tindzk commented 7 years ago

Here is another failure case where a class cannot be initialised when a parameter is omitted:

@ case class Wrap[T <: Singleton](a: String with T,
                                  b: Map[String, Any] = Map.empty,
                                  c: List[String]     = List.empty) 
defined class Wrap
@  
@ Wrap("div") 
res2: Wrap[div] = Wrap("div", Map(), List())
@ Wrap("div", c = List.empty) 
cmd3.sc:1: type mismatch;
 found   : String                                                                                                                                                                       
 required: String with "div"                                                                                                                                                            
Error occurred in an application involving default arguments.                                                                                                                           
val res3 = Wrap("div", c = List.empty)                                                                                                                                                  
                ^                                                                                                                                                                       
Compilation Failed
soronpo commented 7 years ago

Similar behavior in dotty: https://scastie.scala-lang.org/Yv0JU7ETRMWAHFa4zKc5RQ

Why not write? case class Tag[T <: String with Singleton](a: T)

milessabin commented 6 years ago

The issue is that a is being widened on access, and this interferes with copy. I think this should probably be fixed in the synthesis of copy, but it can be worked around by preventing the widening more generally,

scala> case class Tag[T <: String with Singleton](a: T {})
defined class Tag                                                                                                                           

scala> Tag("a").copy()                                                                                                                      
res0: Tag["a"] = Tag(a)
milessabin commented 6 years ago

Fixed in https://github.com/milessabin/scala/commit/78111f228cdeb8e93da66ba9f214c498f3e1cfb9.