1

In Scala REPL I can use Seq[String]() as a default value for a parameter of type Seq[T].

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def d[T](foo: Seq[T] = Seq[String]()) = 12
d: [T](foo: Seq[T])Int

scala> d()
res0: Int = 12

Trying the same in IDEA, it complains “Seq[String] doesn't conform to expected type Seq[T]”. Why?

Screenshot of IDEA complaining about a type problem for parameter default values

  • IntelliJ IDEA 2016.2.4
  • Scala Plugin 2016.2.1
  • Scala 2.11.7

Note 1: Sorry, I know that my example function does not make much sense. However, my real (and useful) function is unnecessarily complex to post it here.

Note 2: At first, instead of type T my type name in the example was Any which was not a good idea (because it shadowed scala.Any) and caused some confusion. Thus I fixed that.

Marcus
  • 1,857
  • 4
  • 22
  • 44
  • I tried the same code in eclipse with same scala version. To my surprise, i'm not getting any error – Balaji Reddy Oct 20 '16 at 08:02
  • 1
    Strangely enough, If I copy-paste your piece of code in IntelliJ, i have the same red underlined text. But the compilation process is just fine. I guess it's a bug in IntelliJ Scala plugin, that's it. – Polentino Oct 20 '16 at 08:12
  • 1
    It is indeed a bug in IntelliJ Scala plugin type conformance. I've created an issue: https://youtrack.jetbrains.com/issue/SCL-10892 – Justin Kaeser Oct 25 '16 at 13:23

1 Answers1

1

When you say def d[Any], the Any here is a generic place holder. It does not point to class Any in scala. It basically shadows the Any class defined globally in scala. So, when you assign Seq[String] to Seq[Any], the compiler does not know any relation between String and Any. Note that Any could be replaced with any character / word as generic place holder. The result would be the same.

Now coming, to why this works in REPL, I am not exactly sure why REPL accepts if Seq[String] when given as a default value, but I was able to reproduce the error in repl when I do the same operation inside the method body.

The following code in REPL throws error:

def d[Any](foo: Seq[Any]) = {
  val a: Seq[Any] = Seq[String]()
}
<console>:12: error: type mismatch;
found   : Seq[String]
required: Seq[Any]
       val a: Seq[Any] = Seq[String]()
                                    ^

I am not sure why REPL was not able to catch the error while given as a default argument.

One alternative theory is, in general when you use generics, the value of the type will be determined based on the caller. For example,

def d[A](a:A) = {}
d(1) // Type of A is Int
d("a") // Type of A is String

So, when you give default value, it assigns the value of String to Any. hence the compilation success.Intellij's Type Checker works based on the first theory and shows an error. But strangely as someone pointed out earlier, the compilation succeeds.

Aravindh S
  • 1,185
  • 11
  • 19
  • @BalajiReddy As I said, it might be how Intellij Idea's Type Checker works. Eclipse might have gotten it right. Also since both REPL & Scala IDE for eclipse are implemented by the developers of Scala, it seems to be the right approach. So this makes me conclude that the second theory I had mentioned is the exact answer. – Aravindh S Oct 20 '16 at 08:30
  • 1
    `Seq` is covariant. Which means `Seq[+A]` can accept subclasses of `A` in the sequence. The doesnt mean `Seq[String]` matches `Seq[T]`. You cant confirm this unless `T` is related to `String`. Even `List` is covariant. As far as I understand Intellij will show error even when you use `def d[T](foo: Seq[T] = Seq[String]()) = { }`. But will compile successfully. I guess the answer is a bug with intellij's type checker. It would help you change your question to `def d[T](foo: Seq[T] = Seq[String]()) = { }` to avoid confusion between the class `Any` defined in scala and the type parameter. – Aravindh S Oct 20 '16 at 08:59
  • Though `Seq[String]()` matches `Seq[Any]`. But you are right. It's not scala.Any in my def example. Thus I replaced Any by T. – Marcus Oct 20 '16 at 09:07
  • So ultimately it’ simply a bug in IDEA Scala Plugin. Thanks for helping me to understand (and improve) my code :) – Marcus Oct 20 '16 at 09:20
  • I am not confirming it is a bug in Idea. Its better to raise a bug in their bug tracker. But based on the behaviour, it seems so. – Aravindh S Oct 20 '16 at 09:21